Initial Contribution
diff --git a/awt/java/awt/AWTEvent.java b/awt/java/awt/AWTEvent.java
new file mode 100644
index 0000000..1ed9a37
--- /dev/null
+++ b/awt/java/awt/AWTEvent.java
@@ -0,0 +1,618 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Dmitry A. Durnev, Michael Danilov
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.util.EventObject;
+import java.util.Hashtable;
+import java.util.EventListener;
+
+import java.awt.event.*;
+
+/**
+ * The abstract AWT events is base class for all AWT events. 
+ * This class and its subclasses supercede the original java.awt.Event class.
+ */
+public abstract class AWTEvent extends EventObject {
+    
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = -1825314779160409405L;
+
+    /** The Constant COMPONENT_EVENT_MASK indicates the event relates to a component. */
+    public static final long COMPONENT_EVENT_MASK = 1;
+
+    /** The Constant CONTAINER_EVENT_MASK indicates the event relates to a container. */
+    public static final long CONTAINER_EVENT_MASK = 2;
+
+    /** The Constant FOCUS_EVENT_MASK indicates the event relates to the focus. */
+    public static final long FOCUS_EVENT_MASK = 4;
+
+    /** The Constant KEY_EVENT_MASK indicates the event relates to a key. */
+    public static final long KEY_EVENT_MASK = 8;
+
+    /** The Constant MOUSE_EVENT_MASK indicates the event relates to the mouse. */
+    public static final long MOUSE_EVENT_MASK = 16;
+
+    /** The Constant MOUSE_MOTION_EVENT_MASK indicates the event relates to a mouse motion. */
+    public static final long MOUSE_MOTION_EVENT_MASK = 32;
+
+    /** The Constant WINDOW_EVENT_MASK indicates the event relates to a window. */
+    public static final long WINDOW_EVENT_MASK = 64;
+
+    /** The Constant ACTION_EVENT_MASK indicates the event relates to an action. */
+    public static final long ACTION_EVENT_MASK = 128;
+
+    /** The Constant ADJUSTMENT_EVENT_MASK indicates the event relates to an adjustment. */
+    public static final long ADJUSTMENT_EVENT_MASK = 256;
+
+    /** The Constant ITEM_EVENT_MASK indicates the event relates to an item. */
+    public static final long ITEM_EVENT_MASK = 512;
+
+    /** The Constant TEXT_EVENT_MASK indicates the event relates to text. */
+    public static final long TEXT_EVENT_MASK = 1024;
+
+    /** The Constant INPUT_METHOD_EVENT_MASK indicates the event relates to an input method. */
+    public static final long INPUT_METHOD_EVENT_MASK = 2048;
+
+    /** The Constant PAINT_EVENT_MASK indicates the event relates to a paint method. */
+    public static final long PAINT_EVENT_MASK = 8192;
+
+    /** The Constant INVOCATION_EVENT_MASK indicates the event relates to a method invocation. */
+    public static final long INVOCATION_EVENT_MASK = 16384;
+
+    /** The Constant HIERARCHY_EVENT_MASK indicates the event relates to a hierarchy. */
+    public static final long HIERARCHY_EVENT_MASK = 32768;
+
+    /** 
+     * The Constant HIERARCHY_BOUNDS_EVENT_MASK indicates the event relates to hierarchy bounds.
+     */
+    public static final long HIERARCHY_BOUNDS_EVENT_MASK = 65536;
+
+    /** The Constant MOUSE_WHEEL_EVENT_MASK indicates the event relates to the mouse wheel. */
+    public static final long MOUSE_WHEEL_EVENT_MASK = 131072;
+
+    /** The Constant WINDOW_STATE_EVENT_MASK indicates the event relates to a window state. */
+    public static final long WINDOW_STATE_EVENT_MASK = 262144;
+
+    /** The Constant WINDOW_FOCUS_EVENT_MASK indicates the event relates to a window focus. */
+    public static final long WINDOW_FOCUS_EVENT_MASK = 524288;
+
+    /** The Constant RESERVED_ID_MAX indicates the maximum value for reserved 
+     * AWT event IDs.
+     */
+    public static final int RESERVED_ID_MAX = 1999;
+
+    /** The Constant eventsMap. */
+    private static final Hashtable<Integer, EventDescriptor> eventsMap = new Hashtable<Integer, EventDescriptor>();
+
+    /** The converter. */
+    private static EventConverter converter;
+
+    /** The ID of the event. */
+    protected int id;
+
+    /** 
+     * The consumed indicates whether or not the event is sent back down to 
+     * the peer once the source has processed it (false means it's sent to the peer,
+     * true means it's not).
+     */ 
+    protected boolean consumed;
+
+    /** The dispatched by kfm. */
+    boolean dispatchedByKFM;
+    
+    /** The is posted. */
+    transient boolean isPosted;
+
+    static {
+        eventsMap.put(new Integer(KeyEvent.KEY_TYPED),
+                new EventDescriptor(KEY_EVENT_MASK, KeyListener.class));
+        eventsMap.put(new Integer(KeyEvent.KEY_PRESSED),
+                new EventDescriptor(KEY_EVENT_MASK, KeyListener.class));
+        eventsMap.put(new Integer(KeyEvent.KEY_RELEASED),
+                new EventDescriptor(KEY_EVENT_MASK, KeyListener.class));
+        eventsMap.put(new Integer(MouseEvent.MOUSE_CLICKED),
+                new EventDescriptor(MOUSE_EVENT_MASK, MouseListener.class));
+        eventsMap.put(new Integer(MouseEvent.MOUSE_PRESSED),
+                new EventDescriptor(MOUSE_EVENT_MASK, MouseListener.class));
+        eventsMap.put(new Integer(MouseEvent.MOUSE_RELEASED),
+                new EventDescriptor(MOUSE_EVENT_MASK, MouseListener.class));
+        eventsMap.put(new Integer(MouseEvent.MOUSE_MOVED),
+                new EventDescriptor(MOUSE_MOTION_EVENT_MASK, MouseMotionListener.class));
+        eventsMap.put(new Integer(MouseEvent.MOUSE_ENTERED),
+                new EventDescriptor(MOUSE_EVENT_MASK, MouseListener.class));
+        eventsMap.put(new Integer(MouseEvent.MOUSE_EXITED),
+                new EventDescriptor(MOUSE_EVENT_MASK, MouseListener.class));
+        eventsMap.put(new Integer(MouseEvent.MOUSE_DRAGGED),
+                new EventDescriptor(MOUSE_MOTION_EVENT_MASK, MouseMotionListener.class));
+        eventsMap.put(new Integer(MouseEvent.MOUSE_WHEEL),
+                new EventDescriptor(MOUSE_WHEEL_EVENT_MASK, MouseWheelListener.class));
+        eventsMap.put(new Integer(ComponentEvent.COMPONENT_MOVED),
+                new EventDescriptor(COMPONENT_EVENT_MASK, ComponentListener.class));
+        eventsMap.put(new Integer(ComponentEvent.COMPONENT_RESIZED),
+                new EventDescriptor(COMPONENT_EVENT_MASK, ComponentListener.class));
+        eventsMap.put(new Integer(ComponentEvent.COMPONENT_SHOWN),
+                new EventDescriptor(COMPONENT_EVENT_MASK, ComponentListener.class));
+        eventsMap.put(new Integer(ComponentEvent.COMPONENT_HIDDEN),
+                new EventDescriptor(COMPONENT_EVENT_MASK, ComponentListener.class));
+        eventsMap.put(new Integer(FocusEvent.FOCUS_GAINED),
+                new EventDescriptor(FOCUS_EVENT_MASK, FocusListener.class));
+        eventsMap.put(new Integer(FocusEvent.FOCUS_LOST),
+                new EventDescriptor(FOCUS_EVENT_MASK, FocusListener.class));
+        eventsMap.put(new Integer(PaintEvent.PAINT),
+                new EventDescriptor(PAINT_EVENT_MASK, null));
+        eventsMap.put(new Integer(PaintEvent.UPDATE),
+                new EventDescriptor(PAINT_EVENT_MASK, null));
+        eventsMap.put(new Integer(WindowEvent.WINDOW_OPENED),
+                new EventDescriptor(WINDOW_EVENT_MASK, WindowListener.class));
+        eventsMap.put(new Integer(WindowEvent.WINDOW_CLOSING),
+                new EventDescriptor(WINDOW_EVENT_MASK, WindowListener.class));
+        eventsMap.put(new Integer(WindowEvent.WINDOW_CLOSED),
+                new EventDescriptor(WINDOW_EVENT_MASK, WindowListener.class));
+        eventsMap.put(new Integer(WindowEvent.WINDOW_DEICONIFIED),
+                new EventDescriptor(WINDOW_EVENT_MASK, WindowListener.class));
+        eventsMap.put(new Integer(WindowEvent.WINDOW_ICONIFIED),
+                new EventDescriptor(WINDOW_EVENT_MASK, WindowListener.class));
+        eventsMap.put(new Integer(WindowEvent.WINDOW_STATE_CHANGED),
+                new EventDescriptor(WINDOW_STATE_EVENT_MASK, WindowStateListener.class));
+        eventsMap.put(new Integer(WindowEvent.WINDOW_LOST_FOCUS),
+                new EventDescriptor(WINDOW_FOCUS_EVENT_MASK, WindowFocusListener.class));
+        eventsMap.put(new Integer(WindowEvent.WINDOW_GAINED_FOCUS),
+                new EventDescriptor(WINDOW_FOCUS_EVENT_MASK, WindowFocusListener.class));
+        eventsMap.put(new Integer(WindowEvent.WINDOW_DEACTIVATED),
+                new EventDescriptor(WINDOW_EVENT_MASK, WindowListener.class));
+        eventsMap.put(new Integer(WindowEvent.WINDOW_ACTIVATED),
+                new EventDescriptor(WINDOW_EVENT_MASK, WindowListener.class));
+        eventsMap.put(new Integer(HierarchyEvent.HIERARCHY_CHANGED),
+                new EventDescriptor(HIERARCHY_EVENT_MASK, HierarchyListener.class));
+        eventsMap.put(new Integer(HierarchyEvent.ANCESTOR_MOVED),
+                new EventDescriptor(HIERARCHY_BOUNDS_EVENT_MASK, HierarchyBoundsListener.class));
+        eventsMap.put(new Integer(HierarchyEvent.ANCESTOR_RESIZED),
+                new EventDescriptor(HIERARCHY_BOUNDS_EVENT_MASK, HierarchyBoundsListener.class));
+        eventsMap.put(new Integer(ContainerEvent.COMPONENT_ADDED),
+                new EventDescriptor(CONTAINER_EVENT_MASK, ContainerListener.class));
+        eventsMap.put(new Integer(ContainerEvent.COMPONENT_REMOVED),
+                new EventDescriptor(CONTAINER_EVENT_MASK, ContainerListener.class));
+        eventsMap.put(new Integer(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED),
+                new EventDescriptor(INPUT_METHOD_EVENT_MASK, InputMethodListener.class));
+        eventsMap.put(new Integer(InputMethodEvent.CARET_POSITION_CHANGED),
+                new EventDescriptor(INPUT_METHOD_EVENT_MASK, InputMethodListener.class));
+        eventsMap.put(new Integer(InvocationEvent.INVOCATION_DEFAULT),
+                new EventDescriptor(INVOCATION_EVENT_MASK, null));
+        eventsMap.put(new Integer(ItemEvent.ITEM_STATE_CHANGED),
+                new EventDescriptor(ITEM_EVENT_MASK, ItemListener.class));
+        eventsMap.put(new Integer(TextEvent.TEXT_VALUE_CHANGED),
+                new EventDescriptor(TEXT_EVENT_MASK, TextListener.class));
+        eventsMap.put(new Integer(ActionEvent.ACTION_PERFORMED),
+                new EventDescriptor(ACTION_EVENT_MASK, ActionListener.class));
+        eventsMap.put(new Integer(AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED),
+                new EventDescriptor(ADJUSTMENT_EVENT_MASK, AdjustmentListener.class));
+        converter = new EventConverter();
+    }
+    
+    /**
+     * Instantiates a new AWT event from the specified Event object.
+     * 
+     * @param event the Event object.
+     */
+    public AWTEvent(Event event) {
+        this(event.target, event.id);
+    }
+
+    /**
+     * Instantiates a new AWT event with the specified object and type.
+     * 
+     * @param source the source Object.
+     * @param id the event's type.
+     */
+    public AWTEvent(Object source, int id) {
+        super(source);
+        this.id = id;
+        consumed = false;
+    }
+
+    /**
+     * Gets the event's type.
+     * 
+     * @return the event type ID.
+     */
+    public int getID() {
+        return id;
+    }
+
+    /**
+     * Sets a new source for the AWTEvent.
+     * 
+     * @param newSource the new source Object for the AWTEvent.
+     */
+    public void setSource(Object newSource) {
+        source = newSource;
+    }
+
+    /**
+     * Returns a String representation of the AWTEvent.
+     * 
+     * @return the String representation of the AWTEvent.
+     */
+    @Override
+    public String toString() {
+        /* The format is based on 1.5 release behavior 
+         * which can be revealed by the following code:
+         * 
+         * AWTEvent event = new AWTEvent(new Component(){}, 1){};
+         * System.out.println(event);
+         */
+        String name = ""; //$NON-NLS-1$
+        
+        if (source instanceof Component && (source != null)) {
+            Component comp = (Component) getSource();
+            name = comp.getName();
+            if (name == null) {
+                name = ""; //$NON-NLS-1$
+            }
+        }
+        
+        return (getClass().getName() + "[" + paramString() + "]" //$NON-NLS-1$ //$NON-NLS-2$
+                + " on " + (name.length() > 0 ? name : source)); //$NON-NLS-1$
+    }
+
+    /**
+     * Returns a string representation of the AWTEvent state. 
+     *  
+     * @return a string representation of the AWTEvent state.
+     */
+    public String paramString() {
+        //nothing to implement: all event types must override this method
+        return ""; //$NON-NLS-1$
+    }
+
+    /**
+     * Checks whether or not this AWTEvent has been consumed.
+     * 
+     * @return true, if this AWTEvent has been consumed, false otherwise.
+     */
+    protected boolean isConsumed() {
+        return consumed;
+    }
+
+    /**
+     * Consumes the AWTEvent.
+     */
+    protected void consume() {
+       consumed = true;
+    }
+
+    /**
+     * Convert AWTEvent object to a corresponding (deprecated) Event object.
+     * 
+     * @return new Event object which is a converted AWTEvent object or null
+     * if the conversion is not possible
+     */
+    Event getEvent() {
+        
+        if (id == ActionEvent.ACTION_PERFORMED) {
+            ActionEvent ae = (ActionEvent) this;
+            return converter.convertActionEvent(ae);
+
+        } else if (id == AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED) {
+            AdjustmentEvent ae = (AdjustmentEvent) this;
+            return converter.convertAdjustmentEvent(ae);
+
+//???AWT
+//        } else if (id == ComponentEvent.COMPONENT_MOVED
+//                && source instanceof Window) {
+//            //the only type of Component events is COMPONENT_MOVED on window
+//            ComponentEvent ce = (ComponentEvent) this;
+//            return converter.convertComponentEvent(ce);
+
+        } else if (id >= FocusEvent.FOCUS_FIRST && id <= FocusEvent.FOCUS_LAST) {
+            //nothing to convert
+
+//???AWT
+//        } else if (id == ItemEvent.ITEM_STATE_CHANGED) {
+//            ItemEvent ie = (ItemEvent) this;
+//            return converter.convertItemEvent(ie);
+
+        } else if (id == KeyEvent.KEY_PRESSED || id == KeyEvent.KEY_RELEASED) {
+            KeyEvent ke = (KeyEvent) this;
+            return converter.convertKeyEvent(ke);
+        } else if (id >= MouseEvent.MOUSE_FIRST && id <= MouseEvent.MOUSE_LAST) {
+            MouseEvent me = (MouseEvent) this;
+            return converter.convertMouseEvent(me);
+        } else if (id == WindowEvent.WINDOW_CLOSING
+                || id == WindowEvent.WINDOW_ICONIFIED
+                || id == WindowEvent.WINDOW_DEICONIFIED) {
+            //nothing to convert
+        } else {
+            return null;
+        }
+        return new Event(source, id, null);
+    }
+
+
+    /**
+     * The Class EventDescriptor.
+     */
+    static final class EventDescriptor {
+
+        /** The event mask. */
+        final long eventMask;
+
+        /** The listener type. */
+        final Class<? extends EventListener> listenerType;
+
+        /**
+         * Instantiates a new event descriptor.
+         * 
+         * @param eventMask the event mask
+         * @param listenerType the listener type
+         */
+        EventDescriptor(long eventMask, Class<? extends EventListener> listenerType) {
+            this.eventMask = eventMask;
+            this.listenerType = listenerType;
+        }
+
+    }
+    
+    /**
+     * The Class EventTypeLookup.
+     */
+    static final class EventTypeLookup {
+        
+        /** The last event. */
+        private AWTEvent lastEvent = null;
+        
+        /** The last event descriptor. */
+        private EventDescriptor lastEventDescriptor = null;
+
+        /**
+         * Gets the event descriptor.
+         * 
+         * @param event the event
+         * 
+         * @return the event descriptor
+         */
+        EventDescriptor getEventDescriptor(AWTEvent event) {
+            synchronized (this) {
+                if (event != lastEvent) {
+                    lastEvent = event;
+                    lastEventDescriptor = eventsMap.get(new Integer(event.id));
+                }
+
+                return lastEventDescriptor;
+            }
+        }
+
+        /**
+         * Gets the event mask.
+         * 
+         * @param event the event
+         * 
+         * @return the event mask
+         */
+        long getEventMask(AWTEvent event) {
+            final EventDescriptor ed = getEventDescriptor(event);
+            return ed == null ? -1 : ed.eventMask;
+        }
+    }
+
+    /**
+     * The Class EventConverter.
+     */
+    static final class EventConverter {
+        
+        /** The Constant OLD_MOD_MASK. */
+        static final int OLD_MOD_MASK = Event.ALT_MASK | Event.CTRL_MASK
+        | Event.META_MASK | Event.SHIFT_MASK;
+
+        /**
+         * Convert action event.
+         * 
+         * @param ae the ae
+         * 
+         * @return the event
+         */
+        Event convertActionEvent(ActionEvent ae) {
+            Event evt = new Event(ae.getSource(), ae.getID(), ae.getActionCommand());
+            evt.when = ae.getWhen();
+            evt.modifiers = ae.getModifiers() & OLD_MOD_MASK;
+
+           /* if (source instanceof Button) {
+                arg = ((Button) source).getLabel();
+            } else if (source instanceof Checkbox) {
+                arg = new Boolean(((Checkbox) source).getState());
+            } else if (source instanceof CheckboxMenuItem) {
+                arg = ((CheckboxMenuItem) source).getLabel();
+            } else if (source instanceof Choice) {
+                arg = ((Choice) source).getSelectedItem();
+            } else if (source instanceof List) {
+                arg = ((List) source).getSelectedItem();
+            } else if (source instanceof MenuItem) {
+                arg = ((MenuItem) source).getLabel();
+            } else if (source instanceof TextField) {
+                arg = ((TextField) source).getText();
+            }
+*/
+            return evt;
+        }
+
+
+        /**
+         * Convert adjustment event.
+         * 
+         * @param ae the ae
+         * 
+         * @return the event
+         */
+        Event convertAdjustmentEvent(AdjustmentEvent ae) {
+            //TODO: Event.SCROLL_BEGIN/SCROLL_END
+            return new Event(ae.source, ae.id + ae.getAdjustmentType() - 1,
+                    new Integer(ae.getValue()));
+        }
+
+        /**
+         * Convert component event.
+         * 
+         * @param ce the ce
+         * 
+         * @return the event
+         */
+        Event convertComponentEvent(ComponentEvent ce) {
+            Component comp = ce.getComponent();
+            Event evt = new Event(comp, Event.WINDOW_MOVED, null);
+            evt.x = comp.getX();
+            evt.y = comp.getY();
+            return evt;
+        }
+
+        //???AWT
+        /*
+        Event convertItemEvent(ItemEvent ie) {
+            int oldId = ie.id + ie.getStateChange() - 1;
+            Object source = ie.source;
+            int idx = -1;
+            if (source instanceof List) {
+                List list = (List) source;
+                idx = list.getSelectedIndex();
+            }
+            else if (source instanceof Choice) {
+                Choice choice = (Choice) source;
+                idx = choice.getSelectedIndex();
+            }
+            Object arg = idx >= 0 ? new Integer(idx) : null;
+            return new Event(source, oldId, arg);
+        }
+        */
+        
+        /**
+         * Convert key event.
+         * 
+         * @param ke the ke
+         * 
+         * @return the event
+         */
+        Event convertKeyEvent(KeyEvent ke) {
+            int oldId = ke.id;
+            //leave only old Event's modifiers
+
+            int mod = ke.getModifiers() & OLD_MOD_MASK;
+            Component comp = ke.getComponent();
+            char keyChar = ke.getKeyChar();
+            int keyCode = ke.getKeyCode();
+            int key = convertKey(keyChar, keyCode);
+            if (key >= Event.HOME && key <= Event.INSERT) {
+                oldId += 2; //non-ASCII key -> action key
+            }
+            return new Event(comp, ke.getWhen(), oldId, 0, 0, key, mod);
+        }
+
+        /**
+         * Convert mouse event.
+         * 
+         * @param me the me
+         * 
+         * @return the event
+         */
+        Event convertMouseEvent(MouseEvent me) {
+            int id = me.id;
+            if (id != MouseEvent.MOUSE_CLICKED) {
+                Event evt = new Event(me.source, id, null);
+                evt.x = me.getX();
+                evt.y = me.getY();
+                int mod = me.getModifiers();
+                //in Event modifiers mean button number for mouse events:
+                evt.modifiers = mod & (Event.ALT_MASK | Event.META_MASK);
+                if (id == MouseEvent.MOUSE_PRESSED) {
+                    evt.clickCount = me.getClickCount();
+                }
+                return evt;
+            }
+            return null;
+        }
+        
+        /**
+         * Convert key.
+         * 
+         * @param keyChar the key char
+         * @param keyCode the key code
+         * 
+         * @return the int
+         */
+        int convertKey(char keyChar, int keyCode) {
+            int key;
+            //F1 - F12
+            if (keyCode >= KeyEvent.VK_F1 && keyCode <= KeyEvent.VK_F12) {
+                key = Event.F1 + keyCode - KeyEvent.VK_F1;
+            } else {
+                switch (keyCode) {
+                default: //non-action key
+                    key = keyChar;
+                    break;
+                //action keys:
+                case KeyEvent.VK_HOME:
+                    key = Event.HOME;
+                    break;
+                case KeyEvent.VK_END:
+                    key = Event.END;
+                    break;
+                case KeyEvent.VK_PAGE_UP:
+                    key = Event.PGUP;
+                    break;
+                case KeyEvent.VK_PAGE_DOWN:
+                    key = Event.PGDN;
+                    break;
+                case KeyEvent.VK_UP:
+                    key = Event.UP;
+                    break;
+                case KeyEvent.VK_DOWN:
+                    key = Event.DOWN;
+                    break;
+                case KeyEvent.VK_LEFT:
+                    key = Event.LEFT;
+                    break;
+                case KeyEvent.VK_RIGHT:
+                    key = Event.RIGHT;
+                    break;
+                case KeyEvent.VK_PRINTSCREEN:
+                    key = Event.PRINT_SCREEN;
+                    break;
+                case KeyEvent.VK_SCROLL_LOCK:
+                    key = Event.SCROLL_LOCK;
+                    break;
+                case KeyEvent.VK_CAPS_LOCK:
+                    key = Event.CAPS_LOCK;
+                    break;
+                case KeyEvent.VK_NUM_LOCK:
+                    key = Event.NUM_LOCK;
+                    break;
+                case KeyEvent.VK_PAUSE:
+                    key = Event.PAUSE;
+                    break;
+                case KeyEvent.VK_INSERT:
+                    key = Event.INSERT;
+                    break;
+                }
+            }
+            return key;
+        }
+
+    }
+
+}
diff --git a/awt/java/awt/AWTException.java b/awt/java/awt/AWTException.java
new file mode 100644
index 0000000..70ce6e1
--- /dev/null
+++ b/awt/java/awt/AWTException.java
@@ -0,0 +1,43 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt;
+
+
+/**
+ * The AWTException class is used to provide notification and information
+ * about AWT errors.
+ */
+public class AWTException extends Exception {
+    
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = -1900414231151323879L;
+
+    /**
+     * Instantiates a new AWT exception with the specified message.
+     * 
+     * @param msg the specific message for current exception.
+     */
+    public AWTException(String msg) {
+        super(msg);
+    }
+
+}
+
diff --git a/awt/java/awt/AWTKeyStroke.java b/awt/java/awt/AWTKeyStroke.java
new file mode 100644
index 0000000..5e7de4e
--- /dev/null
+++ b/awt/java/awt/AWTKeyStroke.java
@@ -0,0 +1,678 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Dmitry A. Durnev
+ * @version $Revision$
+ */
+package java.awt;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The AWTKeyStroke holds all of the information for the complete act of 
+ * typing a character. This includes the events that are generated when 
+ * the key is pressed, released, or typed (pressed and released generating
+ * a unicode character result) which are associated with the event
+ * objects KeyEvent.KEY_PRESSED, KeyEvent.KEY_RELEASED, or KeyEvent.KEY_TYPED.
+ * It also holds information about which modifiers (such as control or 
+ * shift) were used in conjunction with the keystroke. The following masks 
+ * are available to identify the modifiers:
+ * <ul>
+ * <li>java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK</li>
+ * <li>java.awt.event.InputEvent.ALT_DOWN_MASK</li>
+ * <li>java.awt.event.InputEvent.CTRL_DOWN_MASK</li>
+ * <li>java.awt.event.InputEvent.META_DOWN_MASK</li>
+ * <li>java.awt.event.InputEvent.SHIFT_DOWN_MASK</li>
+ * <li>java.awt.event.InputEvent.ALT_GRAPH_MASK</li>
+ * <li>java.awt.event.InputEvent.ALT_MASK</li>
+ * <li>java.awt.event.InputEvent.CTRL_MASK</li>
+ * <li>java.awt.event.InputEvent.META_MASK</li>  
+ * <li>java.awt.event.InputEvent.SHIFT_MASK</li>
+ * </ul>  
+ * <br>
+ *  The AWTKeyStroke is unique, and applications should not create their own 
+ *  instances of AWTKeyStroke. All applications should use getAWTKeyStroke 
+ *  methods for obtaining instances of AWTKeyStroke.
+ */
+public class AWTKeyStroke implements Serializable {
+    
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = -6430539691155161871L;
+
+    /** The Constant cache. */
+    private static final Map<AWTKeyStroke, AWTKeyStroke> cache = new HashMap<AWTKeyStroke, AWTKeyStroke>(); //Map<AWTKeyStroke, ? extends AWTKeyStroke>
+    
+    /** The Constant keyEventTypesMap. */
+    private static final Map<Integer, String> keyEventTypesMap = new HashMap<Integer, String>(); //Map<int, String>
+
+    private static Constructor<?> subConstructor;   
+
+    static {
+        keyEventTypesMap.put(new Integer(KeyEvent.KEY_PRESSED), "pressed"); //$NON-NLS-1$
+        keyEventTypesMap.put(new Integer(KeyEvent.KEY_RELEASED), "released"); //$NON-NLS-1$
+        keyEventTypesMap.put(new Integer(KeyEvent.KEY_TYPED), "typed"); //$NON-NLS-1$
+    }
+
+    /** The key char. */
+    private char keyChar;
+    
+    /** The key code. */
+    private int keyCode;
+    
+    /** The modifiers. */
+    private int modifiers;
+    
+    /** The on key release. */
+    private boolean onKeyRelease;
+    
+    /**
+     * Instantiates a new AWTKeyStroke. 
+     * getAWTKeyStroke method should be used by applications code.  
+     * 
+     * @param keyChar the key char
+     * @param keyCode the key code
+     * @param modifiers the modifiers
+     * @param onKeyRelease true if AWTKeyStroke is for a key release, overwise false. 
+     */
+    protected AWTKeyStroke(char keyChar, int keyCode, int modifiers,
+            boolean onKeyRelease)
+    {
+       setAWTKeyStroke(keyChar, keyCode, modifiers, onKeyRelease);
+    }
+
+    /** Sets the awt key stroke.
+     * 
+     * @param keyChar the key char
+     * @param keyCode the key code
+     * @param modifiers the modifiers
+     * @param onKeyRelease the on key release
+     */
+    private void setAWTKeyStroke( char keyChar, int keyCode, int modifiers,
+            boolean onKeyRelease)
+    {
+        this.keyChar = keyChar;
+        this.keyCode = keyCode;
+        this.modifiers = modifiers;
+        this.onKeyRelease = onKeyRelease;
+    }
+    
+    /**
+     * Instantiates a new AWTKeyStroke with default parameters:
+     * KeyEvent.CHAR_UNDEFINED key char, KeyEvent.VK_UNDEFINED key code,
+     * without modifiers and false key realised value.
+     */
+    protected AWTKeyStroke() {
+        this(KeyEvent.CHAR_UNDEFINED, KeyEvent.VK_UNDEFINED, 0, false);
+    }
+
+    /**
+     * Returns the unique number value for AWTKeyStroke object.
+     * 
+     * @return the int unique value of the AWTKeyStroke object.
+     */
+    @Override
+    public int hashCode() {
+        return modifiers + ( keyCode != KeyEvent.VK_UNDEFINED ?
+                keyCode : keyChar) + (onKeyRelease ? -1 : 0);
+    }
+
+    /**
+     * Gets the set of modifiers for the AWTKeyStroke object.
+     * 
+     * @return the int value which contains modifiers.
+     */
+    public final int getModifiers() {
+        return modifiers;
+    }
+
+    /**
+     * Compares the AWTKeyStroke object to the specified object.
+     * 
+     * @return true, if objects are identical, overwise false.
+     */
+    @Override
+    public final boolean equals(Object anObject) {
+        if (anObject instanceof AWTKeyStroke) {
+            AWTKeyStroke key = (AWTKeyStroke)anObject;
+            return ((key.keyCode == keyCode) && (key.keyChar == keyChar) &&
+                    (key.modifiers == modifiers) &&
+                    (key.onKeyRelease == onKeyRelease));
+        }
+        return false;
+    }
+
+    /**
+     * Returns the string representation of the AWTKeyStroke.
+     * This string should contain key stroke properties.
+     * 
+     * @return the string representation of the AWTKeyStroke.
+     */
+    @Override
+    public String toString() {
+        int type = getKeyEventType();
+        return InputEvent.getModifiersExText(getModifiers()) + " " + //$NON-NLS-1$
+            keyEventTypesMap.get(new Integer(type)) +  " " + //$NON-NLS-1$
+            (type == KeyEvent.KEY_TYPED ? new String(new char[] {keyChar}) :
+                                          KeyEvent.getKeyText(keyCode));
+    }
+
+    /**
+     * Gets the key code for the AWTKeyStroke object.
+     * 
+     * @return the key code for the AWTKeyStroke object.
+     */
+    public final int getKeyCode() {
+        return keyCode;
+    }
+
+    /**
+     * Gets the key character for the AWTKeyStroke object.
+     * 
+     * @return the key character for the AWTKeyStroke object.
+     */
+    public final char getKeyChar() {
+        return keyChar;
+    }
+
+    /**
+     * Gets the AWT key stroke.
+     * 
+     * @param keyChar the key char
+     * @param keyCode the key code
+     * @param modifiers the modifiers
+     * @param onKeyRelease the on key release
+     * 
+     * @return the AWT key stroke
+     */
+    private static AWTKeyStroke getAWTKeyStroke(char keyChar, int keyCode,
+                                                int modifiers,
+                                                boolean onKeyRelease) {
+        AWTKeyStroke key = newInstance(keyChar, keyCode, modifiers, onKeyRelease);
+
+        AWTKeyStroke value = cache.get(key);
+        if (value == null) {
+            value = key;
+            cache.put(key, value);
+        }
+        return value;
+    }
+
+    /**
+     * New instance.
+     * 
+     * @param keyChar the key char
+     * @param keyCode the key code
+     * @param modifiers the modifiers
+     * @param onKeyRelease the on key release
+     * 
+     * @return the AWT key stroke
+     */
+    private static AWTKeyStroke newInstance(char keyChar, int keyCode,
+                                            int modifiers,
+                                            boolean onKeyRelease) {
+        AWTKeyStroke key;
+        //???AWT
+//        if (subConstructor == null) {
+            key = new AWTKeyStroke();
+        //???AWT
+//        } else {
+//            try {
+//                key = (AWTKeyStroke) subConstructor.newInstance();
+//            } catch (Exception e) {
+//                throw new RuntimeException(e);
+//            }
+//        }
+        int allModifiers = getAllModifiers(modifiers);
+        key.setAWTKeyStroke(keyChar, keyCode, allModifiers, onKeyRelease);
+        return key;
+    }
+
+    /**
+     * Adds the mask.
+     * 
+     * @param mod the mod
+     * @param mask the mask
+     * 
+     * @return the int
+     */
+    private static int addMask(int mod, int mask) {
+        return ((mod & mask) != 0) ? (mod | mask) : mod;
+    }
+
+    /**
+     * return all (old & new) modifiers corresponding to.
+     * 
+     * @param mod old or new modifiers
+     * 
+     * @return old and new modifiers together
+     */
+    static int getAllModifiers(int mod) {
+        int allMod = mod;
+        int shift = (InputEvent.SHIFT_MASK | InputEvent.SHIFT_DOWN_MASK);
+        int ctrl = (InputEvent.CTRL_MASK | InputEvent.CTRL_DOWN_MASK);
+        int meta = (InputEvent.META_MASK | InputEvent.META_DOWN_MASK);
+        int alt = (InputEvent.ALT_MASK | InputEvent.ALT_DOWN_MASK);
+        int altGr = (InputEvent.ALT_GRAPH_MASK | InputEvent.ALT_GRAPH_DOWN_MASK);
+        // button modifiers are not converted between old & new
+
+        allMod = addMask(allMod, shift);
+        allMod = addMask(allMod, ctrl);
+        allMod = addMask(allMod, meta);
+        allMod = addMask(allMod, alt);
+        allMod = addMask(allMod, altGr);
+
+        return allMod;
+    }
+
+    /**
+     * Returns an instance of AWTKeyStroke for parsed string.
+     * 
+     * The string must have the following syntax:
+     *<p>
+     * &lt;modifiers&gt;* (&lt;typedID&gt; | &lt;pressedReleasedID&gt;)
+     *<p>
+     * modifiers := shift | control | ctrl | meta | alt | altGraph
+     * <br> 
+     * typedID := typed <typedKey>
+     * <br>
+     * typedKey := string of length 1 giving the Unicode character.
+     * <br>
+     * pressedReleasedID := (pressed | released) <key>
+     * <br>
+     * key := KeyEvent key code name, i.e. the name following "VK_".
+     * <p>
+     * @param s the String which contains key stroke parameters.
+     * 
+     * @return the AWTKeyStroke for string.
+     * 
+     * @throws IllegalArgumentException if string has incorrect format or null.
+     */
+    public static AWTKeyStroke getAWTKeyStroke(String s) {
+        if (s == null) {
+            // awt.65=null argument
+            throw new IllegalArgumentException(Messages.getString("awt.65")); //$NON-NLS-1$
+        }
+
+        StringTokenizer tokenizer = new StringTokenizer(s);
+
+        Boolean release = null;
+        int modifiers = 0;
+        int keyCode = KeyEvent.VK_UNDEFINED;
+        char keyChar = KeyEvent.CHAR_UNDEFINED;
+        boolean typed = false;
+        long modifier = 0;
+        String token = null;
+        do {
+            token = getNextToken(tokenizer);
+            modifier = parseModifier(token);
+            modifiers |= modifier;
+        } while (modifier > 0);
+
+        typed = parseTypedID(token);
+
+        if (typed) {
+            token = getNextToken(tokenizer);
+            keyChar = parseTypedKey(token);
+
+        }
+        if (keyChar == KeyEvent.CHAR_UNDEFINED) {
+            release = parsePressedReleasedID(token);
+            if (release != null) {
+                token = getNextToken(tokenizer);
+            }
+            keyCode = parseKey(token);
+        }
+        if (tokenizer.hasMoreTokens()) {
+            // awt.66=Invalid format
+            throw new IllegalArgumentException(Messages.getString("awt.66")); //$NON-NLS-1$
+        }
+
+        return getAWTKeyStroke(keyChar, keyCode, modifiers,
+                               release == Boolean.TRUE);
+    }
+
+    /**
+     * Gets the next token.
+     * 
+     * @param tokenizer the tokenizer
+     * 
+     * @return the next token
+     */
+    private static String getNextToken(StringTokenizer tokenizer) {
+        try {
+            return tokenizer.nextToken();
+        } catch (NoSuchElementException exception) {
+            // awt.66=Invalid format
+            throw new IllegalArgumentException(Messages.getString("awt.66")); //$NON-NLS-1$
+        }
+    }
+
+    /**
+     * Gets the key code.
+     * 
+     * @param s the s
+     * 
+     * @return the key code
+     */
+    static int getKeyCode(String s) {
+        try {
+            Field vk = KeyEvent.class.getField("VK_" + s); //$NON-NLS-1$
+            return vk.getInt(null);
+        } catch (Exception e) {
+            if (s.length() != 1) {
+                // awt.66=Invalid format
+                throw new IllegalArgumentException(Messages.getString("awt.66")); //$NON-NLS-1$
+            }
+            return KeyEvent.VK_UNDEFINED;
+        }
+    }
+
+    /**
+     * Gets an instance of the AWTKeyStroke for specified character.
+     * 
+     * @param keyChar the keyboard character value.
+     * 
+     * @return a AWTKeyStroke for specified character.
+     */
+    public static AWTKeyStroke getAWTKeyStroke(char keyChar) {
+        return getAWTKeyStroke(keyChar, KeyEvent.VK_UNDEFINED, 0, false);
+    }
+
+    /**
+     * Returns an instance of AWTKeyStroke for a given key code, set 
+     * of modifiers, and specified key released flag value.
+     * The key codes are defined in java.awt.event.KeyEvent class. 
+     * The set of modifiers is given as a bitwise combination 
+     * of masks taken from the following list:
+     * <ul>
+     * <li>java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK</li>
+     * <li>java.awt.event.InputEvent.ALT_DOWN_MASK</li>
+     * <li>java.awt.event.InputEvent.CTRL_DOWN_MASK</li>
+     * <li>java.awt.event.InputEvent.META_DOWN_MASK</li>
+     * <li>java.awt.event.InputEvent.SHIFT_DOWN_MASK</li>
+     * <li>java.awt.event.InputEvent.ALT_GRAPH_MASK</li>
+     * <li>java.awt.event.InputEvent.ALT_MASK</li>
+     * <li>java.awt.event.InputEvent.CTRL_MASK</li>
+     * <li>java.awt.event.InputEvent.META_MASK</li>  
+     * <li>java.awt.event.InputEvent.SHIFT_MASK</li>
+     * </ul>
+     *  <br>
+     *  
+     * @param keyCode the specified key code of keyboard.
+     * @param modifiers the bit set of modifiers.
+     * 
+     * @return the AWTKeyStroke.
+     */
+    public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers,
+                                               boolean onKeyRelease) {
+        return getAWTKeyStroke(KeyEvent.CHAR_UNDEFINED, keyCode, modifiers,
+                               onKeyRelease);
+    }
+
+    /**
+     * Returns AWTKeyStroke for a specified character and set of modifiers. 
+     * The set of modifiers is given as a bitwise combination 
+     * of masks taken from the following list:
+     * <ul>
+     * <li>java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK</li>
+     * <li>java.awt.event.InputEvent.ALT_DOWN_MASK</li>
+     * <li>java.awt.event.InputEvent.CTRL_DOWN_MASK</li>
+     * <li>java.awt.event.InputEvent.META_DOWN_MASK</li>
+     * <li>java.awt.event.InputEvent.SHIFT_DOWN_MASK</li>
+     * <li>java.awt.event.InputEvent.ALT_GRAPH_MASK</li>
+     * <li>java.awt.event.InputEvent.ALT_MASK</li>
+     * <li>java.awt.event.InputEvent.CTRL_MASK</li>
+     * <li>java.awt.event.InputEvent.META_MASK</li>  
+     * <li>java.awt.event.InputEvent.SHIFT_MASK</li>
+     * </ul>
+     * 
+     * @param keyChar the Character object which represents keyboard character value.
+     * @param modifiers the bit set of modifiers.
+     * 
+     * @return the AWTKeyStroke object.
+     * 
+     * @throws IllegalArgumentException if keyChar value is null.
+     */
+    public static AWTKeyStroke getAWTKeyStroke(Character keyChar, int modifiers) {
+        if (keyChar == null) {
+            // awt.01='{0}' parameter is null
+            throw new IllegalArgumentException(Messages.getString("awt.01", "keyChar")); //$NON-NLS-1$ //$NON-NLS-2$
+        }
+        return getAWTKeyStroke(keyChar.charValue(), KeyEvent.VK_UNDEFINED,
+                               modifiers, false);
+    }
+
+    /**
+     * Returns an instance of AWTKeyStroke for a specified key code and 
+     * set of modifiers.
+     * The key codes are defined in java.awt.event.KeyEvent class. 
+     * The set of modifiers is given as a bitwise combination 
+     * of masks taken from the following list:
+     * <ul>
+     * <li>java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK</li>
+     * <li>java.awt.event.InputEvent.ALT_DOWN_MASK</li>
+     * <li>java.awt.event.InputEvent.CTRL_DOWN_MASK</li>
+     * <li>java.awt.event.InputEvent.META_DOWN_MASK</li>
+     * <li>java.awt.event.InputEvent.SHIFT_DOWN_MASK</li>
+     * <li>java.awt.event.InputEvent.ALT_GRAPH_MASK</li>
+     * <li>java.awt.event.InputEvent.ALT_MASK</li>
+     * <li>java.awt.event.InputEvent.CTRL_MASK</li>
+     * <li>java.awt.event.InputEvent.META_MASK</li>  
+     * <li>java.awt.event.InputEvent.SHIFT_MASK</li>
+     * </ul>
+     *  
+     * @param keyCode the specified key code of keyboard.
+     * @param modifiers the bit set of modifiers.
+     * 
+     * @return the AWTKeyStroke
+     */
+    public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers) {
+        return getAWTKeyStroke(keyCode, modifiers, false);
+    }
+
+    /**
+     * Gets the AWTKeyStroke for a key event. This method obtains the key char 
+     * and key code from the specified key event.
+     * 
+     * @param anEvent the key event which identifies the desired AWTKeyStroke.
+     * 
+     * @return the AWTKeyStroke for the key event.
+     */
+    public static AWTKeyStroke getAWTKeyStrokeForEvent(KeyEvent anEvent) {
+        int id = anEvent.getID();
+        char undef = KeyEvent.CHAR_UNDEFINED;
+        char keyChar = (id == KeyEvent.KEY_TYPED ? anEvent.getKeyChar() :
+                                                   undef);
+        int keyCode = (keyChar == undef ? anEvent.getKeyCode() :
+                                          KeyEvent.VK_UNDEFINED);
+        return getAWTKeyStroke(keyChar, keyCode, anEvent.getModifiersEx(),
+                               id == KeyEvent.KEY_RELEASED);
+    }
+
+    /**
+     * Gets the key event type for the AWTKeyStroke object.
+     * 
+     * @return the key event type: KeyEvent.KEY_PRESSED, KeyEvent.KEY_TYPED, or KeyEvent.KEY_RELEASED
+     */
+    public final int getKeyEventType() {
+        if (keyCode == KeyEvent.VK_UNDEFINED) {
+            return KeyEvent.KEY_TYPED;
+        }
+        return (onKeyRelease ? KeyEvent.KEY_RELEASED : KeyEvent.KEY_PRESSED);
+    }
+
+    /**
+     * Retuns true if the key event is associated with the AWTKeyStroke is 
+     * KEY_RELEASED, overwise false.
+     * 
+     * @return true, if if the key event associated with the AWTKeyStroke is 
+     * KEY_RELEASED, overwise false.
+     */
+    public final boolean isOnKeyRelease() {
+        return onKeyRelease;
+    }
+
+    /**
+     * Read resolve.
+     * 
+     * @return the object
+     * 
+     * @throws ObjectStreamException the object stream exception
+     */
+    protected Object readResolve() throws ObjectStreamException {
+        return getAWTKeyStroke(this.keyChar, this.keyCode,
+                               this.modifiers, this.onKeyRelease);
+    }
+
+    /**
+     * Register subclass.
+     * 
+     * @param subclass the subclass
+     */
+    protected static void registerSubclass(Class<?> subclass) {
+        //???AWT
+        /*
+        if (subclass == null) {
+            // awt.01='{0}' parameter is null
+            throw new IllegalArgumentException(Messages.getString("awt.01", "subclass")); //$NON-NLS-1$ //$NON-NLS-2$
+        }
+        if (! AWTKeyStroke.class.isAssignableFrom(subclass)) {
+            // awt.67=subclass is not derived from AWTKeyStroke
+            throw new ClassCastException(Messages.getString("awt.67")); //$NON-NLS-1$
+        }
+        try {
+            subConstructor = subclass.getDeclaredConstructor();
+            subConstructor.setAccessible(true);
+        } catch (SecurityException e) {
+            throw new RuntimeException(e);
+        } catch (NoSuchMethodException e) {
+            // awt.68=subclass could not be instantiated
+            throw new IllegalArgumentException(Messages.getString("awt.68")); //$NON-NLS-1$
+        }
+        cache.clear(); //flush the cache
+        */
+    }
+
+    /**
+     * Parses the modifier.
+     * 
+     * @param strMod the str mod
+     * 
+     * @return the long
+     */
+    private static long parseModifier(String strMod) {
+        long modifiers = 0l;
+        if (strMod.equals("shift")) { //$NON-NLS-1$
+            modifiers |= InputEvent.SHIFT_DOWN_MASK;
+        } else if (strMod.equals("control") || strMod.equals("ctrl")) { //$NON-NLS-1$ //$NON-NLS-2$
+            modifiers |= InputEvent.CTRL_DOWN_MASK;
+        } else if (strMod.equals("meta")) { //$NON-NLS-1$
+            modifiers |= InputEvent.META_DOWN_MASK;
+        } else if (strMod.equals("alt")) { //$NON-NLS-1$
+            modifiers |= InputEvent.ALT_DOWN_MASK;
+        } else if (strMod.equals("altGraph")) { //$NON-NLS-1$
+            modifiers |= InputEvent.ALT_GRAPH_DOWN_MASK;
+        } else if (strMod.equals("button1")) { //$NON-NLS-1$
+            modifiers |= InputEvent.BUTTON1_DOWN_MASK;
+        } else if (strMod.equals("button2")) { //$NON-NLS-1$
+            modifiers |= InputEvent.BUTTON2_DOWN_MASK;
+        } else if (strMod.equals("button3")) { //$NON-NLS-1$
+            modifiers |= InputEvent.BUTTON3_DOWN_MASK;
+        }
+        return modifiers;
+    }
+
+    /**
+     * Parses the typed id.
+     * 
+     * @param strTyped the str typed
+     * 
+     * @return true, if successful
+     */
+    private static boolean parseTypedID(String strTyped) {
+        if (strTyped.equals("typed")) { //$NON-NLS-1$
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Parses the typed key.
+     * 
+     * @param strChar the str char
+     * 
+     * @return the char
+     */
+    private static char parseTypedKey(String strChar) {
+        char keyChar = KeyEvent.CHAR_UNDEFINED;
+
+        if (strChar.length() != 1) {
+            // awt.66=Invalid format
+            throw new IllegalArgumentException(Messages.getString("awt.66")); //$NON-NLS-1$
+        }
+        keyChar = strChar.charAt(0);
+        return keyChar;
+    }
+
+    /**
+     * Parses the pressed released id.
+     * 
+     * @param str the str
+     * 
+     * @return the boolean
+     */
+    private static Boolean parsePressedReleasedID(String str) {
+
+        if (str.equals("pressed")) { //$NON-NLS-1$
+            return Boolean.FALSE;
+        } else if (str.equals("released")) { //$NON-NLS-1$
+            return Boolean.TRUE;
+        }
+        return null;
+    }
+
+    /**
+     * Parses the key.
+     * 
+     * @param strCode the str code
+     * 
+     * @return the int
+     */
+    private static int parseKey(String strCode) {
+        int keyCode = KeyEvent.VK_UNDEFINED;
+
+        keyCode = getKeyCode(strCode);
+
+        if (keyCode == KeyEvent.VK_UNDEFINED) {
+            // awt.66=Invalid format
+            throw new IllegalArgumentException(Messages.getString("awt.66")); //$NON-NLS-1$
+        }
+        return keyCode;
+    }
+}
+
diff --git a/awt/java/awt/AWTListenerList.java b/awt/java/awt/AWTListenerList.java
new file mode 100644
index 0000000..3327d63
--- /dev/null
+++ b/awt/java/awt/AWTListenerList.java
@@ -0,0 +1,47 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package java.awt;
+
+import java.util.EventListener;
+
+import org.apache.harmony.awt.ListenerList;
+
+final class AWTListenerList<T extends EventListener> extends ListenerList<T> {
+    private static final long serialVersionUID = -2622077171532840953L;
+
+    private final Component owner;
+    
+    AWTListenerList() {
+        super();
+        this.owner = null;
+    }
+
+    AWTListenerList(Component owner) {
+        super();
+        this.owner = owner;
+    }
+
+    @Override
+    public void addUserListener(T listener) {
+        super.addUserListener(listener);
+
+        if (owner != null) {
+            owner.deprecatedEventHandler = false;
+        }
+    }
+}
diff --git a/awt/java/awt/AWTPermission.java b/awt/java/awt/AWTPermission.java
new file mode 100644
index 0000000..25326ab
--- /dev/null
+++ b/awt/java/awt/AWTPermission.java
@@ -0,0 +1,54 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.security.BasicPermission;
+
+/**
+ * The AWTPermission specifies the name of the permission and the 
+ * corresponding action list.
+ */
+public final class AWTPermission extends BasicPermission {
+    
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = 8890392402588814465L;
+
+    /**
+     * Instantiates a new AWTPermission with defined name and actions.
+     * 
+     * @param name the name of a new AWTPermission. 
+     * @param actions the actions of a new AWTPermission.
+     */
+    public AWTPermission(String name, String actions) {
+        super(name, actions);
+    }
+
+    /**
+     * Instantiates a new AWT permission with the defined name.
+     * 
+     * @param name the name of a new AWTPermission. 
+     */
+    public AWTPermission(String name) {
+        super(name);
+    }
+
+}
+
diff --git a/awt/java/awt/ActiveEvent.java b/awt/java/awt/ActiveEvent.java
new file mode 100644
index 0000000..4133752
--- /dev/null
+++ b/awt/java/awt/ActiveEvent.java
@@ -0,0 +1,36 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt;
+
+/**
+ * This interface defines events that know how to dispatch themselves. 
+ * Such event can be placed upon the event queue and its dispatch method 
+ * will be called when the event is dispatched.
+ */
+public interface ActiveEvent {
+
+    /**
+     * Dispatches the event to the listeners of the event's source, 
+     * or does whatever it is this event is supposed to do.
+     */
+    public void dispatch();
+
+}
diff --git a/awt/java/awt/Adjustable.java b/awt/java/awt/Adjustable.java
new file mode 100644
index 0000000..3241cad
--- /dev/null
+++ b/awt/java/awt/Adjustable.java
@@ -0,0 +1,156 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.awt.event.AdjustmentListener;
+
+/**
+ * The Adjustable interface represents an adjustable numeric value 
+ * contained within a bounded range of values, such as the current 
+ * location in scrollable region or the value of a gauge.
+ */
+public interface Adjustable {
+
+    /** 
+     * The Constant HORIZONTAL indicates that the Adjustable's orientation 
+     * is horizontal. 
+     */
+    public static final int HORIZONTAL = 0;
+
+    /** 
+     * The Constant VERTICAL indicates that the Adjustable's orientation 
+     * is vertical. 
+     */
+    public static final int VERTICAL = 1;
+
+    /** 
+     * The Constant NO_ORIENTATION indicates that the Adjustable 
+     * has no orientation.
+     */
+    public static final int NO_ORIENTATION = 2;
+
+    /**
+     * Gets the value of the Adjustable.
+     * 
+     * @return the current value of the Adjustable.
+     */
+    public int getValue();
+
+    /**
+     * Sets the value to the Adjustable object.
+     * 
+     * @param a0 the new value of the Adjustable object. 
+     */
+    public void setValue(int a0);
+
+    /**
+     * Adds the AdjustmentListener to current Adjustment.
+     * 
+     * @param a0 the AdjustmentListener object.
+     */
+    public void addAdjustmentListener(AdjustmentListener a0);
+
+    /**
+     * Gets the block increment of the Adjustable.
+     * 
+     * @return the block increment of the Adjustable.
+     */
+    public int getBlockIncrement();
+
+    /**
+     * Gets the maximum value of the Adjustable.
+     * 
+     * @return the maximum value of the Adjustable.
+     */
+    public int getMaximum();
+
+    /**
+     * Gets the minimum value of the Adjustable.
+     * 
+     * @return the minimum value of the Adjustable. 
+     */
+    public int getMinimum();
+
+    /**
+     * Gets the orientation of the Adjustable.
+     * 
+     * @return the orientation of the Adjustable.
+     */
+    public int getOrientation();
+
+    /**
+     * Gets the unit increment of the Adjustable.
+     * 
+     * @return the unit increment of the Adjustable.
+     */
+    public int getUnitIncrement();
+
+    /**
+     * Gets the visible amount of the Adjustable.
+     * 
+     * @return the visible amount of the Adjustable.
+     */
+    public int getVisibleAmount();
+
+    /**
+     * Removes the adjustment listener of the Adjustable.
+     * 
+     * @param a0 the specified AdjustmentListener to be removed.
+     */
+    public void removeAdjustmentListener(AdjustmentListener a0);
+
+    /**
+     * Sets the block increment for the Adjustable.
+     * 
+     * @param a0 the new block increment.
+     */
+    public void setBlockIncrement(int a0);
+
+    /**
+     * Sets the maximum value of the Adjustable.
+     * 
+     * @param a0 the new maximum of the Adjustable.
+     */
+    public void setMaximum(int a0);
+
+    /**
+     * Sets the minimum value of the Adjustable.
+     * 
+     * @param a0 the new minimum of the Adjustable.
+     */
+    public void setMinimum(int a0);
+
+    /**
+     * Sets the unit increment of the Adjustable.
+     * 
+     * @param a0 the new unit increment of the Adjustable.
+     */
+    public void setUnitIncrement(int a0);
+
+    /**
+     * Sets the visible amount of the Adjustable.
+     * 
+     * @param a0 the new visible amount of the Adjustable.
+     */
+    public void setVisibleAmount(int a0);
+
+}
+
diff --git a/awt/java/awt/AlphaComposite.java b/awt/java/awt/AlphaComposite.java
new file mode 100644
index 0000000..d26753c
--- /dev/null
+++ b/awt/java/awt/AlphaComposite.java
@@ -0,0 +1,315 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.awt.Composite;
+import java.awt.CompositeContext;
+import java.awt.RenderingHints;
+import java.awt.image.ColorModel;
+
+import org.apache.harmony.awt.gl.ICompositeContext;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+
+/**
+ * The AlphaComposite class defines a basic alpha compositing rules for 
+ * combining source and destination colors to achieve blending and 
+ * transparency effects with graphics and images.
+ */
+public final class AlphaComposite implements Composite {
+
+    /** 
+     * The Constant CLEAR indicates that both the color and the alpha of 
+     * the destination are cleared (Porter-Duff Clear rule).
+     */
+    public static final int CLEAR = 1;
+
+    /** 
+     * The Constant SRC indicates that the source is copied to the destination 
+     * (Porter-Duff Source rule).
+     */
+    public static final int SRC = 2;
+
+    /** The Constant DST indicates that the destination is left untouched 
+     * (Porter-Duff Destination rule).
+     */
+    public static final int DST = 9;
+
+    /** 
+     * The Constant SRC_OVER indicates that the source is composited over 
+     * the destination (Porter-Duff Source Over Destination rule).
+     */
+    public static final int SRC_OVER = 3;
+
+    /**
+     * The Constant DST_OVER indicates that The destination is composited over 
+     * the source and the result replaces the destination 
+     * (Porter-Duff Destination Over Source rule).
+     */
+    public static final int DST_OVER = 4;
+
+    /**
+     * The Constant SRC_IN indicates that the part of the source lying 
+     * inside of the destination replaces the destination (Porter-Duff 
+     * Source In Destination rule).
+     */
+    public static final int SRC_IN = 5;
+
+    /** 
+     * The Constant DST_IN indicates that the part of the destination 
+     * lying inside of the source replaces the destination 
+     * (Porter-Duff Destination In Source rule).
+     */
+    public static final int DST_IN = 6;
+
+    /**
+     * The Constant SRC_OUT indicates that the part of the source lying 
+     * outside of the destination replaces the destination (Porter-Duff 
+     * Source Held Out By Destination rule).
+     */
+    public static final int SRC_OUT = 7;
+
+    /** 
+     * The Constant DST_OUT indicates that the part of the destination 
+     * lying outside of the source replaces the destination (Porter-Duff 
+     * Destination Held Out By Source rule).
+     */
+    public static final int DST_OUT = 8;
+
+    /** 
+     * The Constant SRC_ATOP indicates that the part of the source lying 
+     * inside of the destination is composited onto the destination 
+     * (Porter-Duff Source Atop Destination rule).
+     */
+    public static final int SRC_ATOP = 10;
+
+    /** 
+     * The Constant DST_ATOP indicates that the part of the destination 
+     * lying inside of the source is composited over the source and replaces 
+     * the destination (Porter-Duff Destination Atop Source rule).
+     */
+    public static final int DST_ATOP = 11;
+
+    /**
+     * The Constant XOR indicates that the part of the source that lies 
+     * outside of the destination is combined with the part of the destination 
+     * that lies outside of the source (Porter-Duff Source Xor Destination rule).
+     */
+    public static final int XOR = 12;
+
+    /** AlphaComposite object with the opaque CLEAR rule and an alpha of 1.0f. */
+    public static final AlphaComposite Clear = new AlphaComposite(CLEAR);
+
+    /** AlphaComposite object with the opaque SRC rule and an alpha of 1.0f. */
+    public static final AlphaComposite Src = new AlphaComposite(SRC);
+
+    /** AlphaComposite object with the opaque DST rule and an alpha of 1.0f. */
+    public static final AlphaComposite Dst = new AlphaComposite(DST);
+
+    /** AlphaComposite object with the opaque SRC_OVER rule and an alpha of 1.0f. */
+    public static final AlphaComposite SrcOver = new AlphaComposite(SRC_OVER);
+
+    /** AlphaComposite object with the opaque DST_OVER rule and an alpha of 1.0f. */
+    public static final AlphaComposite DstOver = new AlphaComposite(DST_OVER);
+
+    /** AlphaComposite object with the opaque SRC_IN rule and an alpha of 1.0f. */
+    public static final AlphaComposite SrcIn = new AlphaComposite(SRC_IN);
+
+    /** AlphaComposite object with the opaque DST_IN rule and an alpha of 1.0f. */
+    public static final AlphaComposite DstIn = new AlphaComposite(DST_IN);
+
+    /** AlphaComposite object with the opaque SRC_OUT rule and an alpha of 1.0f. */
+    public static final AlphaComposite SrcOut = new AlphaComposite(SRC_OUT);
+
+    /** AlphaComposite object with the opaque DST_OUT rule and an alpha of 1.0f. */
+    public static final AlphaComposite DstOut = new AlphaComposite(DST_OUT);
+
+    /** AlphaComposite object with the opaque SRC_ATOP rule and an alpha of 1.0f. */
+    public static final AlphaComposite SrcAtop = new AlphaComposite(SRC_ATOP);
+
+    /** AlphaComposite object with the opaque DST_ATOP rule and an alpha of 1.0f. */
+    public static final AlphaComposite DstAtop = new AlphaComposite(DST_ATOP);
+
+    /** AlphaComposite object with the opaque XOR rule and an alpha of 1.0f. */
+    public static final AlphaComposite Xor = new AlphaComposite(XOR);
+
+    /** The rule. */
+    private int rule;
+    
+    /** The alpha. */
+    private float alpha;
+
+    /**
+     * Instantiates a new alpha composite.
+     * Creates a context for the compositing operation. The context contains state that is used in performing the compositing operation.
+     * 
+     * @param rule the rule
+     * @param alpha the alpha
+     */
+    private AlphaComposite(int rule, float alpha){
+        if(rule < CLEAR || rule > XOR) {
+            // awt.11D=Unknown rule
+            throw new IllegalArgumentException(Messages.getString("awt.11D")); //$NON-NLS-1$
+        }
+        if(alpha < 0.0f || alpha > 1.0f) {
+            // awt.11E=Wrong alpha value
+            throw new IllegalArgumentException(Messages.getString("awt.11E")); //$NON-NLS-1$
+        }
+
+        this.rule = rule;
+        this.alpha = alpha;
+    }
+
+    /**
+     * Instantiates a new alpha composite.
+     * 
+     * @param rule the rule
+     */
+    private AlphaComposite(int rule){
+        this(rule, 1.0f);
+    }
+
+    /**
+     * Creates a CompositeContext object with the specified source ColorModel,
+     * destination ColorModel and RenderingHints parameters for a composing 
+     * operation.
+     * 
+     * @param srcColorModel the source's ColorModel.
+     * @param dstColorModel the destination's ColorModel.
+     * @param hints the RenderingHints object.
+     * 
+     * @return the CompositeContext object.    
+     * 
+     * @see java.awt.Composite#createContext(java.awt.image.ColorModel, java.awt.image.ColorModel, java.awt.RenderingHints)
+     */
+    public CompositeContext createContext(ColorModel srcColorModel,
+            ColorModel dstColorModel, RenderingHints hints) {
+        return new ICompositeContext(this, srcColorModel, dstColorModel);
+    }
+
+    /**
+     * Compares the AlphaComposite object with the specified object.
+     * 
+     * @param obj the Object to be compared.
+     * 
+     * @return true, if the AlphaComposite object is equal to the specified
+     * object.
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if(!(obj instanceof AlphaComposite)) {
+            return false;
+        }
+        AlphaComposite other = (AlphaComposite)obj;
+        return (this.rule == other.getRule() && this.alpha == other.getAlpha());
+    }
+
+    /**
+     * Returns the hash code of the AlphaComposite object.
+     * 
+     * @return the hash code of the AlphaComposite object.
+     */
+    @Override
+    public int hashCode() {
+        int hash = Float.floatToIntBits(alpha);
+        int tmp = hash >>> 24;
+        hash <<= 8;
+        hash |= tmp;
+        hash ^= rule;
+        return hash;
+    }
+
+    /**
+     * Gets the compositing rule of this AlphaComposite object.
+     * 
+     * @return the compositing rule of this AlphaComposite object.
+     */
+    public int getRule() {
+        return rule;
+    }
+
+    /**
+     * Gets the alpha value of this AlphaComposite object; returns 1.0 if 
+     * this AlphaComposite object doesn't have alpha value.
+     * 
+     * @return the alpha value of this AlphaComposite object or 1.0 if 
+     * this AlphaComposite object doesn't have alpha value.
+     */
+    public float getAlpha() {
+        return alpha;
+    }
+
+    /**
+     * Gets the AlphaComposite instance with the specified rule and alpha value.
+     * 
+     * @param rule the compositing rule.
+     * @param alpha the alpha value.
+     * 
+     * @return AlphaComposite instance.
+     */
+    public static AlphaComposite getInstance(int rule, float alpha) {
+        if(alpha == 1.0f) {
+            return getInstance(rule);
+        }
+        return new AlphaComposite(rule, alpha);
+    }
+
+    /**
+     * Gets the AlphaComposite instance with the specified rule.
+     * 
+     * @param rule the compositing rule.
+     * 
+     * @return AlphaComposite instance.
+     */
+    public static AlphaComposite getInstance(int rule) {
+        switch(rule){
+        case CLEAR:
+            return Clear;
+        case SRC:
+            return Src;
+        case DST:
+            return Dst;
+        case SRC_OVER:
+            return SrcOver;
+        case DST_OVER:
+            return DstOver;
+        case SRC_IN:
+            return SrcIn;
+        case DST_IN:
+            return DstIn;
+        case SRC_OUT:
+            return SrcOut;
+        case DST_OUT:
+            return DstOut;
+        case SRC_ATOP:
+            return SrcAtop;
+        case DST_ATOP:
+            return DstAtop;
+        case XOR:
+            return Xor;
+        default:
+            // awt.11D=Unknown rule
+            throw new IllegalArgumentException(Messages.getString("awt.11D")); //$NON-NLS-1$
+        }
+    }
+
+}
+
diff --git a/awt/java/awt/BasicStroke.java b/awt/java/awt/BasicStroke.java
new file mode 100644
index 0000000..955dc6b
--- /dev/null
+++ b/awt/java/awt/BasicStroke.java
@@ -0,0 +1,2204 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Denis M. Kishenko
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.awt.geom.GeneralPath;
+import java.awt.geom.PathIterator;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+import org.apache.harmony.misc.HashCode;
+
+/**
+ * The BasicStroke class specifies a set of rendering attributes for the outlines 
+ * of graphics primitives. The BasicStroke attributes describe the shape of the 
+ * pen which draws the outline of a Shape and the decorations applied at the ends
+ * and joins of path segments of the Shape. The BasicStroke has the following
+ * rendering attributes:
+ * <p>
+ * <ul>
+ * <li> line width -the pen width which draws the outlines.</li>
+ * <li> end caps - indicates the decoration applied to the ends of unclosed 
+ * subpaths and dash segments. The BasicStroke defines three different decorations:
+ * CAP_BUTT, CAP_ROUND, and CAP_SQUARE.</li>
+ * <li>line joins - indicates the decoration applied at the intersection of 
+ * two path segments and at the intersection of the endpoints of a subpath.
+ * The BasicStroke defines three decorations: JOIN_BEVEL, JOIN_MITER, 
+ * and JOIN_ROUND.</li>
+ * <li>miter limit - the limit to trim a line join that has a JOIN_MITER 
+ * decoration.</li>
+ * <li>dash attributes - the definition of how to make a dash pattern by 
+ * alternating between opaque and transparent sections </li>
+ * </ul>
+ */
+public class BasicStroke implements Stroke {
+
+    /** 
+     * The Constant CAP_BUTT indicates the ends of unclosed subpaths 
+     * and dash segments have no added decoration.
+     */
+    public static final int CAP_BUTT = 0;
+    
+    /** 
+     * The Constant CAP_ROUND indicates the ends of unclosed subpaths 
+     * and dash segments have a round decoration.
+     */
+    public static final int CAP_ROUND = 1;
+    
+    /** 
+     * The Constant CAP_SQUARE indicates the ends of unclosed subpaths 
+     * and dash segments have a square projection.
+     */
+    public static final int CAP_SQUARE = 2;
+
+    /** 
+     * The Constant JOIN_MITER indicates that path segments are joined by 
+     * extending their outside edges until they meet.
+     */
+    public static final int JOIN_MITER = 0;
+    
+    /** 
+     * The Constant JOIN_ROUND indicates that path segments are joined by 
+     * rounding off the corner at a radius of half the line width.
+     */
+    public static final int JOIN_ROUND = 1;
+    
+    /** 
+     * The Constant JOIN_BEVEL indicates that path segments are joined by 
+     * connecting the outer corners of their wide outlines with 
+     * a straight segment.
+     */
+    public static final int JOIN_BEVEL = 2;
+    
+    /** Constants for calculating. */
+    static final int MAX_LEVEL = 20;        // Maximal deepness of curve subdivision
+    
+    /** The Constant CURVE_DELTA. */
+    static final double CURVE_DELTA = 2.0;  // Width tolerance
+    
+    /** The Constant CORNER_ANGLE. */
+    static final double CORNER_ANGLE = 4.0; // Minimum corner angle
+    
+    /** The Constant CORNER_ZERO. */
+    static final double CORNER_ZERO = 0.01; // Zero angle
+    
+    /** The Constant CUBIC_ARC. */
+    static final double CUBIC_ARC = 4.0 / 3.0 * (Math.sqrt(2.0) - 1);
+
+    /** Stroke width. */
+    float width;
+    
+    /** Stroke cap type. */
+    int cap;
+    
+    /** Stroke join type. */
+    int join;
+    
+    /** Stroke miter limit. */
+    float miterLimit;
+    
+    /** Stroke dashes array. */
+    float dash[];
+    
+    /** Stroke dash phase. */
+    float dashPhase;
+
+    /** The temporary pre-calculated values. */
+    double curveDelta;
+    
+    /** The corner delta. */
+    double cornerDelta;
+    
+    /** The zero delta. */
+    double zeroDelta;
+
+    /** The w2. */
+    double w2;
+    
+    /** The fmy. */
+    double fmx, fmy;
+    
+    /** The smy. */
+    double scx, scy, smx, smy;
+    
+    /** The cy. */
+    double mx, my, cx, cy;
+
+    /** The temporary indicators. */
+    boolean isMove;
+    
+    /** The is first. */
+    boolean isFirst;
+    
+    /** The check move. */
+    boolean checkMove;
+    
+    /** The temporary and destination work paths. */
+    BufferedPath dst, lp, rp, sp;
+    
+    /** Stroke dasher class. */
+    Dasher dasher;
+
+    /**
+     * Instantiates a new BasicStroke with default width, cap, join, limit,
+     * dash attributes parameters. The default parameters are a solid line of 
+     * width 1.0, CAP_SQUARE, JOIN_MITER, a miter limit of 10.0, null dash attributes,
+     * and a dash phase of 0.0f.
+     */
+    public BasicStroke() {
+        this(1.0f, CAP_SQUARE, JOIN_MITER, 10.0f, null, 0.0f);
+    }
+
+    /**
+     * Instantiates a new BasicStroke with the specified width,  
+     * caps, joins, limit, dash attributes, dash phase parameters.
+     * 
+     * @param width the width of BasikStroke.
+     * @param cap the end decoration of BasikStroke.
+     * @param join the join segments decoration.
+     * @param miterLimit the limit to trim the miter join.
+     * @param dash the array with the dashing pattern.
+     * @param dashPhase the offset to start the dashing pattern.
+     */
+    public BasicStroke(float width, int cap, int join, float miterLimit, float[] dash, float dashPhase) {
+        if (width < 0.0f) {
+            // awt.133=Negative width
+            throw new IllegalArgumentException(Messages.getString("awt.133")); //$NON-NLS-1$
+        }
+        if (cap != CAP_BUTT && cap != CAP_ROUND && cap != CAP_SQUARE) {
+            // awt.134=Illegal cap
+            throw new IllegalArgumentException(Messages.getString("awt.134")); //$NON-NLS-1$
+        }
+        if (join != JOIN_MITER && join != JOIN_ROUND && join != JOIN_BEVEL) {
+            // awt.135=Illegal join
+            throw new IllegalArgumentException(Messages.getString("awt.135")); //$NON-NLS-1$
+        }
+        if (join == JOIN_MITER && miterLimit < 1.0f) {
+            // awt.136=miterLimit less than 1.0f
+            throw new IllegalArgumentException(Messages.getString("awt.136")); //$NON-NLS-1$
+        }
+        if (dash != null) {
+            if (dashPhase < 0.0f) {
+                // awt.137=Negative dashPhase
+                throw new IllegalArgumentException(Messages.getString("awt.137")); //$NON-NLS-1$
+            }
+            if (dash.length == 0) {
+                // awt.138=Zero dash length
+                throw new IllegalArgumentException(Messages.getString("awt.138")); //$NON-NLS-1$
+            }
+            ZERO: {
+                for(int i = 0; i < dash.length; i++) {
+                    if (dash[i] < 0.0) {
+                        // awt.139=Negative dash[{0}]
+                        throw new IllegalArgumentException(Messages.getString("awt.139", i)); //$NON-NLS-1$
+                    }
+                    if (dash[i] > 0.0) {
+                        break ZERO;
+                    }
+                }
+                // awt.13A=All dash lengths zero
+                throw new IllegalArgumentException(Messages.getString("awt.13A")); //$NON-NLS-1$
+            }
+        }
+        this.width = width;
+        this.cap = cap;
+        this.join = join;
+        this.miterLimit = miterLimit;
+        this.dash = dash;
+        this.dashPhase = dashPhase;
+    }
+
+    /**
+     * Instantiates a new BasicStroke with specified width, cap, join, limit
+     * and default dash attributes parameters. 
+     * 
+     * @param width the width of BasikStroke.
+     * @param cap the end decoration of BasikStroke.
+     * @param join the join segments decoration.
+     * @param miterLimit the limit to trim the miter join.
+     */
+    public BasicStroke(float width, int cap, int join, float miterLimit) {
+        this(width, cap, join, miterLimit, null, 0.0f);
+    }
+
+    /**
+     * Instantiates a new BasicStroke with specified width, cap, join
+     * and default limit and dash attributes parameters. 
+     * 
+     * @param width the width of BasikStroke.
+     * @param cap the end decoration of BasikStroke.
+     * @param join the join segments decoration.
+     */
+    public BasicStroke(float width, int cap, int join) {
+        this(width, cap, join, 10.0f, null, 0.0f);
+    }
+
+    /**
+     * Instantiates a new BasicStroke with specified width and default cap, join,
+     * limit, dash attributes parameters.
+     * 
+     * @param width the width of BasicStroke.
+     */
+    public BasicStroke(float width) {
+        this(width, CAP_SQUARE, JOIN_MITER, 10.0f, null, 0.0f);
+    }
+
+    /**
+     * Gets the line width of the BasicStroke.
+     * 
+     * @return the line width of the BasicStroke.
+     */
+    public float getLineWidth() {
+        return width;
+    }
+
+    /**
+     * Gets the end cap style of the BasicStroke.
+     * 
+     * @return the end cap style of the BasicStroke.
+     */
+    public int getEndCap() {
+        return cap;
+    }
+
+    /**
+     * Gets the line join style of the BasicStroke.
+     * 
+     * @return the line join style of the BasicStroke.
+     */
+    public int getLineJoin() {
+        return join;
+    }
+
+    /**
+     * Gets the miter limit of the BasicStroke (the limit to trim the miter join).
+     * 
+     * @return the miter limit of the BasicStroke.
+     */
+    public float getMiterLimit() {
+        return miterLimit;
+    }
+
+    /**
+     * Gets the dash attributes array of the BasicStroke.
+     * 
+     * @return the dash attributes array of the BasicStroke.
+     */
+    public float[] getDashArray() {
+        return dash;
+    }
+
+    /**
+     * Gets the dash phase of the BasicStroke.
+     * 
+     * @return the dash phase of the BasicStroke.
+     */
+    public float getDashPhase() {
+        return dashPhase;
+    }
+
+    /**
+     * Returns hash code of this BasicStroke.
+     * 
+     * @return the hash code of this BasicStroke.
+     */
+    @Override
+    public int hashCode() {
+        HashCode hash = new HashCode();
+        hash.append(width);
+        hash.append(cap);
+        hash.append(join);
+        hash.append(miterLimit);
+        if (dash != null) {
+            hash.append(dashPhase);
+            for (float element : dash) {
+                hash.append(element);
+            }
+        }
+        return hash.hashCode();
+    }
+
+    /**
+     * Compares this BasicStroke object with the specified Object.
+     * 
+     * @param obj the Object to be compared.
+     * 
+     * @return true, if the Object is a BasicStroke with the same data
+     * values as this BasicStroke; false otherwise. 
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (obj instanceof BasicStroke) {
+            BasicStroke bs = (BasicStroke)obj;
+            return
+                bs.width == width &&
+                bs.cap == cap &&
+                bs.join == join &&
+                bs.miterLimit == miterLimit &&
+                bs.dashPhase == dashPhase &&
+                java.util.Arrays.equals(bs.dash, dash);
+        }
+        return false;
+    }
+
+    /**
+     * Calculates allowable curve derivation.
+     * 
+     * @param width the width
+     * 
+     * @return the curve delta
+     */
+    double getCurveDelta(double width) {
+        double a = width + CURVE_DELTA;
+        double cos = 1.0 - 2.0 * width * width / (a * a);
+        double sin = Math.sqrt(1.0 - cos * cos);
+        return Math.abs(sin / cos);
+    }
+
+    /**
+     * Calculates the value to detect a small angle.
+     * 
+     * @param width the width
+     * 
+     * @return the corner delta
+     */
+    double getCornerDelta(double width) {
+        return width * width * Math.sin(Math.PI * CORNER_ANGLE / 180.0);
+    }
+
+    /**
+     * Calculates value to detect a zero angle.
+     * 
+     * @param width the width
+     * 
+     * @return the zero delta
+     */
+    double getZeroDelta(double width) {
+        return width * width * Math.sin(Math.PI * CORNER_ZERO / 180.0);
+    }
+
+    /**
+     * Creates a Shape from the outline of the specified shape 
+     * drawn with this BasicStroke.
+     * 
+     * @param s the specified Shape to be stroked.
+     * 
+     * @return the Shape of the stroked outline.
+     * 
+     * @see java.awt.Stroke#createStrokedShape(java.awt.Shape)
+     */
+    public Shape createStrokedShape(Shape s) {
+        w2 = width / 2.0;
+        curveDelta = getCurveDelta(w2);
+        cornerDelta = getCornerDelta(w2);
+        zeroDelta = getZeroDelta(w2);
+
+        dst = new BufferedPath();
+        lp = new BufferedPath();
+        rp = new BufferedPath();
+
+        if (dash == null) {
+            createSolidShape(s.getPathIterator(null));
+        } else {
+            createDashedShape(s.getPathIterator(null));
+        }
+
+        return dst.createGeneralPath();
+    }
+
+    /**
+     * Generates a shape with a solid (not dashed) outline.
+     * 
+     * @param p - the PathIterator of source shape
+     */
+    void createSolidShape(PathIterator p) {
+        double coords[] = new double[6];
+        mx = my = cx = cy = 0.0;
+        isMove = false;
+        isFirst = false;
+        checkMove = true;
+        boolean isClosed = true;
+
+        while(!p.isDone()) {
+            switch(p.currentSegment(coords)) {
+            case PathIterator.SEG_MOVETO:
+                if (!isClosed) {
+                    closeSolidShape();
+                }
+                rp.clean();
+                mx = cx = coords[0];
+                my = cy = coords[1];
+                isMove = true;
+                isClosed = false;
+                break;
+            case PathIterator.SEG_LINETO:
+                addLine(cx, cy, cx = coords[0], cy = coords[1], true);
+                break;
+            case PathIterator.SEG_QUADTO:
+                addQuad(cx, cy, coords[0], coords[1], cx = coords[2], cy = coords[3]);
+                break;
+            case PathIterator.SEG_CUBICTO:
+                addCubic(cx, cy, coords[0], coords[1], coords[2], coords[3], cx = coords[4], cy = coords[5]);
+                break;
+            case PathIterator.SEG_CLOSE:
+                addLine(cx, cy, mx, my, false);
+                addJoin(lp, mx, my, lp.xMove, lp.yMove, true);
+                addJoin(rp, mx, my, rp.xMove, rp.yMove, false);
+                lp.closePath();
+                rp.closePath();
+                lp.appendReverse(rp);
+                isClosed = true;
+                break;
+            }
+            p.next();
+        }
+        if (!isClosed) {
+            closeSolidShape();
+        }
+
+        dst = lp;
+    }
+
+    /**
+     * Closes solid shape path.
+     */
+    void closeSolidShape() {
+        addCap(lp, cx, cy, rp.xLast, rp.yLast);
+        lp.combine(rp);
+        addCap(lp, mx, my, lp.xMove, lp.yMove);
+        lp.closePath();
+    }
+
+    /**
+     * Generates dashed stroked shape.
+     * 
+     * @param p - the PathIterator of source shape
+     */
+    void createDashedShape(PathIterator p) {
+        double coords[] = new double[6];
+        mx = my = cx = cy = 0.0;
+        smx = smy = scx = scy = 0.0;
+        isMove = false;
+        checkMove = false;
+        boolean isClosed = true;
+
+        while(!p.isDone()) {
+            switch(p.currentSegment(coords)) {
+            case PathIterator.SEG_MOVETO:
+
+                if (!isClosed) {
+                    closeDashedShape();
+                }
+
+                dasher = new Dasher(dash, dashPhase);
+                lp.clean();
+                rp.clean();
+                sp = null;
+                isFirst = true;
+                isMove = true;
+                isClosed = false;
+                mx = cx = coords[0];
+                my = cy = coords[1];
+                break;
+            case PathIterator.SEG_LINETO:
+                addDashLine(cx, cy, cx = coords[0], cy = coords[1]);
+                break;
+            case PathIterator.SEG_QUADTO:
+                addDashQuad(cx, cy, coords[0], coords[1], cx = coords[2], cy = coords[3]);
+                break;
+            case PathIterator.SEG_CUBICTO:
+                addDashCubic(cx, cy, coords[0], coords[1], coords[2], coords[3], cx = coords[4], cy = coords[5]);
+                break;
+            case PathIterator.SEG_CLOSE:
+                addDashLine(cx, cy, cx = mx, cy = my);
+
+                if (dasher.isConnected()) {
+                    // Connect current and head segments
+                    addJoin(lp, fmx, fmy, sp.xMove, sp.yMove, true);
+                    lp.join(sp);
+                    addJoin(lp, fmx, fmy, rp.xLast, rp.yLast, true);
+                    lp.combine(rp);
+                    addCap(lp, smx, smy, lp.xMove, lp.yMove);
+                    lp.closePath();
+                    dst.append(lp);
+                    sp = null;
+                } else {
+                    closeDashedShape();
+                }
+
+                isClosed = true;
+                break;
+            }
+            p.next();
+        }
+
+        if (!isClosed) {
+            closeDashedShape();
+        }
+
+    }
+
+    /**
+     * Closes dashed shape path.
+     */
+    void closeDashedShape() {
+        // Add head segment
+        if (sp != null) {
+            addCap(sp, fmx, fmy, sp.xMove, sp.yMove);
+            sp.closePath();
+            dst.append(sp);
+        }
+        if (lp.typeSize > 0) {
+            // Close current segment
+            if (!dasher.isClosed()) {
+                addCap(lp, scx, scy, rp.xLast, rp.yLast);
+                lp.combine(rp);
+                addCap(lp, smx, smy, lp.xMove, lp.yMove);
+                lp.closePath();
+            }
+            dst.append(lp);
+        }
+    }
+
+    /**
+     * Adds cap to the work path.
+     * 
+     * @param p - the BufferedPath object of work path
+     * @param x0 - the x coordinate of the source path
+     * @param y0 - the y coordinate on the source path
+     * @param x2 - the x coordinate of the next point on the work path
+     * @param y2 - the y coordinate of the next point on the work path
+     */
+    void addCap(BufferedPath p, double x0, double y0, double x2, double y2) {
+        double x1 = p.xLast;
+        double y1 = p.yLast;
+        double x10 = x1 - x0;
+        double y10 = y1 - y0;
+        double x20 = x2 - x0;
+        double y20 = y2 - y0;
+
+        switch(cap) {
+        case CAP_BUTT:
+            p.lineTo(x2, y2);
+            break;
+        case CAP_ROUND:
+            double mx = x10 * CUBIC_ARC;
+            double my = y10 * CUBIC_ARC;
+
+            double x3 = x0 + y10;
+            double y3 = y0 - x10;
+
+            x10 *= CUBIC_ARC;
+            y10 *= CUBIC_ARC;
+            x20 *= CUBIC_ARC;
+            y20 *= CUBIC_ARC;
+
+            p.cubicTo(x1 + y10, y1 - x10, x3 + mx, y3 + my, x3, y3);
+            p.cubicTo(x3 - mx, y3 - my, x2 - y20, y2 + x20, x2, y2);
+            break;
+        case CAP_SQUARE:
+            p.lineTo(x1 + y10, y1 - x10);
+            p.lineTo(x2 - y20, y2 + x20);
+            p.lineTo(x2, y2);
+            break;
+        }
+    }
+
+    /**
+     * Adds bevel and miter join to the work path.
+     * 
+     * @param p - the BufferedPath object of work path
+     * @param x0 - the x coordinate of the source path
+     * @param y0 - the y coordinate on the source path
+     * @param x2 - the x coordinate of the next point on the work path
+     * @param y2 - the y coordinate of the next point on the work path
+     * @param isLeft - the orientation of work path, true if work path lies to the left from source path, false otherwise
+     */
+    void addJoin(BufferedPath p, double x0, double y0, double x2, double y2, boolean isLeft) {
+        double x1 = p.xLast;
+        double y1 = p.yLast;
+        double x10 = x1 - x0;
+        double y10 = y1 - y0;
+        double x20 = x2 - x0;
+        double y20 = y2 - y0;
+        double sin0 = x10 * y20 - y10 * x20;
+
+        // Small corner
+        if (-cornerDelta < sin0 && sin0 < cornerDelta) {
+            double cos0 = x10 * x20 + y10 * y20;
+            if (cos0 > 0.0) {
+                // if zero corner do nothing
+                if (-zeroDelta > sin0 || sin0 > zeroDelta) {
+                    double x3 = x0 + w2 * w2 * (y20 - y10) / sin0;
+                    double y3 = y0 + w2 * w2 * (x10 - x20) / sin0;
+                    p.setLast(x3, y3);
+                }
+                return;
+            }
+            // Zero corner
+            if (-zeroDelta < sin0 && sin0 < zeroDelta) {
+                p.lineTo(x2, y2);
+            }
+            return;
+        }
+
+        if (isLeft ^ (sin0 < 0.0)) {
+            // Twisted corner
+            p.lineTo(x0, y0);
+            p.lineTo(x2, y2);
+        } else {
+            switch(join) {
+            case JOIN_BEVEL:
+                p.lineTo(x2, y2);
+                break;
+            case JOIN_MITER:
+                double s1 = x1 * x10 + y1 * y10;
+                double s2 = x2 * x20 + y2 * y20;
+                double x3 = (s1 * y20 - s2 * y10) / sin0;
+                double y3 = (s2 * x10 - s1 * x20) / sin0;
+                double x30 = x3 - x0;
+                double y30 = y3 - y0;
+                double miterLength = Math.sqrt(x30 * x30 + y30 * y30);
+                if (miterLength < miterLimit * w2) {
+                    p.lineTo(x3, y3);
+                }
+                p.lineTo(x2, y2);
+                break;
+            case JOIN_ROUND:
+                addRoundJoin(p, x0, y0, x2, y2, isLeft);
+                break;
+            }
+        }
+    }
+
+    /**
+     * Adds round join to the work path.
+     * 
+     * @param p - the BufferedPath object of work path
+     * @param x0 - the x coordinate of the source path
+     * @param y0 - the y coordinate on the source path
+     * @param x2 - the x coordinate of the next point on the work path
+     * @param y2 - the y coordinate of the next point on the work path
+     * @param isLeft - the orientation of work path, true if work path lies to the left from source path, false otherwise
+     */
+    void addRoundJoin(BufferedPath p, double x0, double y0, double x2, double y2, boolean isLeft) {
+        double x1 = p.xLast;
+        double y1 = p.yLast;
+        double x10 = x1 - x0;
+        double y10 = y1 - y0;
+        double x20 = x2 - x0;
+        double y20 = y2 - y0;
+
+        double x30 = x10 + x20;
+        double y30 = y10 + y20;
+
+        double l30 = Math.sqrt(x30 * x30 + y30 * y30);
+
+        if (l30 < 1E-5) {
+            p.lineTo(x2, y2);
+            return;
+        }
+
+        double w = w2 / l30;
+
+        x30 *= w;
+        y30 *= w;
+
+        double x3 = x0 + x30;
+        double y3 = y0 + y30;
+
+        double cos = x10 * x20 + y10 * y20;
+        double a = Math.acos(cos / (w2 * w2));
+        if (cos >= 0.0) {
+            double k = 4.0 / 3.0 * Math.tan(a / 4.0);
+            if (isLeft) {
+                k = -k;
+            }
+
+            x10 *= k;
+            y10 *= k;
+            x20 *= k;
+            y20 *= k;
+
+            p.cubicTo(x1 - y10, y1 + x10, x2 + y20, y2 - x20, x2, y2);
+        } else {
+            double k = 4.0 / 3.0 * Math.tan(a / 8.0);
+            if (isLeft) {
+                k = -k;
+            }
+
+            x10 *= k;
+            y10 *= k;
+            x20 *= k;
+            y20 *= k;
+            x30 *= k;
+            y30 *= k;
+
+            p.cubicTo(x1 - y10, y1 + x10, x3 + y30, y3 - x30, x3, y3);
+            p.cubicTo(x3 - y30, y3 + x30, x2 + y20, y2 - x20, x2, y2);
+        }
+
+    }
+
+    /**
+     * Adds solid line segment to the work path.
+     * 
+     * @param x1 - the x coordinate of the start line point
+     * @param y1 - the y coordinate of the start line point
+     * @param x2 - the x coordinate of the end line point
+     * @param y2 - the y coordinate of the end line point
+     * @param zero - if true it's allowable to add zero length line segment
+     */
+    void addLine(double x1, double y1, double x2, double y2, boolean zero) {
+        double dx = x2 - x1;
+        double dy = y2 - y1;
+
+        if (dx == 0.0 && dy == 0.0) {
+            if (!zero) {
+                return;
+            }
+            dx = w2;
+            dy = 0;
+        } else {
+            double w = w2 / Math.sqrt(dx * dx + dy * dy);
+            dx *= w;
+            dy *= w;
+        }
+
+        double lx1 = x1 - dy;
+        double ly1 = y1 + dx;
+        double rx1 = x1 + dy;
+        double ry1 = y1 - dx;
+
+        if (checkMove) {
+            if (isMove) {
+                isMove = false;
+                lp.moveTo(lx1, ly1);
+                rp.moveTo(rx1, ry1);
+            } else {
+                addJoin(lp, x1, y1, lx1, ly1, true);
+                addJoin(rp, x1, y1, rx1, ry1, false);
+            }
+        }
+
+        lp.lineTo(x2 - dy, y2 + dx);
+        rp.lineTo(x2 + dy, y2 - dx);
+    }
+
+    /**
+     * Adds solid quad segment to the work path.
+     * 
+     * @param x1 - the x coordinate of the first control point
+     * @param y1 - the y coordinate of the first control point
+     * @param x2 - the x coordinate of the second control point
+     * @param y2 - the y coordinate of the second control point
+     * @param x3 - the x coordinate of the third control point
+     * @param y3 - the y coordinate of the third control point
+     */
+    void addQuad(double x1, double y1, double x2, double y2, double x3, double y3) {
+        double x21 = x2 - x1;
+        double y21 = y2 - y1;
+        double x23 = x2 - x3;
+        double y23 = y2 - y3;
+
+        double l21 = Math.sqrt(x21 * x21 + y21 * y21);
+        double l23 = Math.sqrt(x23 * x23 + y23 * y23);
+
+        if (l21 == 0.0 && l23 == 0.0) {
+            addLine(x1, y1, x3, y3, false);
+            return;
+        }
+
+        if (l21 == 0.0) {
+            addLine(x2, y2, x3, y3, false);
+            return;
+        }
+
+        if (l23 == 0.0) {
+            addLine(x1, y1, x2, y2, false);
+            return;
+        }
+
+        double w;
+        w = w2 / l21;
+        double mx1 = - y21 * w;
+        double my1 =   x21 * w;
+        w = w2 / l23;
+        double mx3 =   y23 * w;
+        double my3 = - x23 * w;
+
+        double lx1 = x1 + mx1;
+        double ly1 = y1 + my1;
+        double rx1 = x1 - mx1;
+        double ry1 = y1 - my1;
+
+        if (checkMove) {
+            if (isMove) {
+                isMove = false;
+                lp.moveTo(lx1, ly1);
+                rp.moveTo(rx1, ry1);
+            } else {
+                addJoin(lp, x1, y1, lx1, ly1, true);
+                addJoin(rp, x1, y1, rx1, ry1, false);
+            }
+        }
+
+        if (x21 * y23 - y21 * x23 == 0.0) {
+            // On line curve
+            if (x21 * x23 + y21 * y23 > 0.0) {
+                // Twisted curve
+                if (l21 == l23) {
+                    double px = x1 + (x21 + x23) / 4.0;
+                    double py = y1 + (y21 + y23) / 4.0;
+                    lp.lineTo(px + mx1, py + my1);
+                    rp.lineTo(px - mx1, py - my1);
+                    lp.lineTo(px - mx1, py - my1);
+                    rp.lineTo(px + mx1, py + my1);
+                    lp.lineTo(x3 - mx1, y3 - my1);
+                    rp.lineTo(x3 + mx1, y3 + my1);
+                } else {
+                    double px1, py1;
+                    double k = l21 / (l21 + l23);
+                    double px = x1 + (x21 + x23) * k * k;
+                    double py = y1 + (y21 + y23) * k * k;
+                    px1 = (x1 + px) / 2.0;
+                    py1 = (y1 + py) / 2.0;
+                    lp.quadTo(px1 + mx1, py1 + my1, px + mx1, py + my1);
+                    rp.quadTo(px1 - mx1, py1 - my1, px - mx1, py - my1);
+                    lp.lineTo(px - mx1, py - my1);
+                    rp.lineTo(px + mx1, py + my1);
+                    px1 = (x3 + px) / 2.0;
+                    py1 = (y3 + py) / 2.0;
+                    lp.quadTo(px1 - mx1, py1 - my1, x3 - mx1, y3 - my1);
+                    rp.quadTo(px1 + mx1, py1 + my1, x3 + mx1, y3 + my1);
+                }
+            } else {
+                // Simple curve
+                lp.quadTo(x2 + mx1, y2 + my1, x3 + mx3, y3 + my3);
+                rp.quadTo(x2 - mx1, y2 - my1, x3 - mx3, y3 - my3);
+            }
+        } else {
+            addSubQuad(x1, y1, x2, y2, x3, y3, 0);
+        }
+    }
+
+    /**
+     * Subdivides solid quad curve to make outline for source quad segment and adds it to work path.
+     * 
+     * @param x1 - the x coordinate of the first control point
+     * @param y1 - the y coordinate of the first control point
+     * @param x2 - the x coordinate of the second control point
+     * @param y2 - the y coordinate of the second control point
+     * @param x3 - the x coordinate of the third control point
+     * @param y3 - the y coordinate of the third control point
+     * @param level - the maximum level of subdivision deepness
+     */
+    void addSubQuad(double x1, double y1, double x2, double y2, double x3, double y3, int level) {
+        double x21 = x2 - x1;
+        double y21 = y2 - y1;
+        double x23 = x2 - x3;
+        double y23 = y2 - y3;
+
+        double cos = x21 * x23 + y21 * y23;
+        double sin = x21 * y23 - y21 * x23;
+
+        if (level < MAX_LEVEL && (cos >= 0.0 || (Math.abs(sin / cos) > curveDelta))) {
+            double c1x = (x2 + x1) / 2.0;
+            double c1y = (y2 + y1) / 2.0;
+            double c2x = (x2 + x3) / 2.0;
+            double c2y = (y2 + y3) / 2.0;
+            double c3x = (c1x + c2x) / 2.0;
+            double c3y = (c1y + c2y) / 2.0;
+            addSubQuad(x1, y1, c1x, c1y, c3x, c3y, level + 1);
+            addSubQuad(c3x, c3y, c2x, c2y, x3, y3, level + 1);
+        } else {
+            double w;
+            double l21 = Math.sqrt(x21 * x21 + y21 * y21);
+            double l23 = Math.sqrt(x23 * x23 + y23 * y23);
+            w = w2 / sin;
+            double mx2 = (x21 * l23 + x23 * l21) * w;
+            double my2 = (y21 * l23 + y23 * l21) * w;
+            w = w2 / l23;
+            double mx3 =   y23 * w;
+            double my3 = - x23 * w;
+            lp.quadTo(x2 + mx2, y2 + my2, x3 + mx3, y3 + my3);
+            rp.quadTo(x2 - mx2, y2 - my2, x3 - mx3, y3 - my3);
+        }
+    }
+
+    /**
+     * Adds solid cubic segment to the work path.
+     * 
+     * @param x1 - the x coordinate of the first control point
+     * @param y1 - the y coordinate of the first control point
+     * @param x2 - the x coordinate of the second control point
+     * @param y2 - the y coordinate of the second control point
+     * @param x3 - the x coordinate of the third control point
+     * @param y3 - the y coordinate of the third control point
+     * @param x4 - the x coordinate of the fours control point
+     * @param y4 - the y coordinate of the fours control point
+     */
+    void addCubic(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) {
+        double x12 = x1 - x2;
+        double y12 = y1 - y2;
+        double x23 = x2 - x3;
+        double y23 = y2 - y3;
+        double x34 = x3 - x4;
+        double y34 = y3 - y4;
+
+        double l12 = Math.sqrt(x12 * x12 + y12 * y12);
+        double l23 = Math.sqrt(x23 * x23 + y23 * y23);
+        double l34 = Math.sqrt(x34 * x34 + y34 * y34);
+
+        // All edges are zero
+        if (l12 == 0.0 && l23 == 0.0 && l34 == 0.0) {
+            addLine(x1, y1, x4, y4, false);
+            return;
+        }
+
+        // One zero edge
+        if (l12 == 0.0 && l23 == 0.0) {
+            addLine(x3, y3, x4, y4, false);
+            return;
+        }
+
+        if (l23 == 0.0 && l34 == 0.0) {
+            addLine(x1, y1, x2, y2, false);
+            return;
+        }
+
+        if (l12 == 0.0 && l34 == 0.0) {
+            addLine(x2, y2, x3, y3, false);
+            return;
+        }
+
+        double w, mx1, my1, mx4, my4;
+        boolean onLine;
+
+        if (l12 == 0.0) {
+            w = w2 / l23;
+            mx1 =   y23 * w;
+            my1 = - x23 * w;
+            w = w2 / l34;
+            mx4 =   y34 * w;
+            my4 = - x34 * w;
+            onLine = - x23 * y34 + y23 * x34 == 0.0; // sin3
+        } else
+        if (l34 == 0.0) {
+            w = w2 / l12;
+            mx1 =   y12 * w;
+            my1 = - x12 * w;
+            w = w2 / l23;
+            mx4 =   y23 * w;
+            my4 = - x23 * w;
+            onLine = - x12 * y23 + y12 * x23 == 0.0; // sin2
+        } else {
+            w = w2 / l12;
+            mx1 =   y12 * w;
+            my1 = - x12 * w;
+            w = w2 / l34;
+            mx4 =   y34 * w;
+            my4 = - x34 * w;
+            if (l23 == 0.0) {
+                onLine = - x12 * y34 + y12 * x34 == 0.0;
+            } else {
+                onLine =
+                    - x12 * y34 + y12 * x34 == 0.0 &&
+                    - x12 * y23 + y12 * x23 == 0.0 && // sin2
+                    - x23 * y34 + y23 * x34 == 0.0;   // sin3
+            }
+        }
+
+        double lx1 = x1 + mx1;
+        double ly1 = y1 + my1;
+        double rx1 = x1 - mx1;
+        double ry1 = y1 - my1;
+
+        if (checkMove) {
+            if (isMove) {
+                isMove = false;
+                lp.moveTo(lx1, ly1);
+                rp.moveTo(rx1, ry1);
+            } else {
+                addJoin(lp, x1, y1, lx1, ly1, true);
+                addJoin(rp, x1, y1, rx1, ry1, false);
+            }
+        }
+
+        if (onLine) {
+            if ((x1 == x2 && y1 < y2) || x1 < x2) {
+                l12 = -l12;
+            }
+            if ((x2 == x3 && y2 < y3) || x2 < x3) {
+                l23 = -l23;
+            }
+            if ((x3 == x4 && y3 < y4) || x3 < x4) {
+                l34 = -l34;
+            }
+            double d = l23 * l23 - l12 * l34;
+            double roots[] = new double[3];
+            int rc = 0;
+            if (d == 0.0) {
+                double t = (l12 - l23) / (l12 + l34 - l23 - l23);
+                if (0.0 < t && t < 1.0) {
+                    roots[rc++] = t;
+                }
+            } else
+            if (d > 0.0) {
+                d = Math.sqrt(d);
+                double z = l12 + l34 - l23 - l23;
+                double t;
+                t = (l12 - l23 + d) / z;
+                if (0.0 < t && t < 1.0) {
+                    roots[rc++] = t;
+                }
+                t = (l12 - l23 - d) / z;
+                if (0.0 < t && t < 1.0) {
+                    roots[rc++] = t;
+                }
+            }
+
+            if (rc > 0) {
+                // Sort roots
+                if (rc == 2 && roots[0] > roots[1]) {
+                    double tmp = roots[0];
+                    roots[0] = roots[1];
+                    roots[1] = tmp;
+                }
+                roots[rc++] = 1.0;
+
+                double ax = - x34 - x12 + x23 + x23;
+                double ay = - y34 - y12 + y23 + y23;
+                double bx = 3.0 * (- x23 + x12);
+                double by = 3.0 * (- y23 + y12);
+                double cx = 3.0 * (- x12);
+                double cy = 3.0 * (- y12);
+                double xPrev = x1;
+                double yPrev = y1;
+                for(int i = 0; i < rc; i++) {
+                    double t = roots[i];
+                    double px = t * (t * (t * ax + bx) + cx) + x1;
+                    double py = t * (t * (t * ay + by) + cy) + y1;
+                    double px1 = (xPrev + px) / 2.0;
+                    double py1 = (yPrev + py) / 2.0;
+                    lp.cubicTo(px1 + mx1, py1 + my1, px1 + mx1, py1 + my1, px + mx1, py + my1);
+                    rp.cubicTo(px1 - mx1, py1 - my1, px1 - mx1, py1 - my1, px - mx1, py - my1);
+                    if (i < rc - 1) {
+                        lp.lineTo(px - mx1, py - my1);
+                        rp.lineTo(px + mx1, py + my1);
+                    }
+                    xPrev = px;
+                    yPrev = py;
+                    mx1 = - mx1;
+                    my1 = - my1;
+                }
+            } else {
+                lp.cubicTo(x2 + mx1, y2 + my1, x3 + mx4, y3 + my4, x4 + mx4, y4 + my4);
+                rp.cubicTo(x2 - mx1, y2 - my1, x3 - mx4, y3 - my4, x4 - mx4, y4 - my4);
+            }
+        } else {
+            addSubCubic(x1, y1, x2, y2, x3, y3, x4, y4, 0);
+        }
+    }
+
+    /**
+     * Subdivides solid cubic curve to make outline for source quad segment and adds it to work path.
+     * 
+     * @param x1 - the x coordinate of the first control point
+     * @param y1 - the y coordinate of the first control point
+     * @param x2 - the x coordinate of the second control point
+     * @param y2 - the y coordinate of the second control point
+     * @param x3 - the x coordinate of the third control point
+     * @param y3 - the y coordinate of the third control point
+     * @param x4 - the x coordinate of the fours control point
+     * @param y4 - the y coordinate of the fours control point
+     * @param level - the maximum level of subdivision deepness
+     */
+    void addSubCubic(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4, int level) {
+        double x12 = x1 - x2;
+        double y12 = y1 - y2;
+        double x23 = x2 - x3;
+        double y23 = y2 - y3;
+        double x34 = x3 - x4;
+        double y34 = y3 - y4;
+
+        double cos2 = - x12 * x23 - y12 * y23;
+        double cos3 = - x23 * x34 - y23 * y34;
+        double sin2 = - x12 * y23 + y12 * x23;
+        double sin3 = - x23 * y34 + y23 * x34;
+        double sin0 = - x12 * y34 + y12 * x34;
+        double cos0 = - x12 * x34 - y12 * y34;
+
+        if (level < MAX_LEVEL && (sin2 != 0.0 || sin3 != 0.0 || sin0 != 0.0) &&
+            (cos2 >= 0.0 || cos3 >= 0.0 || cos0 >= 0.0 ||
+            (Math.abs(sin2 / cos2) > curveDelta) ||
+            (Math.abs(sin3 / cos3) > curveDelta) ||
+            (Math.abs(sin0 / cos0) > curveDelta)))
+        {
+            double cx = (x2 + x3) / 2.0;
+            double cy = (y2 + y3) / 2.0;
+            double lx2 = (x2 + x1) / 2.0;
+            double ly2 = (y2 + y1) / 2.0;
+            double rx3 = (x3 + x4) / 2.0;
+            double ry3 = (y3 + y4) / 2.0;
+            double lx3 = (cx + lx2) / 2.0;
+            double ly3 = (cy + ly2) / 2.0;
+            double rx2 = (cx + rx3) / 2.0;
+            double ry2 = (cy + ry3) / 2.0;
+            cx = (lx3 + rx2) / 2.0;
+            cy = (ly3 + ry2) / 2.0;
+            addSubCubic(x1, y1, lx2, ly2, lx3, ly3, cx, cy, level + 1);
+            addSubCubic(cx, cy, rx2, ry2, rx3, ry3, x4, y4, level + 1);
+        } else {
+            double w, mx1, my1, mx2, my2, mx3, my3, mx4, my4;
+            double l12 = Math.sqrt(x12 * x12 + y12 * y12);
+            double l23 = Math.sqrt(x23 * x23 + y23 * y23);
+            double l34 = Math.sqrt(x34 * x34 + y34 * y34);
+
+            if (l12 == 0.0) {
+                w = w2 / l23;
+                mx1 =   y23 * w;
+                my1 = - x23 * w;
+                w = w2 / l34;
+                mx4 =   y34 * w;
+                my4 = - x34 * w;
+            } else
+            if (l34 == 0.0) {
+                w = w2 / l12;
+                mx1 =   y12 * w;
+                my1 = - x12 * w;
+                w = w2 / l23;
+                mx4 =   y23 * w;
+                my4 = - x23 * w;
+            } else {
+                // Common case
+                w = w2 / l12;
+                mx1 =   y12 * w;
+                my1 = - x12 * w;
+                w = w2 / l34;
+                mx4 =   y34 * w;
+                my4 = - x34 * w;
+            }
+
+            if (sin2 == 0.0) {
+                mx2 = mx1;
+                my2 = my1;
+            } else {
+                w = w2 / sin2;
+                mx2 = -(x12 * l23 - x23 * l12) * w;
+                my2 = -(y12 * l23 - y23 * l12) * w;
+            }
+            if (sin3 == 0.0) {
+                mx3 = mx4;
+                my3 = my4;
+            } else {
+                w = w2 / sin3;
+                mx3 = -(x23 * l34 - x34 * l23) * w;
+                my3 = -(y23 * l34 - y34 * l23) * w;
+            }
+
+            lp.cubicTo(x2 + mx2, y2 + my2, x3 + mx3, y3 + my3, x4 + mx4, y4 + my4);
+            rp.cubicTo(x2 - mx2, y2 - my2, x3 - mx3, y3 - my3, x4 - mx4, y4 - my4);
+        }
+    }
+
+    /**
+     * Adds dashed line segment to the work path.
+     * 
+     * @param x1 - the x coordinate of the start line point
+     * @param y1 - the y coordinate of the start line point
+     * @param x2 - the x coordinate of the end line point
+     * @param y2 - the y coordinate of the end line point
+     */
+    void addDashLine(double x1, double y1, double x2, double y2) {
+        double x21 = x2 - x1;
+        double y21 = y2 - y1;
+
+        double l21 = Math.sqrt(x21 * x21 + y21 * y21);
+
+        if (l21 == 0.0) {
+            return;
+        }
+
+        double px1, py1;
+        px1 = py1 = 0.0;
+        double w = w2 / l21;
+        double mx = - y21 * w;
+        double my =   x21 * w;
+
+        dasher.init(new DashIterator.Line(l21));
+
+        while(!dasher.eof()) {
+            double t = dasher.getValue();
+            scx = x1 + t * x21;
+            scy = y1 + t * y21;
+
+            if (dasher.isOpen()) {
+                px1 = scx;
+                py1 = scy;
+                double lx1 = px1 + mx;
+                double ly1 = py1 + my;
+                double rx1 = px1 - mx;
+                double ry1 = py1 - my;
+                if (isMove) {
+                    isMove = false;
+                    smx = px1;
+                    smy = py1;
+                    rp.clean();
+                    lp.moveTo(lx1, ly1);
+                    rp.moveTo(rx1, ry1);
+                } else {
+                    addJoin(lp, x1, y1, lx1, ly1, true);
+                    addJoin(rp, x1, y1, rx1, ry1, false);
+                }
+            } else
+                if (dasher.isContinue()) {
+                    double px2 = scx;
+                    double py2 = scy;
+                    lp.lineTo(px2 + mx, py2 + my);
+                    rp.lineTo(px2 - mx, py2 - my);
+                    if (dasher.close) {
+                        addCap(lp, px2, py2, rp.xLast, rp.yLast);
+                        lp.combine(rp);
+                        if (isFirst) {
+                            isFirst = false;
+                            fmx = smx;
+                            fmy = smy;
+                            sp = lp;
+                            lp = new BufferedPath();
+                        } else {
+                            addCap(lp, smx, smy, lp.xMove, lp.yMove);
+                            lp.closePath();
+                        }
+                        isMove = true;
+                    }
+                }
+
+            dasher.next();
+        }
+    }
+
+    /**
+     * Adds dashed quad segment to the work path.
+     * 
+     * @param x1 - the x coordinate of the first control point
+     * @param y1 - the y coordinate of the first control point
+     * @param x2 - the x coordinate of the second control point
+     * @param y2 - the y coordinate of the second control point
+     * @param x3 - the x coordinate of the third control point
+     * @param y3 - the y coordinate of the third control point
+     */
+    void addDashQuad(double x1, double y1, double x2, double y2, double x3, double y3) {
+
+        double x21 = x2 - x1;
+        double y21 = y2 - y1;
+        double x23 = x2 - x3;
+        double y23 = y2 - y3;
+
+        double l21 = Math.sqrt(x21 * x21 + y21 * y21);
+        double l23 = Math.sqrt(x23 * x23 + y23 * y23);
+
+        if (l21 == 0.0 && l23 == 0.0) {
+            return;
+        }
+
+        if (l21 == 0.0) {
+            addDashLine(x2, y2, x3, y3);
+            return;
+        }
+
+        if (l23 == 0.0) {
+            addDashLine(x1, y1, x2, y2);
+            return;
+        }
+
+        double ax = x1 + x3 - x2 - x2;
+        double ay = y1 + y3 - y2 - y2;
+        double bx = x2 - x1;
+        double by = y2 - y1;
+        double cx = x1;
+        double cy = y1;
+
+        double px1, py1, dx1, dy1;
+        px1 = py1 = dx1 = dy1 = 0.0;
+        double prev = 0.0;
+
+        dasher.init(new DashIterator.Quad(x1, y1, x2, y2, x3, y3));
+
+        while(!dasher.eof()) {
+            double t = dasher.getValue();
+            double dx = t * ax + bx;
+            double dy = t * ay + by;
+            scx = t * (dx + bx) + cx; // t^2 * ax + 2.0 * t * bx + cx
+            scy = t * (dy + by) + cy; // t^2 * ay + 2.0 * t * by + cy
+            if (dasher.isOpen()) {
+                px1 = scx;
+                py1 = scy;
+                dx1 = dx;
+                dy1 = dy;
+                double w = w2 / Math.sqrt(dx1 * dx1 + dy1 * dy1);
+                double mx1 = - dy1 * w;
+                double my1 =   dx1 * w;
+                double lx1 = px1 + mx1;
+                double ly1 = py1 + my1;
+                double rx1 = px1 - mx1;
+                double ry1 = py1 - my1;
+                if (isMove) {
+                    isMove = false;
+                    smx = px1;
+                    smy = py1;
+                    rp.clean();
+                    lp.moveTo(lx1, ly1);
+                    rp.moveTo(rx1, ry1);
+                } else {
+                    addJoin(lp, x1, y1, lx1, ly1, true);
+                    addJoin(rp, x1, y1, rx1, ry1, false);
+                }
+            } else 
+                if (dasher.isContinue()) {
+                    double px3 = scx;
+                    double py3 = scy;
+                    double sx = x2 - x23 * prev;
+                    double sy = y2 - y23 * prev;
+                    double t2 = (t - prev) / (1 - prev);
+                    double px2 = px1 + (sx - px1) * t2;
+                    double py2 = py1 + (sy - py1) * t2;
+
+                    addQuad(px1, py1, px2, py2, px3, py3);
+                    if (dasher.isClosed()) {
+                        addCap(lp, px3, py3, rp.xLast, rp.yLast);
+                        lp.combine(rp);
+                        if (isFirst) {
+                            isFirst = false;
+                            fmx = smx;
+                            fmy = smy;
+                            sp = lp;
+                            lp = new BufferedPath();
+                        } else {
+                            addCap(lp, smx, smy, lp.xMove, lp.yMove);
+                            lp.closePath();
+                        }
+                        isMove = true;
+                    }
+                }
+
+            prev = t;
+            dasher.next();
+        }
+    }
+
+    /**
+     * Adds dashed cubic segment to the work path.
+     * 
+     * @param x1 - the x coordinate of the first control point
+     * @param y1 - the y coordinate of the first control point
+     * @param x2 - the x coordinate of the second control point
+     * @param y2 - the y coordinate of the second control point
+     * @param x3 - the x coordinate of the third control point
+     * @param y3 - the y coordinate of the third control point
+     * @param x4 - the x coordinate of the fours control point
+     * @param y4 - the y coordinate of the fours control point
+     */
+    void addDashCubic(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) {
+
+        double x12 = x1 - x2;
+        double y12 = y1 - y2;
+        double x23 = x2 - x3;
+        double y23 = y2 - y3;
+        double x34 = x3 - x4;
+        double y34 = y3 - y4;
+
+        double l12 = Math.sqrt(x12 * x12 + y12 * y12);
+        double l23 = Math.sqrt(x23 * x23 + y23 * y23);
+        double l34 = Math.sqrt(x34 * x34 + y34 * y34);
+
+        // All edges are zero
+        if (l12 == 0.0 && l23 == 0.0 && l34 == 0.0) {
+            // NOTHING
+            return;
+        }
+
+        // One zero edge
+        if (l12 == 0.0 && l23 == 0.0) {
+            addDashLine(x3, y3, x4, y4);
+            return;
+        }
+
+        if (l23 == 0.0 && l34 == 0.0) {
+            addDashLine(x1, y1, x2, y2);
+            return;
+        }
+
+        if (l12 == 0.0 && l34 == 0.0) {
+            addDashLine(x2, y2, x3, y3);
+            return;
+        }
+
+        double ax = x4 - x1 + 3.0 * (x2 - x3);
+        double ay = y4 - y1 + 3.0 * (y2 - y3);
+        double bx = 3.0 * (x1 + x3 - x2 - x2);
+        double by = 3.0 * (y1 + y3 - y2 - y2);
+        double cx = 3.0 * (x2 - x1);
+        double cy = 3.0 * (y2 - y1);
+        double dx = x1;
+        double dy = y1;
+
+        double px1 = 0.0;
+        double py1 = 0.0;
+        double prev = 0.0;
+
+        dasher.init(new DashIterator.Cubic(x1, y1, x2, y2, x3, y3, x4, y4));
+
+        while(!dasher.eof()) {
+
+            double t = dasher.getValue();
+            scx = t * (t * (t * ax + bx) + cx) + dx;
+            scy = t * (t * (t * ay + by) + cy) + dy;
+            if (dasher.isOpen()) {
+                px1 = scx;
+                py1 = scy;
+                double dx1 = t * (t * (ax + ax + ax) + bx + bx) + cx;
+                double dy1 = t * (t * (ay + ay + ay) + by + by) + cy;
+                double w = w2 / Math.sqrt(dx1 * dx1 + dy1 * dy1);
+                double mx1 = - dy1 * w;
+                double my1 =   dx1 * w;
+                double lx1 = px1 + mx1;
+                double ly1 = py1 + my1;
+                double rx1 = px1 - mx1;
+                double ry1 = py1 - my1;
+                if (isMove) {
+                    isMove = false;
+                    smx = px1;
+                    smy = py1;
+                    rp.clean();
+                    lp.moveTo(lx1, ly1);
+                    rp.moveTo(rx1, ry1);
+                } else {
+                    addJoin(lp, x1, y1, lx1, ly1, true);
+                    addJoin(rp, x1, y1, rx1, ry1, false);
+                }
+            } else 
+                if (dasher.isContinue()) {
+                    double sx1 = x2 - x23 * prev;
+                    double sy1 = y2 - y23 * prev;
+                    double sx2 = x3 - x34 * prev;
+                    double sy2 = y3 - y34 * prev;
+                    double sx3 = sx1 + (sx2 - sx1) * prev;
+                    double sy3 = sy1 + (sy2 - sy1) * prev;
+                    double t2 = (t - prev) / (1 - prev);
+                    double sx4 = sx3 + (sx2 - sx3) * t2;
+                    double sy4 = sy3 + (sy2 - sy3) * t2;
+
+                    double px4 = scx;
+                    double py4 = scy;
+                    double px2 = px1 + (sx3 - px1) * t2;
+                    double py2 = py1 + (sy3 - py1) * t2;
+                    double px3 = px2 + (sx4 - px2) * t2;
+                    double py3 = py2 + (sy4 - py2) * t2;
+
+                    addCubic(px1, py1, px2, py2, px3, py3, px4, py4);
+                    if (dasher.isClosed()) {
+                        addCap(lp, px4, py4, rp.xLast, rp.yLast);
+                        lp.combine(rp);
+                        if (isFirst) {
+                            isFirst = false;
+                            fmx = smx;
+                            fmy = smy;
+                            sp = lp;
+                            lp = new BufferedPath();
+                        } else {
+                            addCap(lp, smx, smy, lp.xMove, lp.yMove);
+                            lp.closePath();
+                        }
+                        isMove = true;
+                    }
+                }
+
+            prev = t;
+            dasher.next();
+        }
+    }
+
+    /**
+     * Dasher class provides dashing for particular dash style.
+     */
+    class Dasher {
+        
+        /** The pos. */
+        double pos;
+        
+        /** The first. */
+        boolean close, visible, first;
+        
+        /** The dash. */
+        float dash[];
+        
+        /** The phase. */
+        float phase;
+        
+        /** The index. */
+        int index;
+        
+        /** The iter. */
+        DashIterator iter;
+        
+        /**
+         * Instantiates a new dasher.
+         * 
+         * @param dash the dash
+         * @param phase the phase
+         */
+        Dasher(float dash[], float phase) {
+            this.dash = dash;
+            this.phase = phase;
+            index = 0;
+            pos = phase;
+            visible = true;
+            while (pos >= dash[index]) {
+                visible = !visible;
+                pos -= dash[index];
+                index = (index + 1) % dash.length;
+            }            
+            pos = -pos;
+            first = visible;
+        }
+        
+        /**
+         * Inits the.
+         * 
+         * @param iter the iter
+         */
+        void init(DashIterator iter) {
+            this.iter = iter;
+            close = true;
+        }
+        
+        /**
+         * Checks if is open.
+         * 
+         * @return true, if is open
+         */
+        boolean isOpen() {
+            return visible && pos < iter.length;
+        }
+        
+        /**
+         * Checks if is continue.
+         * 
+         * @return true, if is continue
+         */
+        boolean isContinue() {
+            return !visible && pos > 0;
+        }
+        
+        /**
+         * Checks if is closed.
+         * 
+         * @return true, if is closed
+         */
+        boolean isClosed() {
+            return close;
+        }
+        
+        /**
+         * Checks if is connected.
+         * 
+         * @return true, if is connected
+         */
+        boolean isConnected() {
+            return first && !close;
+        }
+
+        /**
+         * Eof.
+         * 
+         * @return true, if successful
+         */
+        boolean eof() {
+            if (!close) {
+                pos -= iter.length;
+                return true;
+            }
+            if (pos >= iter.length) {
+                if (visible) {
+                    pos -= iter.length;
+                    return true;
+                }
+                close = pos == iter.length;
+            }
+            return false;
+        }
+        
+        /**
+         * Next.
+         */
+        void next() {
+            if (close) {
+                pos += dash[index];
+                index = (index + 1) % dash.length;
+            } else {
+                // Go back
+                index = (index + dash.length - 1) % dash.length;
+                pos -= dash[index];
+            }
+            visible = !visible;
+        }
+        
+        /**
+         * Gets the value.
+         * 
+         * @return the value
+         */
+        double getValue() {
+            double t = iter.getNext(pos);
+            return t < 0 ? 0 : (t > 1 ? 1 : t);
+        }
+        
+    }
+
+    /**
+     * DashIterator class provides dashing for particular segment type.
+     */
+    static abstract class DashIterator {
+
+        /** The Constant FLATNESS. */
+        static final double FLATNESS = 1.0;
+
+        /**
+         * The Class Line.
+         */
+        static class Line extends DashIterator {
+
+            /**
+             * Instantiates a new line.
+             * 
+             * @param len the len
+             */
+            Line(double len) {
+                length = len;
+            }
+
+            @Override
+            double getNext(double dashPos) {
+                return dashPos / length;
+            }
+
+        }
+
+        /**
+         * The Class Quad.
+         */
+        static class Quad extends DashIterator {
+
+            /** The val size. */
+            int valSize;
+            
+            /** The val pos. */
+            int valPos;
+            
+            /** The cur len. */
+            double curLen;
+            
+            /** The prev len. */
+            double prevLen;
+            
+            /** The last len. */
+            double lastLen;
+            
+            /** The values. */
+            double[] values;
+            
+            /** The step. */
+            double step;
+
+            /**
+             * Instantiates a new quad.
+             * 
+             * @param x1 the x1
+             * @param y1 the y1
+             * @param x2 the x2
+             * @param y2 the y2
+             * @param x3 the x3
+             * @param y3 the y3
+             */
+            Quad(double x1, double y1, double x2, double y2, double x3, double y3) {
+
+                double nx = x1 + x3 - x2 - x2;
+                double ny = y1 + y3 - y2 - y2;
+
+                int n = (int)(1 + Math.sqrt(0.75 * (Math.abs(nx) + Math.abs(ny)) * FLATNESS));
+                step = 1.0 / n;
+
+                double ax = x1 + x3 - x2 - x2;
+                double ay = y1 + y3 - y2 - y2;
+                double bx = 2.0 * (x2 - x1);
+                double by = 2.0 * (y2 - y1);
+
+                double dx1 = step * (step * ax + bx);
+                double dy1 = step * (step * ay + by);
+                double dx2 = step * (step * ax * 2.0);
+                double dy2 = step * (step * ay * 2.0);
+                double vx = x1;
+                double vy = y1;
+
+                valSize = n;
+                values = new double[valSize];
+                double pvx = vx;
+                double pvy = vy;
+                length = 0.0;
+                for(int i = 0; i < n; i++) {
+                    vx += dx1;
+                    vy += dy1;
+                    dx1 += dx2;
+                    dy1 += dy2;
+                    double lx = vx - pvx;
+                    double ly = vy - pvy;
+                    values[i] = Math.sqrt(lx * lx + ly * ly);
+                    length += values[i];
+                    pvx = vx;
+                    pvy = vy;
+                }
+
+                valPos = 0;
+                curLen = 0.0;
+                prevLen = 0.0;
+            }
+
+            @Override
+            double getNext(double dashPos) {
+                double t = 2.0;
+                while (curLen <= dashPos && valPos < valSize) {
+                    prevLen = curLen;
+                    curLen += lastLen = values[valPos++];
+                }
+                if (curLen > dashPos) {
+                    t = (valPos - 1 + (dashPos - prevLen) / lastLen) * step;
+                }
+                return t;
+            }
+
+        }
+
+        /**
+         * The Class Cubic.
+         */
+        static class Cubic extends DashIterator {
+
+            /** The val size. */
+            int valSize;
+            
+            /** The val pos. */
+            int valPos;
+            
+            /** The cur len. */
+            double curLen;
+            
+            /** The prev len. */
+            double prevLen;
+            
+            /** The last len. */
+            double lastLen;
+            
+            /** The values. */
+            double[] values;
+            
+            /** The step. */
+            double step;
+
+            /**
+             * Instantiates a new cubic.
+             * 
+             * @param x1 the x1
+             * @param y1 the y1
+             * @param x2 the x2
+             * @param y2 the y2
+             * @param x3 the x3
+             * @param y3 the y3
+             * @param x4 the x4
+             * @param y4 the y4
+             */
+            Cubic(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) {
+
+                double nx1 = x1 + x3 - x2 - x2;
+                double ny1 = y1 + y3 - y2 - y2;
+                double nx2 = x2 + x4 - x3 - x3;
+                double ny2 = y2 + y4 - y3 - y3;
+
+                double max = Math.max(Math.abs(nx1) + Math.abs(ny1), Math.abs(nx2) + Math.abs(ny2));
+                int n = (int)(1 + Math.sqrt(0.75 * max) * FLATNESS);
+                step = 1.0 / n;
+
+                double ax = x4 - x1 + 3.0 * (x2 - x3);
+                double ay = y4 - y1 + 3.0 * (y2 - y3);
+                double bx = 3.0 * (x1 + x3 - x2 - x2);
+                double by = 3.0 * (y1 + y3 - y2 - y2);
+                double cx = 3.0 * (x2 - x1);
+                double cy = 3.0 * (y2 - y1);
+
+                double dx1 = step * (step * (step * ax + bx) + cx);
+                double dy1 = step * (step * (step * ay + by) + cy);
+                double dx2 = step * (step * (step * ax * 6.0 + bx * 2.0));
+                double dy2 = step * (step * (step * ay * 6.0 + by * 2.0));
+                double dx3 = step * (step * (step * ax * 6.0));
+                double dy3 = step * (step * (step * ay * 6.0));
+                double vx = x1;
+                double vy = y1;
+
+                valSize = n;
+                values = new double[valSize];
+                double pvx = vx;
+                double pvy = vy;
+                length = 0.0;
+                for(int i = 0; i < n; i++) {
+                    vx += dx1;
+                    vy += dy1;
+                    dx1 += dx2;
+                    dy1 += dy2;
+                    dx2 += dx3;
+                    dy2 += dy3;
+                    double lx = vx - pvx;
+                    double ly = vy - pvy;
+                    values[i] = Math.sqrt(lx * lx + ly * ly);
+                    length += values[i];
+                    pvx = vx;
+                    pvy = vy;
+                }
+
+                valPos = 0;
+                curLen = 0.0;
+                prevLen = 0.0;
+            }
+
+            @Override
+            double getNext(double dashPos) {
+                double t = 2.0;
+                while (curLen <= dashPos && valPos < valSize) {
+                    prevLen = curLen;
+                    curLen += lastLen = values[valPos++];
+                }
+                if (curLen > dashPos) {
+                    t = (valPos - 1 + (dashPos - prevLen) / lastLen) * step;
+                }
+                return t;
+            }
+
+        }
+
+        /** The length. */
+        double length;
+
+        /**
+         * Gets the next.
+         * 
+         * @param dashPos the dash pos
+         * 
+         * @return the next
+         */
+        abstract double getNext(double dashPos);
+
+    }
+
+    /**
+     * BufferedPath class provides work path storing and processing.
+     */
+    static class BufferedPath {
+
+        /** The Constant bufCapacity. */
+        private static final int bufCapacity = 10;
+
+        /** The point shift. */
+        static int pointShift[] = {
+                2,  // MOVETO
+                2,  // LINETO
+                4,  // QUADTO
+                6,  // CUBICTO
+                0}; // CLOSE
+
+        /** The types. */
+        byte[] types;
+        
+        /** The points. */
+        float[] points;
+        
+        /** The type size. */
+        int typeSize;
+        
+        /** The point size. */
+        int pointSize;
+
+        /** The x last. */
+        float xLast;
+        
+        /** The y last. */
+        float yLast;
+        
+        /** The x move. */
+        float xMove;
+        
+        /** The y move. */
+        float yMove;
+
+        /**
+         * Instantiates a new buffered path.
+         */
+        public BufferedPath() {
+            types = new byte[bufCapacity];
+            points = new float[bufCapacity * 2];
+        }
+
+        /**
+         * Check buf.
+         * 
+         * @param typeCount the type count
+         * @param pointCount the point count
+         */
+        void checkBuf(int typeCount, int pointCount) {
+            if (typeSize + typeCount > types.length) {
+                byte tmp[] = new byte[typeSize + Math.max(bufCapacity, typeCount)];
+                System.arraycopy(types, 0, tmp, 0, typeSize);
+                types = tmp;
+            }
+            if (pointSize + pointCount > points.length) {
+                float tmp[] = new float[pointSize + Math.max(bufCapacity * 2, pointCount)];
+                System.arraycopy(points, 0, tmp, 0, pointSize);
+                points = tmp;
+            }
+        }
+
+        /**
+         * Checks if is empty.
+         * 
+         * @return true, if is empty
+         */
+        boolean isEmpty() {
+            return typeSize == 0;
+        }
+
+        /**
+         * Clean.
+         */
+        void clean() {
+            typeSize = 0;
+            pointSize = 0;
+        }
+
+        /**
+         * Move to.
+         * 
+         * @param x the x
+         * @param y the y
+         */
+        void moveTo(double x, double y) {
+            checkBuf(1, 2);
+            types[typeSize++] = PathIterator.SEG_MOVETO;
+            points[pointSize++] = xMove = (float)x;
+            points[pointSize++] = yMove = (float)y;
+        }
+
+        /**
+         * Line to.
+         * 
+         * @param x the x
+         * @param y the y
+         */
+        void lineTo(double x, double y) {
+            checkBuf(1, 2);
+            types[typeSize++] = PathIterator.SEG_LINETO;
+            points[pointSize++] = xLast = (float)x;
+            points[pointSize++] = yLast = (float)y;
+        }
+
+        /**
+         * Quad to.
+         * 
+         * @param x1 the x1
+         * @param y1 the y1
+         * @param x2 the x2
+         * @param y2 the y2
+         */
+        void quadTo(double x1, double y1, double x2, double y2) {
+            checkBuf(1, 4);
+            types[typeSize++] = PathIterator.SEG_QUADTO;
+            points[pointSize++] = (float)x1;
+            points[pointSize++] = (float)y1;
+            points[pointSize++] = xLast = (float)x2;
+            points[pointSize++] = yLast = (float)y2;
+        }
+
+        /**
+         * Cubic to.
+         * 
+         * @param x1 the x1
+         * @param y1 the y1
+         * @param x2 the x2
+         * @param y2 the y2
+         * @param x3 the x3
+         * @param y3 the y3
+         */
+        void cubicTo(double x1, double y1, double x2, double y2, double x3, double y3) {
+            checkBuf(1, 6);
+            types[typeSize++] = PathIterator.SEG_CUBICTO;
+            points[pointSize++] = (float)x1;
+            points[pointSize++] = (float)y1;
+            points[pointSize++] = (float)x2;
+            points[pointSize++] = (float)y2;
+            points[pointSize++] = xLast = (float)x3;
+            points[pointSize++] = yLast = (float)y3;
+        }
+
+        /**
+         * Close path.
+         */
+        void closePath() {
+            checkBuf(1, 0);
+            types[typeSize++] = PathIterator.SEG_CLOSE;
+        }
+
+        /**
+         * Sets the last.
+         * 
+         * @param x the x
+         * @param y the y
+         */
+        void setLast(double x, double y) {
+            points[pointSize - 2] = xLast = (float)x;
+            points[pointSize - 1] = yLast = (float)y;
+        }
+
+        /**
+         * Append.
+         * 
+         * @param p the p
+         */
+        void append(BufferedPath p) {
+            checkBuf(p.typeSize, p.pointSize);
+            System.arraycopy(p.points, 0, points, pointSize, p.pointSize);
+            System.arraycopy(p.types, 0, types, typeSize, p.typeSize);
+            pointSize += p.pointSize;
+            typeSize += p.typeSize;
+            xLast = points[pointSize - 2];
+            yLast = points[pointSize - 1];
+        }
+
+        /**
+         * Append reverse.
+         * 
+         * @param p the p
+         */
+        void appendReverse(BufferedPath p) {
+            checkBuf(p.typeSize, p.pointSize);
+            // Skip last point, beacause it's the first point of the second path
+            for(int i = p.pointSize - 2; i >= 0; i -= 2) {
+                points[pointSize++] = p.points[i + 0];
+                points[pointSize++] = p.points[i + 1];
+            }
+            // Skip first type, beacuse it's always MOVETO
+            int closeIndex = 0;
+            for(int i = p.typeSize - 1; i >= 0; i--) {
+                byte type = p.types[i];
+                if (type == PathIterator.SEG_MOVETO) {
+                    types[closeIndex] = PathIterator.SEG_MOVETO;
+                    types[typeSize++] = PathIterator.SEG_CLOSE;
+                } else {
+                    if (type == PathIterator.SEG_CLOSE) {
+                        closeIndex = typeSize;
+                    }
+                    types[typeSize++] = type;
+                }
+            }
+            xLast = points[pointSize - 2];
+            yLast = points[pointSize - 1];
+        }
+
+        /**
+         * Join.
+         * 
+         * @param p the p
+         */
+        void join(BufferedPath p) {
+            // Skip MOVETO
+            checkBuf(p.typeSize - 1, p.pointSize - 2);
+            System.arraycopy(p.points, 2, points, pointSize, p.pointSize - 2);
+            System.arraycopy(p.types, 1, types, typeSize, p.typeSize - 1);
+            pointSize += p.pointSize - 2;
+            typeSize += p.typeSize - 1;
+            xLast = points[pointSize - 2];
+            yLast = points[pointSize - 1];
+        }
+
+        /**
+         * Combine.
+         * 
+         * @param p the p
+         */
+        void combine(BufferedPath p) {
+            checkBuf(p.typeSize - 1, p.pointSize - 2);
+            // Skip last point, beacause it's the first point of the second path
+            for(int i = p.pointSize - 4; i >= 0; i -= 2) {
+                points[pointSize++] = p.points[i + 0];
+                points[pointSize++] = p.points[i + 1];
+            }
+            // Skip first type, beacuse it's always MOVETO
+            for(int i = p.typeSize - 1; i >= 1; i--) {
+                types[typeSize++] = p.types[i];
+            }
+            xLast = points[pointSize - 2];
+            yLast = points[pointSize - 1];
+        }
+
+        /**
+         * Creates the general path.
+         * 
+         * @return the general path
+         */
+        GeneralPath createGeneralPath() {
+            GeneralPath p = new GeneralPath();
+            int j = 0;
+            for(int i = 0; i < typeSize; i++) {
+                int type = types[i];
+                switch(type){
+                case PathIterator.SEG_MOVETO:
+                    p.moveTo(points[j], points[j + 1]);
+                    break;
+                case PathIterator.SEG_LINETO:
+                    p.lineTo(points[j], points[j + 1]);
+                    break;
+                case PathIterator.SEG_QUADTO:
+                    p.quadTo(points[j], points[j + 1], points[j + 2], points[j + 3]);
+                    break;
+                case PathIterator.SEG_CUBICTO:
+                    p.curveTo(points[j], points[j + 1], points[j + 2], points[j + 3], points[j + 4], points[j + 5]);
+                    break;
+                case PathIterator.SEG_CLOSE:
+                    p.closePath();
+                    break;
+                }
+                j += pointShift[type];
+            }
+            return p;
+        }
+
+    }
+
+}
+
diff --git a/awt/java/awt/BufferCapabilities.java b/awt/java/awt/BufferCapabilities.java
new file mode 100644
index 0000000..80e8add
--- /dev/null
+++ b/awt/java/awt/BufferCapabilities.java
@@ -0,0 +1,185 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Alexey A. Petrenko
+ * @version $Revision$
+ */
+package java.awt;
+
+
+/**
+ * The BufferCapabilities class represents the capabilities 
+ * and other properties of the image buffers.
+ */
+public class BufferCapabilities implements Cloneable {
+    
+    /** The front buffer capabilities. */
+    private final ImageCapabilities frontBufferCapabilities;
+    
+    /** The back buffer capabilities. */
+    private final ImageCapabilities backBufferCapabilities;
+    
+    /** The flip contents. */
+    private final FlipContents flipContents;
+
+    /**
+     * Instantiates a new BufferCapabilities object.
+     * 
+     * @param frontBufferCapabilities the front buffer capabilities, 
+     * can not be null.
+     * @param backBufferCapabilities the the back and intermediate 
+     * buffers capabilities, can not be null.
+     * @param flipContents the back buffer contents after page flipping, 
+     * null if page flipping is not used.
+     */
+    public BufferCapabilities(ImageCapabilities frontBufferCapabilities, 
+            ImageCapabilities backBufferCapabilities, FlipContents flipContents) {
+        if (frontBufferCapabilities == null || backBufferCapabilities == null) {
+            throw new IllegalArgumentException();
+        }
+
+        this.frontBufferCapabilities = frontBufferCapabilities;
+        this.backBufferCapabilities = backBufferCapabilities;
+        this.flipContents = flipContents;
+    }
+
+    /**
+     * Returns a copy of the BufferCapabilities object.
+     * 
+     * @return a copy of the BufferCapabilities object.
+     */
+    @Override
+    public Object clone() {
+        return new BufferCapabilities(frontBufferCapabilities, backBufferCapabilities, flipContents);
+    }
+
+    /**
+     * Gets the image capabilities of the front buffer.
+     * 
+     * @return the ImageCapabilities object represented capabilities 
+     * of the front buffer. 
+     */
+    public ImageCapabilities getFrontBufferCapabilities() {
+        return frontBufferCapabilities;
+    }
+
+    /**
+     * Gets the image capabilities of the back buffer.
+     * 
+     * @return the ImageCapabilities object represented capabilities 
+     * of the back buffer. 
+     */
+    public ImageCapabilities getBackBufferCapabilities() {
+        return backBufferCapabilities;
+    }
+
+    /**
+     * Gets the flip contents of the back buffer after page-flipping. 
+     * 
+     * @return the FlipContents of the back buffer after page-flipping.
+     */
+    public FlipContents getFlipContents() {
+        return flipContents;
+    }
+
+    /**
+     * Checks if the buffer strategy uses page flipping.
+     * 
+     * @return true, if the buffer strategy uses page flipping,
+     * false otherwise.
+     */
+    public boolean isPageFlipping() {
+        return flipContents != null;
+    }
+
+    /**
+     * Checks if page flipping is only available in full-screen mode.
+     * 
+     * @return true, if page flipping is only available in full-screen mode,
+     * false otherwise.
+     */
+    public boolean isFullScreenRequired() {
+        return false;
+    }
+
+    /**
+     * Checks if page flipping can be performed using more than two buffers.
+     * 
+     * @return true, if page flipping can be performed using more than two buffers,
+     * false otherwise.
+     */
+    public boolean isMultiBufferAvailable() {
+        return false;
+    }
+
+    /**
+     * The FlipContents class represents a set of possible back buffer contents 
+     * after page-flipping.
+     */
+    public static final class FlipContents {
+        
+        /**
+         * The back buffered contents are cleared with the background color 
+         * after flipping.
+         */
+        public static final FlipContents BACKGROUND = new FlipContents();
+        
+        /** 
+         * The back buffered contents are copied to the front buffer before 
+         * flipping.
+         */
+        public static final FlipContents COPIED = new FlipContents();
+        
+        /** 
+         * The back buffer contents are the prior contents of the 
+         * front buffer.
+         */
+        public static final FlipContents PRIOR = new FlipContents();
+        
+        /** 
+         * The back buffer contents are undefined after flipping 
+         */
+        public static final FlipContents UNDEFINED = new FlipContents();
+
+        /**
+         * Instantiates a new flip contents.
+         */
+        private FlipContents() {
+
+        }
+
+        /**
+         * Returns the hash code of the FlipContents object.
+         * 
+         * @return the hash code of the FlipContents object.
+         */
+        @Override
+        public int hashCode() {
+            return super.hashCode();
+        }
+
+        /**
+         * Returns the String representation of the FlipContents object.
+         * 
+         * @return the string
+         */
+        @Override
+        public String toString() {
+            return super.toString();
+        }
+    }
+}
diff --git a/awt/java/awt/Color.java b/awt/java/awt/Color.java
new file mode 100644
index 0000000..e1e4178
--- /dev/null
+++ b/awt/java/awt/Color.java
@@ -0,0 +1,881 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.awt.color.ColorSpace;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.ColorModel;
+import java.awt.image.DataBufferInt;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+import java.io.Serializable;
+import java.util.Arrays;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Color class defines colors in the default sRGB color 
+ * space or in the specified ColorSpace. Every Color contains alpha value.
+ * The alpha value defines the transparency of a color and can be represented
+ * by a float value in the range 0.0 - 1.0 or 0 - 255. 
+  */
+public class Color implements Paint, Serializable {
+    
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = 118526816881161077L;
+
+    /*
+     * The values of the following colors are based on 1.5 release behavior which
+     * can be revealed using the following or similar code:
+     *   Color c = Color.white;
+     *   System.out.println(c);
+     */
+
+    /** The color white. */
+    public static final Color white = new Color(255, 255, 255);
+
+    /** The color white. */
+    public static final Color WHITE = white;
+
+    /** The color light gray. */
+    public static final Color lightGray = new Color(192, 192, 192);
+
+    /** The color light gray. */
+    public static final Color LIGHT_GRAY = lightGray;
+
+    /** The color gray. */
+    public static final Color gray = new Color(128, 128, 128);
+
+    /** The color gray. */
+    public static final Color GRAY = gray;
+
+    /** The color dark gray. */
+    public static final Color darkGray = new Color(64, 64, 64);
+
+    /** The color dark gray. */
+    public static final Color DARK_GRAY = darkGray;
+
+    /** The color black. */
+    public static final Color black = new Color(0, 0, 0);
+
+    /** The color black. */
+    public static final Color BLACK = black;
+
+    /** The color red. */
+    public static final Color red = new Color(255, 0, 0);
+
+    /** The color red. */
+    public static final Color RED = red;
+
+    /** The color pink. */
+    public static final Color pink = new Color(255, 175, 175);
+
+    /** The color pink. */
+    public static final Color PINK = pink;
+
+    /** The color orange. */
+    public static final Color orange = new Color(255, 200, 0);
+
+    /** The color orange. */
+    public static final Color ORANGE = orange;
+
+    /** The color yellow. */
+    public static final Color yellow = new Color(255, 255, 0);
+
+    /** The color yellow. */
+    public static final Color YELLOW = yellow;
+
+    /** The color green. */
+    public static final Color green = new Color(0, 255, 0);
+
+    /** The color green. */
+    public static final Color GREEN = green;
+
+    /** The color magenta. */
+    public static final Color magenta = new Color(255, 0, 255);
+
+    /** The color magenta. */
+    public static final Color MAGENTA = magenta;
+
+    /** The color cyan. */
+    public static final Color cyan = new Color(0, 255, 255);
+
+    /** The color cyan. */
+    public static final Color CYAN = cyan;
+
+    /** The color blue. */
+    public static final Color blue = new Color(0, 0, 255);
+
+    /** The color blue. */
+    public static final Color BLUE = blue;
+
+    /** integer RGB value. */
+    int value;
+
+    /** Float sRGB value. */
+    private float[] frgbvalue;
+
+    /** Color in an arbitrary color space with <code>float</code> components. If null, other value should be used. */
+    private float fvalue[];
+
+    /** Float alpha value. If frgbvalue is null, this is not valid data. */
+    private float falpha;
+
+    /** The color's color space if applicable. */
+    private ColorSpace cs;
+
+    /*
+     * The value of the SCALE_FACTOR is based on 1.5 release behavior which
+     * can be revealed using the following code:
+     *   Color c = new Color(100, 100, 100);
+     *   Color bc = c.brighter();
+     *   System.out.println("Brighter factor: " + ((float)c.getRed())/((float)bc.getRed()));
+     *   Color dc = c.darker();
+     *   System.out.println("Darker factor: " + ((float)dc.getRed())/((float)c.getRed()));
+     * The result is the same for brighter and darker methods, so we need only
+     * one scale factor for both.
+     */
+    /** The Constant SCALE_FACTOR. */
+    private static final double SCALE_FACTOR = 0.7;
+
+    /** The Constant MIN_SCALABLE. */
+    private static final int MIN_SCALABLE = 3; // should increase when multiplied by SCALE_FACTOR
+
+    /** The current paint context. */
+    transient private PaintContext currentPaintContext;
+
+    /**
+     * Creates a color in the specified ColorSpace, the specified color 
+     * components and the specified alpha. 
+     * 
+     * @param cspace the ColorSpace to be used to define the components.
+     * @param components the components.
+     * @param alpha the alpha.
+     */
+    public Color(ColorSpace cspace, float[] components, float alpha) {
+        int nComps = cspace.getNumComponents();
+        float comp;
+        fvalue = new float[nComps];
+
+        for(int i=0 ; i<nComps; i++) {
+            comp = components[i];
+            if(comp < 0.0f || comp > 1.0f) {
+                // awt.107=Color parameter outside of expected range: component {0}.
+                throw new IllegalArgumentException(
+                        Messages.getString("awt.107", i)); //$NON-NLS-1$
+            }
+            fvalue[i] = components[i];
+        }
+
+        if (alpha < 0.0f || alpha > 1.0f) {
+            // awt.108=Alpha value outside of expected range.
+            throw new IllegalArgumentException(Messages.getString("awt.108")); //$NON-NLS-1$
+        }
+        falpha = alpha;
+
+        cs = cspace;
+
+        frgbvalue = cs.toRGB(fvalue);
+
+        value =  ((int)(frgbvalue[2]*255 + 0.5))    |
+                (((int)(frgbvalue[1]*255 + 0.5)) << 8 )  |
+                (((int)(frgbvalue[0]*255 + 0.5)) << 16 ) |
+                (((int)(falpha*255 + 0.5)) << 24 );
+    }
+
+    /**
+     * Instantiates a new sRGB color with the specified combined 
+     * RGBA value consisting of the alpha component in bits 24-31, 
+     * the red component in bits 16-23, the green component in bits 8-15, 
+     * and the blue component in bits 0-7. If the hasalpha argument is 
+     * false, the alpha has default value - 255.
+     * 
+     * @param rgba the RGBA components.
+     * @param hasAlpha alpha parameter is true if alpha bits are valid,
+     * false otherwise.
+     */
+    public Color(int rgba, boolean hasAlpha) {
+        if (!hasAlpha) {
+            value = rgba | 0xFF000000;
+        } else {
+            value = rgba;
+        }
+    }
+
+    /**
+     * Instantiates a new color with the specified red, green, blue and alpha 
+     * components.
+     * 
+     * @param r the red component.
+     * @param g the green component.
+     * @param b the blue component.
+     * @param a the alpha component.
+     */
+    public Color(int r, int g, int b, int a) {
+        if ((r & 0xFF) != r || (g & 0xFF) != g || (b & 0xFF) != b || (a & 0xFF) != a) {
+            // awt.109=Color parameter outside of expected range.
+            throw new IllegalArgumentException(Messages.getString("awt.109")); //$NON-NLS-1$
+        }
+        value = b | (g << 8) | (r << 16) | (a << 24);
+    }
+
+    /**
+     * Instantiates a new opaque sRGB color with the specified red, green, 
+     * and blue values. The Alpha component is set to the default - 1.0.
+     * 
+     * @param r the red component. 
+     * @param g the green component.
+     * @param b the blue component.
+     */
+    public Color(int r, int g, int b) {
+        if ((r & 0xFF) != r || (g & 0xFF) != g || (b & 0xFF) != b) {
+            // awt.109=Color parameter outside of expected range.
+            throw new IllegalArgumentException(Messages.getString("awt.109")); //$NON-NLS-1$
+        }
+        // 0xFF for alpha channel
+        value = b | (g << 8) | (r << 16) | 0xFF000000;
+    }
+
+    /**
+     * Instantiates a new sRGB color with the specified 
+     * RGB value consisting of the red component in bits 16-23, 
+     * the green component in bits 8-15, and the blue component 
+     * in bits 0-7. Alpha has default value - 255.
+     * 
+     * @param rgb the RGB components.
+     */
+    public Color(int rgb) {
+        value = rgb | 0xFF000000;
+    }
+
+    /**
+     * Instantiates a new color with the specified red, green, blue and alpha 
+     * components.
+     * 
+     * @param r the red component.
+     * @param g the green component.
+     * @param b the blue component.
+     * @param a the alpha component.
+     */
+    public Color(float r, float g, float b, float a) {
+        this((int)(r*255+0.5),
+                (int)(g*255+0.5),
+                (int)(b*255+0.5),
+                (int)(a*255+0.5));
+        falpha = a;
+        fvalue = new float[3];
+        fvalue[0] = r;
+        fvalue[1] = g;
+        fvalue[2] = b;
+        frgbvalue = fvalue;
+    }
+
+    /**
+     * Instantiates a new color with the specified red, green, and blue 
+     * components and default alfa value - 1.0.
+     * 
+     * @param r the red component.
+     * @param g the green component.
+     * @param b the blue component.
+     */
+    public Color(float r, float g, float b) {
+        this(r, g, b, 1.0f);
+    }
+
+    public PaintContext createContext(
+            ColorModel cm,
+            Rectangle r,
+            Rectangle2D r2d,
+            AffineTransform xform,
+            RenderingHints rhs
+    ) {
+        if(currentPaintContext != null) {
+            return currentPaintContext;
+        }
+        currentPaintContext = new Color.ColorPaintContext(value);
+        return currentPaintContext;
+    }
+
+    /**
+     * Returns a string representation of the Color object.
+     * 
+     * @return the string representation of the Color object.
+     */
+    @Override
+    public String toString() {
+        /*
+           The format of the string is based on 1.5 release behavior which
+           can be revealed using the following code:
+
+           Color c = new Color(1, 2, 3);
+           System.out.println(c);
+        */
+        
+        return getClass().getName() +
+                "[r=" + getRed() + //$NON-NLS-1$
+                ",g=" + getGreen() + //$NON-NLS-1$
+                ",b=" + getBlue() + //$NON-NLS-1$
+                "]"; //$NON-NLS-1$
+    }
+
+    /**
+     * Compares the specified Object to the Color.
+     * 
+     * @param obj the Object to be compared.
+     * 
+     * @return true, if the specified Object is a Color whose 
+     * value is equal to this Color, false otherwise.
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if(obj instanceof Color) {
+            return ((Color)obj).value == this.value;
+        }
+        return false;
+    }
+
+    /**
+     * Returns a float array containing the color and alpha components of 
+     * the Color in the specified ColorSpace. 
+     * 
+     * @param colorSpace the specified ColorSpace.
+     * @param components the results of this method will be written to
+     * this float array. If null, a float array will be created.
+     * 
+     * @return the color and alpha components in a float array.
+     */
+    public float[] getComponents(ColorSpace colorSpace, float[] components) {
+        int nComps = colorSpace.getNumComponents();
+        if(components == null) {
+            components = new float[nComps+1];
+        }
+
+        getColorComponents(colorSpace, components);
+
+        if(frgbvalue != null) {
+            components[nComps] = falpha;
+        } else {
+            components[nComps] = getAlpha()/255f;
+        }
+
+        return components;
+    }
+
+    /**
+     * Returns a float array containing the color components of 
+     * the Color in the specified ColorSpace.
+     * 
+     * @param colorSpace the specified ColorSpace.
+     * @param components the results of this method will be written to
+     * this float array. If null, a float array will be created.
+     * 
+     * @return the color components in a float array.
+     */
+    public float[] getColorComponents(ColorSpace colorSpace, float[] components) {
+        float[] cieXYZComponents = getColorSpace().toCIEXYZ(getColorComponents(null));
+        float[] csComponents = colorSpace.fromCIEXYZ(cieXYZComponents);
+
+        if(components == null) {
+            return csComponents;
+        }
+
+        for(int i=0; i<csComponents.length; i++) {
+            components[i] = csComponents[i];
+        }
+
+        return components;
+    }
+
+    /**
+     * Gets the ColorSpace of this Color.
+     * 
+     * @return the ColorSpace object.
+     */
+    public ColorSpace getColorSpace() {
+        if (cs == null) {
+            cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
+        }
+
+        return cs;
+    }
+
+    /**
+     * Creates a new Color which is a darker than this Color
+     * according to a fixed scale factor.
+     * 
+     * @return the darker Color.
+     */
+    public Color darker() {
+        return new Color(
+                (int)(getRed()*SCALE_FACTOR),
+                (int)(getGreen()*SCALE_FACTOR),
+                (int)(getBlue()*SCALE_FACTOR));
+    }
+
+    /**
+     * Creates a new Color which is a brighter than this Color.
+     * 
+     * @return the brighter Color.
+     */
+    public Color brighter() {
+
+        int r = getRed();
+        int b = getBlue();
+        int g = getGreen();
+
+        if(r == 0 && b == 0 && g == 0) {
+            return new Color(MIN_SCALABLE, MIN_SCALABLE, MIN_SCALABLE);
+        }
+
+        if(r < MIN_SCALABLE && r != 0) {
+            r = MIN_SCALABLE;
+        } else {
+            r = (int) (r/SCALE_FACTOR);
+            r = (r > 255) ? 255 : r;
+        }
+
+        if(b < MIN_SCALABLE && b != 0) {
+            b = MIN_SCALABLE;
+        } else {
+            b = (int) (b/SCALE_FACTOR);
+            b = (b > 255) ? 255 : b;
+        }
+
+        if(g < MIN_SCALABLE && g != 0) {
+            g = MIN_SCALABLE;
+        } else {
+            g = (int) (g/SCALE_FACTOR);
+            g = (g > 255) ? 255 : g;
+        }
+
+        return new Color(r, g, b);
+    }
+
+    /**
+     * Returns a float array containing the color and alpha components of 
+     * the Color in the default sRGB color space. 
+     * 
+     * @param components the results of this method will be written to
+     * this float array. A new float array will be created if this
+     * argument is null.
+     * 
+     * @return the RGB color and alpha components in a float array.
+     */
+    public float[] getRGBComponents(float[] components) {
+        if(components == null) {
+            components = new float[4];
+        }
+
+        if(frgbvalue != null) {
+            components[3] = falpha;
+        } else {
+            components[3] = getAlpha()/255f;
+        }
+
+        getRGBColorComponents(components);
+
+        return components;
+    }
+
+    /**
+     * Returns a float array containing the color components of 
+     * the Color in the default sRGB color space. 
+     * 
+     * @param components the results of this method will be written to
+     * this float array. A new float array will be created if this
+     * argument is null.
+     * 
+     * @return the RGB color components in a float array.
+     */
+    public float[] getRGBColorComponents(float[] components) {
+        if(components == null) {
+            components = new float[3];
+        }
+
+        if(frgbvalue != null) {
+            components[2] = frgbvalue[2];
+            components[1] = frgbvalue[1];
+            components[0] = frgbvalue[0];
+        } else {
+            components[2] = getBlue()/255f;
+            components[1] = getGreen()/255f;
+            components[0] = getRed()/255f;
+        }
+
+        return components;
+    }
+
+    /**
+     * Returns a float array which contains the color and alpha components of 
+     * the Color in the ColorSpace of the Color.
+     * 
+     * @param components the results of this method will be written to
+     * this float array. A new float array will be created if this
+     * argument is null.
+     * 
+     * @return the color and alpha components in a float array.
+     */
+    public float[] getComponents(float[] components) {
+        if(fvalue == null) {
+            return getRGBComponents(components);
+        }
+
+        int nColorComps = fvalue.length;
+
+        if(components == null) {
+            components = new float[nColorComps+1];
+        }
+
+        getColorComponents(components);
+
+        components[nColorComps] = falpha;
+
+        return components;
+    }
+
+    /**
+     * Returns a float array which contains the color components of 
+     * the Color in the ColorSpace of the Color.
+     * 
+     * @param components the results of this method will be written to
+     * this float array. A new float array will be created if this
+     * argument is null.
+     * 
+     * @return the color components in a float array.
+     */
+    public float[] getColorComponents(float[] components) {
+        if(fvalue == null) {
+            return getRGBColorComponents(components);
+        }
+
+        if(components == null) {
+            components = new float[fvalue.length];
+        }
+
+        for(int i=0; i<fvalue.length; i++) {
+            components[i] = fvalue[i];
+        }
+
+        return components;
+    }
+
+    /**
+     * Returns a hash code of this Color object.
+     * 
+     * @return a hash code of this Color object.
+     */
+    @Override
+    public int hashCode() {
+        return value;
+    }
+
+    public int getTransparency() {
+        switch(getAlpha()) {
+            case 0xff:
+                return Transparency.OPAQUE;
+            case 0:
+                return Transparency.BITMASK;
+            default:
+                return Transparency.TRANSLUCENT;
+        }
+    }
+
+    /**
+     * Gets the red component of the Color in the range 0-255.
+     * 
+     * @return the red component of the Color.
+     */
+    public int getRed() {
+        return (value >> 16) & 0xFF;
+    }
+
+    /**
+     * Gets the RGB value that represents the color in the default sRGB ColorModel.
+     * 
+     * @return the RGB color value in the default sRGB ColorModel.
+     */
+    public int getRGB() {
+        return value;
+    }
+
+    /**
+     * Gets the green component of the Color in the range 0-255.
+     * 
+     * @return the green component of the Color.
+     */
+    public int getGreen() {
+        return (value >> 8) & 0xFF;
+    }
+
+    /**
+     * Gets the blue component of the Color in the range 0-255.
+     * 
+     * @return the blue component of the Color.
+     */
+    public int getBlue() {
+        return value & 0xFF;
+    }
+
+    /**
+     * Gets the alpha component of the Color in the range 0-255.
+     * 
+     * @return the alpha component of the Color.
+     */
+    public int getAlpha() {
+        return (value >> 24) & 0xFF;
+    }
+
+    /**
+     * Gets the Color from the specified string, or returns the Color
+     * specified by the second parameter.
+     * 
+     * @param nm the specified string.
+     * @param def the default Color.
+     * 
+     * @return the color from the specified string, or the Color
+     * specified by the second parameter.
+     */
+    public static Color getColor(String nm, Color def) {
+        Integer integer = Integer.getInteger(nm);
+
+        if (integer == null) {
+            return def;
+        }
+
+        return new Color(integer.intValue());
+    }
+
+    /**
+     * Gets the Color from the specified string, or returns the Color converted
+     * from the second parameter.
+     * 
+     * @param nm the specified string.
+     * @param def the default Color.
+     * 
+     * @return the color from the specified string, or the Color
+     * converted from the second parameter.
+     */
+    public static Color getColor(String nm, int def) {
+        Integer integer = Integer.getInteger(nm);
+
+        if (integer == null) {
+            return new Color(def);
+        }
+
+        return new Color(integer.intValue());
+    }
+
+    /**
+     * Gets the Color from the specified String.
+     * 
+     * @param nm the specified string.
+     * 
+     * @return the Color object, or null.
+     */
+    public static Color getColor(String nm) {
+        Integer integer = Integer.getInteger(nm);
+
+        if (integer == null) {
+            return null;
+        }
+
+        return new Color(integer.intValue());
+    }
+
+    /**
+     * Decodes a String to an integer and returns the specified opaque Color.
+     * 
+     * @param nm a String which represents an opaque color as a 24-bit integer.
+     * 
+     * @throws NumberFormatException if the specified string can not be
+     * converted to an integer.
+     */
+    public static Color decode(String nm) throws NumberFormatException {
+        Integer integer = Integer.decode(nm);
+        return new Color(integer.intValue());
+    }
+
+    /**
+     * Gets a Color object using the specified values of the HSB color model.
+     * 
+     * @param h the hue component of the Color.
+     * @param s the saturation of the Color.
+     * @param b the brightness of the Color.
+     * 
+     * @return a color object with the specified hue, saturation and 
+     * brightness values.
+     */
+    public static Color getHSBColor(float h, float s, float b) {
+        return new Color(HSBtoRGB(h, s, b));
+    }
+
+    /**
+     * Converts the Color specified by the RGB model to an equivalent 
+     * color in the HSB model.
+     * 
+     * @param r the red component.
+     * @param g the green component.
+     * @param b the blue component.
+     * @param hsbvals the array of result hue, saturation, brightness
+     * values or null.
+     * 
+     * @return the float array of hue, saturation, brightness values.
+     */
+    public static float[] RGBtoHSB(int r, int g, int b, float[] hsbvals) {
+        if(hsbvals == null) {
+            hsbvals = new float[3];
+        }
+
+        int V = Math.max(b, Math.max(r, g));
+        int temp = Math.min(b, Math.min(r, g));
+
+        float H, S, B;
+
+        B = V/255.f;
+
+        if(V == temp) {
+            H = S = 0;
+        } else {
+            S = (V - temp)/((float)V);
+
+            float Cr = (V - r) / (float)(V - temp);
+            float Cg = (V - g) / (float)(V - temp);
+            float Cb = (V - b) / (float)(V - temp);
+
+            if (r == V) {
+                H = Cb - Cg;
+            } else if (g == V) {
+                H = 2 + Cr - Cb;
+            } else {
+                H = 4 + Cg - Cr;
+            }
+
+            H /= 6.f;
+            if(H < 0) {
+                H++;
+            }
+        }
+
+        hsbvals[0] = H;
+        hsbvals[1] = S;
+        hsbvals[2] = B;
+
+        return hsbvals;
+    }
+
+    /**
+     * Converts the Color specified by the HSB model to an equivalent 
+     * color in the default RGB model.
+     * 
+     * @param hue the hue component of the Color.
+     * @param saturation the saturation of the Color.
+     * @param brightness the brightness of the Color.
+     * 
+     * @return the RGB value of the color with the specified hue, 
+     * saturation and brightness.
+     */
+    public static int HSBtoRGB(float hue, float saturation, float brightness) {
+        float fr, fg, fb;
+
+        if(saturation == 0) {
+            fr = fg = fb = brightness;
+        } else {
+            float H = (hue - (float)Math.floor(hue)) * 6;
+            int I = (int) Math.floor(H);
+            float F = H - I;
+            float M = brightness * (1 - saturation);
+            float N = brightness * (1 - saturation * F);
+            float K = brightness * (1 - saturation * (1 - F));
+
+            switch(I) {
+                case 0:
+                    fr = brightness; fg = K; fb = M; break;
+                case 1:
+                    fr = N; fg = brightness; fb = M; break;
+                case 2:
+                    fr = M; fg = brightness; fb = K; break;
+                case 3:
+                    fr = M; fg = N; fb = brightness; break;
+                case 4:
+                    fr = K; fg = M; fb = brightness; break;
+                case 5:
+                    fr = brightness; fg = M; fb = N; break;
+                default:
+                    fr = fb = fg = 0; // impossible, to supress compiler error
+            }
+        }
+
+        int r = (int) (fr * 255. + 0.5);
+        int g = (int) (fg * 255. + 0.5);
+        int b = (int) (fb * 255. + 0.5);
+
+        return (r << 16) | (g << 8) | b | 0xFF000000;
+    }
+
+    /**
+     * The Class ColorPaintContext.
+     */
+    class ColorPaintContext implements PaintContext {
+        
+        /** The rgb value. */
+        int rgbValue;
+        
+        /** The saved raster. */
+        WritableRaster savedRaster = null;
+
+        /**
+         * Instantiates a new color paint context.
+         * 
+         * @param rgb the rgb
+         */
+        protected ColorPaintContext(int rgb) {
+            rgbValue = rgb;
+        }
+
+        public void dispose() {
+            savedRaster = null;
+        }
+
+        public ColorModel getColorModel() {
+            return ColorModel.getRGBdefault();
+        }
+
+        public Raster getRaster(int x, int y, int w, int h) {
+            if (savedRaster == null ||
+                    w != savedRaster.getWidth() ||
+                    h != savedRaster.getHeight()) {
+                savedRaster =
+                        getColorModel().createCompatibleWritableRaster(w, h);
+
+                // Suppose we have here simple INT/RGB color/sample model
+                DataBufferInt intBuffer =
+                        (DataBufferInt) savedRaster.getDataBuffer();
+                int rgbValues[] = intBuffer.getData();
+                int rgbFillValue = rgbValue;
+                Arrays.fill(rgbValues, rgbFillValue);
+            }
+
+            return savedRaster;
+        }
+    }
+}
+
diff --git a/awt/java/awt/Component.java b/awt/java/awt/Component.java
new file mode 100644
index 0000000..f19d285
--- /dev/null
+++ b/awt/java/awt/Component.java
@@ -0,0 +1,6408 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package java.awt;
+
+//import java.awt.dnd.DropTarget;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.event.HierarchyBoundsListener;
+import java.awt.event.HierarchyEvent;
+import java.awt.event.HierarchyListener;
+import java.awt.event.InputMethodEvent;
+import java.awt.event.InputMethodListener;
+import java.awt.event.InvocationEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.awt.event.MouseWheelEvent;
+import java.awt.event.MouseWheelListener;
+import java.awt.event.PaintEvent;
+import java.awt.event.WindowEvent;
+import java.awt.im.InputContext;
+import java.awt.im.InputMethodRequests;
+import java.awt.image.BufferStrategy;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.awt.image.VolatileImage;
+import java.awt.image.WritableRaster;
+import java.awt.peer.ComponentPeer;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.Serializable;
+import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.EventListener;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+//???AWT
+//import javax.accessibility.Accessible;
+//import javax.accessibility.AccessibleComponent;
+//import javax.accessibility.AccessibleContext;
+//import javax.accessibility.AccessibleRole;
+//import javax.accessibility.AccessibleState;
+//import javax.accessibility.AccessibleStateSet;
+
+import org.apache.harmony.awt.ClipRegion;
+//import org.apache.harmony.awt.FieldsAccessor;
+import org.apache.harmony.awt.gl.MultiRectArea;
+import org.apache.harmony.awt.internal.nls.Messages;
+import org.apache.harmony.awt.state.State;
+//import org.apache.harmony.awt.text.TextFieldKit;
+//import org.apache.harmony.awt.text.TextKit;
+import org.apache.harmony.awt.wtk.NativeWindow;
+
+/**
+ * The abstract Component class specifies an object with a graphical 
+ * representation that can be displayed on the screen and that can 
+ * interact with the user (for example: scrollbars, buttons, checkboxes).
+ */
+public abstract class Component implements ImageObserver, MenuContainer, Serializable {
+    
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = -7644114512714619750L;
+
+    /** The Constant TOP_ALIGNMENT indicates the top alignment of the component. */
+    public static final float TOP_ALIGNMENT = 0.0f;
+
+    /** The Constant CENTER_ALIGNMENT indicates the center alignment of the component. */
+    public static final float CENTER_ALIGNMENT = 0.5f;
+
+    /** The Constant BOTTOM_ALIGNMENT indicates the bottom alignment of the component. */
+    public static final float BOTTOM_ALIGNMENT = 1.0f;
+
+    /** The Constant LEFT_ALIGNMENT indicates the left alignment of the component. */
+    public static final float LEFT_ALIGNMENT = 0.0f;
+
+    /** The Constant RIGHT_ALIGNMENT indicates the right alignment of the component. */
+    public static final float RIGHT_ALIGNMENT = 1.0f;
+
+    /** The Constant childClassesFlags. */
+    private static final Hashtable<Class<?>, Boolean> childClassesFlags = new Hashtable<Class<?>, Boolean>();
+
+    /** The Constant peer. */
+    private static final ComponentPeer peer = new ComponentPeer() {
+    };
+
+    /** The Constant incrementalImageUpdate. */
+    private static final boolean incrementalImageUpdate;
+
+    /** The toolkit. */
+    final transient Toolkit toolkit = Toolkit.getDefaultToolkit();
+
+    //???AWT
+    /*
+    protected abstract class AccessibleAWTComponent extends AccessibleContext implements
+            Serializable, AccessibleComponent {
+        private static final long serialVersionUID = 642321655757800191L;
+
+        protected class AccessibleAWTComponentHandler implements ComponentListener {
+            protected AccessibleAWTComponentHandler() {
+            }
+
+            public void componentHidden(ComponentEvent e) {
+                if (behaviour.isLightweight()) {
+                    return;
+                }
+                firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
+                        AccessibleState.VISIBLE, null);
+            }
+
+            public void componentMoved(ComponentEvent e) {
+            }
+
+            public void componentResized(ComponentEvent e) {
+            }
+
+            public void componentShown(ComponentEvent e) {
+                if (behaviour.isLightweight()) {
+                    return;
+                }
+                firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY, null,
+                        AccessibleState.VISIBLE);
+            }
+        }
+
+        protected class AccessibleAWTFocusHandler implements FocusListener {
+            public void focusGained(FocusEvent e) {
+                if (behaviour.isLightweight()) {
+                    return;
+                }
+                firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY, null,
+                        AccessibleState.FOCUSED);
+            }
+
+            public void focusLost(FocusEvent e) {
+                if (behaviour.isLightweight()) {
+                    return;
+                }
+                firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
+                        AccessibleState.FOCUSED, null);
+            }
+        }
+    
+        protected ComponentListener accessibleAWTComponentHandler;
+    
+        protected FocusListener accessibleAWTFocusHandler;
+        */
+        /*
+         * Number of registered property change listeners.
+         */
+        /*
+        int listenersCount;
+
+        public void addFocusListener(FocusListener l) {
+            Component.this.addFocusListener(l);
+        }
+
+        @Override
+        public void addPropertyChangeListener(PropertyChangeListener listener) {
+            toolkit.lockAWT();
+            try {
+                super.addPropertyChangeListener(listener);
+                listenersCount++;
+                if (accessibleAWTComponentHandler == null) {
+                    accessibleAWTComponentHandler = new AccessibleAWTComponentHandler();
+                    Component.this.addComponentListener(accessibleAWTComponentHandler);
+                }
+                if (accessibleAWTFocusHandler == null) {
+                    accessibleAWTFocusHandler = new AccessibleAWTFocusHandler();
+                    Component.this.addFocusListener(accessibleAWTFocusHandler);
+                }
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+        
+        public boolean contains(Point p) {
+            toolkit.lockAWT();
+            try {
+                return Component.this.contains(p);
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        public Accessible getAccessibleAt(Point arg0) {
+            toolkit.lockAWT();
+            try {
+                return null;
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        public Color getBackground() {
+            toolkit.lockAWT();
+            try {
+                return Component.this.getBackground();
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        public Rectangle getBounds() {
+            toolkit.lockAWT();
+            try {
+                return Component.this.getBounds();
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        public Cursor getCursor() {
+            toolkit.lockAWT();
+            try {
+                return Component.this.getCursor();
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        public Font getFont() {
+            toolkit.lockAWT();
+            try {
+                return Component.this.getFont();
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        public FontMetrics getFontMetrics(Font f) {
+            toolkit.lockAWT();
+            try {
+                return Component.this.getFontMetrics(f);
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        public Color getForeground() {
+            toolkit.lockAWT();
+            try {
+                return Component.this.getForeground();
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        public Point getLocation() {
+            toolkit.lockAWT();
+            try {
+                return Component.this.getLocation();
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        public Point getLocationOnScreen() {
+            toolkit.lockAWT();
+            try {
+                return Component.this.getLocationOnScreen();
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        public Dimension getSize() {
+            toolkit.lockAWT();
+            try {
+                return Component.this.getSize();
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        public boolean isEnabled() {
+            toolkit.lockAWT();
+            try {
+                return Component.this.isEnabled();
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        public boolean isFocusTraversable() {
+            toolkit.lockAWT();
+            try {
+                return Component.this.isFocusTraversable();
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        public boolean isShowing() {
+            toolkit.lockAWT();
+            try {
+                return Component.this.isShowing();
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        public boolean isVisible() {
+            toolkit.lockAWT();
+            try {
+                return Component.this.isVisible();
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        public void removeFocusListener(FocusListener l) {
+            Component.this.removeFocusListener(l);
+        }
+
+        @Override
+        public void removePropertyChangeListener(PropertyChangeListener listener) {
+            toolkit.lockAWT();
+            try {
+                super.removePropertyChangeListener(listener);
+                listenersCount--;
+                if (listenersCount > 0) {
+                    return;
+                }
+                // if there are no more listeners, remove handlers:
+                Component.this.removeFocusListener(accessibleAWTFocusHandler);
+                Component.this.removeComponentListener(accessibleAWTComponentHandler);
+                accessibleAWTComponentHandler = null;
+                accessibleAWTFocusHandler = null;
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        public void requestFocus() {
+            toolkit.lockAWT();
+            try {
+                Component.this.requestFocus();
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        public void setBackground(Color color) {
+            toolkit.lockAWT();
+            try {
+                Component.this.setBackground(color);
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        public void setBounds(Rectangle r) {
+            toolkit.lockAWT();
+            try {
+                Component.this.setBounds(r);
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        public void setCursor(Cursor cursor) {
+            toolkit.lockAWT();
+            try {
+                Component.this.setCursor(cursor);
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        public void setEnabled(boolean enabled) {
+            toolkit.lockAWT();
+            try {
+                Component.this.setEnabled(enabled);
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        public void setFont(Font f) {
+            toolkit.lockAWT();
+            try {
+                Component.this.setFont(f);
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        public void setForeground(Color color) {
+            toolkit.lockAWT();
+            try {
+                Component.this.setForeground(color);
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        public void setLocation(Point p) {
+            toolkit.lockAWT();
+            try {
+                Component.this.setLocation(p);
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        public void setSize(Dimension size) {
+            toolkit.lockAWT();
+            try {
+                Component.this.setSize(size);
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        public void setVisible(boolean visible) {
+            toolkit.lockAWT();
+            try {
+                Component.this.setVisible(visible);
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+        
+        @Override
+        public Accessible getAccessibleParent() {
+            toolkit.lockAWT();
+            try {
+                Accessible aParent = super.getAccessibleParent();
+                if (aParent != null) {
+                    return aParent;
+                }
+                Container parent = getParent();
+                return (parent instanceof Accessible ? (Accessible) parent : null);
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        @Override
+        public Accessible getAccessibleChild(int i) {
+            toolkit.lockAWT();
+            try {
+                return null;
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        @Override
+        public int getAccessibleChildrenCount() {
+            toolkit.lockAWT();
+            try {
+                return 0;
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        @Override
+        public AccessibleComponent getAccessibleComponent() {
+            return this;
+        }
+
+        @Override
+        public String getAccessibleDescription() {
+            return super.getAccessibleDescription(); // why override?
+        }
+
+        @Override
+        public int getAccessibleIndexInParent() {
+            toolkit.lockAWT();
+            try {
+                if (getAccessibleParent() == null) {
+                    return -1;
+                }
+                int count = 0;
+                Container parent = getParent();
+                for (int i = 0; i < parent.getComponentCount(); i++) {
+                    Component aComp = parent.getComponent(i);
+                    if (aComp instanceof Accessible) {
+                        if (aComp == Component.this) {
+                            return count;
+                        }
+                        ++count;
+                    }
+                }
+                return -1;
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        @Override
+        public AccessibleRole getAccessibleRole() {
+            toolkit.lockAWT();
+            try {
+                return AccessibleRole.AWT_COMPONENT;
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        @Override
+        public AccessibleStateSet getAccessibleStateSet() {
+            toolkit.lockAWT();
+            try {
+                AccessibleStateSet set = new AccessibleStateSet();
+                if (isEnabled()) {
+                    set.add(AccessibleState.ENABLED);
+                }
+                if (isFocusable()) {
+                    set.add(AccessibleState.FOCUSABLE);
+                }
+                if (hasFocus()) {
+                    set.add(AccessibleState.FOCUSED);
+                }
+                if (isOpaque()) {
+                    set.add(AccessibleState.OPAQUE);
+                }
+                if (isShowing()) {
+                    set.add(AccessibleState.SHOWING);
+                }
+                if (isVisible()) {
+                    set.add(AccessibleState.VISIBLE);
+                }
+                return set;
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        @Override
+        public Locale getLocale() throws IllegalComponentStateException {
+            toolkit.lockAWT();
+            try {
+                return Component.this.getLocale();
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+    }
+    */
+    /**
+     * The BltBufferStrategy class provides opportunity of blitting 
+     * offscreen surfaces to a component. For more information on 
+     * blitting, see <a href="http://en.wikipedia.org/wiki/Bit_blit">Bit blit</a>.
+     */
+    protected class BltBufferStrategy extends BufferStrategy {
+        
+        /** The back buffers. */
+        protected VolatileImage[] backBuffers;
+
+        /** The caps. */
+        protected BufferCapabilities caps;
+
+        /** The width. */
+        protected int width;
+
+        /** The height. */
+        protected int height;
+
+        /** The validated contents. */
+        protected boolean validatedContents;
+
+        /**
+         * Instantiates a new BltBufferStrategy buffer strategy.
+         * 
+         * @param numBuffers the number of buffers.
+         * @param caps the BufferCapabilities.
+         * 
+         * @throws NotImplementedException the not implemented exception.
+         */
+        protected BltBufferStrategy(int numBuffers, BufferCapabilities caps) throws org.apache.harmony.luni.util.NotImplementedException {
+            if (true) {
+                throw new RuntimeException("Method is not implemented"); //$NON-NLS-1$
+            }
+        }
+
+        /**
+         * Returns true if the drawing buffer has been lost since the last call 
+         * to getDrawGraphics. 
+         * 
+         * @return true if the drawing buffer has been lost since the last call 
+         * to getDrawGraphics, false otherwise.
+         *  
+         * @see java.awt.image.BufferStrategy#contentsLost()
+         */
+        @Override
+        public boolean contentsLost() {
+            if (true) {
+                throw new RuntimeException("Method is not implemented"); //$NON-NLS-1$
+            }
+            return false;
+        }
+
+        /**
+         * Returns true if the drawing buffer has been restored from a lost
+         * state and reinitialized to the default background color.
+         * 
+         * @return true if the drawing buffer has been restored from a lost
+         * state and reinitialized to the default background color,
+         * false otherwise.
+         *           
+         * @see java.awt.image.BufferStrategy#contentsRestored()
+         */
+        @Override
+        public boolean contentsRestored() {
+            if (true) {
+                throw new RuntimeException("Method is not implemented"); //$NON-NLS-1$
+            }
+            return false;
+        }
+
+        /**
+         * Creates the back buffers.
+         * 
+         * @param numBuffers the number of buffers.
+         */
+        protected void createBackBuffers(int numBuffers) {
+            if (true) {
+                throw new RuntimeException("Method is not implemented"); //$NON-NLS-1$
+            }
+        }
+
+        /**
+         * Returns the BufferCapabilities of the buffer strategy.
+         * 
+         * @return the BufferCapabilities.
+         * 
+         * @see java.awt.image.BufferStrategy#getCapabilities()
+         */
+        @Override
+        public BufferCapabilities getCapabilities() {
+            return (BufferCapabilities) caps.clone();
+        }
+
+        /**
+         * Gets Graphics of current buffer strategy.
+         * 
+         * @return the Graphics of current buffer strategy.
+         * 
+         * @see java.awt.image.BufferStrategy#getDrawGraphics()
+         */
+        @Override
+        public Graphics getDrawGraphics() {
+            if (true) {
+                throw new RuntimeException("Method is not implemented"); //$NON-NLS-1$
+            }
+            return null;
+        }
+
+        /**
+         * Revalidates the lost drawing buffer.
+         */
+        protected void revalidate() {
+            if (true) {
+                throw new RuntimeException("Method is not implemented"); //$NON-NLS-1$
+            }
+        }
+
+        /**
+         * Shows the next available buffer.
+         * 
+         * @see java.awt.image.BufferStrategy#show()
+         */
+        @Override
+        public void show() {
+            if (true) {
+                throw new RuntimeException("Method is not implemented"); //$NON-NLS-1$
+            }
+        }
+    }
+
+    /**
+     * The FlipBufferStrategy class is for flipping buffers on a component. 
+     */
+    protected class FlipBufferStrategy extends BufferStrategy {
+        
+        /** The Buffer Capabilities. */
+        protected BufferCapabilities caps;
+
+        /** The drawing buffer. */
+        protected Image drawBuffer;
+
+        /** The drawing VolatileImage buffer. */
+        protected VolatileImage drawVBuffer;
+
+        /** The number of buffers. */
+        protected int numBuffers;
+
+        /** The validated contents indicates if the drawing buffer is restored from
+         * lost state. */
+        protected boolean validatedContents;
+
+        /**
+         * Instantiates a new flip buffer strategy.
+         * 
+         * @param numBuffers the number of buffers.
+         * @param caps the BufferCapabilities.
+         * 
+         * @throws AWTException if the capabilities supplied could not 
+         * be supported or met.
+         */
+        protected FlipBufferStrategy(int numBuffers, BufferCapabilities caps)
+                throws AWTException {
+            //???AWT
+            /*
+            if (!(Component.this instanceof Window) && !(Component.this instanceof Canvas)) {
+                // awt.14B=Only Canvas or Window is allowed
+                throw new ClassCastException(Messages.getString("awt.14B")); //$NON-NLS-1$
+            }
+            */
+            // TODO: throw new AWTException("Capabilities are not supported");
+            this.numBuffers = numBuffers;
+            this.caps = (BufferCapabilities) caps.clone();
+        }
+
+        /**
+         * Returns true if the drawing buffer has been lost since the last call 
+         * to getDrawGraphics. 
+         * 
+         * @return true if the drawing buffer has been lost since the last call 
+         * to getDrawGraphics, false otherwise.
+         * 
+         * @see java.awt.image.BufferStrategy#contentsLost()
+         */
+        @Override
+        public boolean contentsLost() {
+            if (true) {
+                throw new RuntimeException("Method is not implemented"); //$NON-NLS-1$
+            }
+            return false;
+        }
+
+        /**
+         * Returns true if the drawing buffer has been restored from a lost
+         * state and reinitialized to the default background color.
+         * 
+         * @return true if the drawing buffer has been restored from a lost
+         * state and reinitialized to the default background color,
+         * false otherwise. 
+         * 
+         * @see java.awt.image.BufferStrategy#contentsRestored()
+         */
+        @Override
+        public boolean contentsRestored() {
+            if (true) {
+                throw new RuntimeException("Method is not implemented"); //$NON-NLS-1$
+            }
+            return false;
+        }
+
+        /**
+         * Creates flipping buffers with the specified buffer capabilities.
+         * 
+         * @param numBuffers the number of buffers.
+         * @param caps the BufferCapabilities.
+         * 
+         * @throws AWTException if the capabilities could not be 
+         * supported or met.
+         */
+        protected void createBuffers(int numBuffers, BufferCapabilities caps)
+                throws AWTException {
+            if (numBuffers < 2) {
+                // awt.14C=Number of buffers must be greater than one
+                throw new IllegalArgumentException(Messages.getString("awt.14C")); //$NON-NLS-1$
+            }
+            if (!caps.isPageFlipping()) {
+                // awt.14D=Buffer capabilities should support flipping
+                throw new IllegalArgumentException(Messages.getString("awt.14D")); //$NON-NLS-1$
+            }
+            if (!Component.this.behaviour.isDisplayable()) {
+                // awt.14E=Component should be displayable
+                throw new IllegalStateException(Messages.getString("awt.14E")); //$NON-NLS-1$
+            }
+            // TODO: throw new AWTException("Capabilities are not supported");
+            if (true) {
+                throw new RuntimeException("Method is not implemented"); //$NON-NLS-1$
+            }
+        }
+
+        /**
+         * Destroy buffers.
+         */
+        protected void destroyBuffers() {
+            if (true) {
+                throw new RuntimeException("Method is not implemented"); //$NON-NLS-1$
+            }
+        }
+
+        /**
+         * Flips the contents of the back buffer to the front buffer.
+         * 
+         * @param flipAction the flip action.
+         */
+        protected void flip(BufferCapabilities.FlipContents flipAction) {
+            if (true) {
+                throw new RuntimeException("Method is not implemented"); //$NON-NLS-1$
+            }
+        }
+
+        /**
+         * Gets the back buffer as Image.
+         * 
+         * @return the back buffer as Image.
+         */
+        protected Image getBackBuffer() {
+            if (true) {
+                throw new RuntimeException("Method is not implemented"); //$NON-NLS-1$
+            }
+            return null;
+        }
+
+        /**
+         * Returns the BufferCapabilities of the buffer strategy.
+         * 
+         * @return the BufferCapabilities.
+         * 
+         * @see java.awt.image.BufferStrategy#getCapabilities()
+         */
+        @Override
+        public BufferCapabilities getCapabilities() {
+            return (BufferCapabilities) caps.clone();
+        }
+
+        /**
+         * Gets Graphics of current buffer strategy.
+         * 
+         * @return the Graphics of current buffer strategy.
+         * 
+         * @see java.awt.image.BufferStrategy#getDrawGraphics()
+         */
+        @Override
+        public Graphics getDrawGraphics() {
+            if (true) {
+                throw new RuntimeException("Method is not implemented"); //$NON-NLS-1$
+            }
+            return null;
+        }
+
+        /**
+         * Revalidates the lost drawing buffer.
+         */
+        protected void revalidate() {
+            if (true) {
+                throw new RuntimeException("Method is not implemented"); //$NON-NLS-1$
+            }
+        }
+
+        /**
+         * Shows the next available buffer.
+         * 
+         * @see java.awt.image.BufferStrategy#show()
+         */
+        @Override
+        public void show() {
+            if (true) {
+                throw new RuntimeException("Method is not implemented"); //$NON-NLS-1$
+            }
+        }
+    }
+
+    /**
+     * The internal component's state utilized by the visual theme.
+     */
+    class ComponentState implements State {
+        
+        /** The default minimum size. */
+        private Dimension defaultMinimumSize = new Dimension();
+
+        /**
+         * Checks if the component is enabled.
+         * 
+         * @return true, if the component is enabled
+         */
+        public boolean isEnabled() {
+            return enabled;
+        }
+
+        /**
+         * Checks if the component is visible.
+         * 
+         * @return true, if the component is visible
+         */
+        public boolean isVisible() {
+            return visible;
+        }
+
+        /**
+         * Checks if is focused.
+         * 
+         * @return true, if is focused
+         */
+        public boolean isFocused() {
+            //???AWT: return isFocusOwner();
+            return false;
+        }
+
+        /**
+         * Gets the font.
+         * 
+         * @return the font
+         */
+        public Font getFont() {
+            return Component.this.getFont();
+        }
+
+        /**
+         * Checks if the font has been set.
+         * 
+         * @return true, if the font has been set
+         */
+        public boolean isFontSet() {
+            return font != null;
+        }
+
+        /**
+         * Gets the background color.
+         * 
+         * @return the background color
+         */
+        public Color getBackground() {
+            Color c = Component.this.getBackground();
+            return (c != null) ? c : getDefaultBackground();
+        }
+
+        /**
+         * Checks if the background is set.
+         * 
+         * @return true, if the background is set
+         */
+        public boolean isBackgroundSet() {
+            return backColor != null;
+        }
+
+        /**
+         * Gets the text color.
+         * 
+         * @return the text color
+         */
+        public Color getTextColor() {
+            Color c = getForeground();
+            return (c != null) ? c : getDefaultForeground();
+        }
+
+        /**
+         * Checks if the text color is set.
+         * 
+         * @return true, if the text color is set
+         */
+        public boolean isTextColorSet() {
+            return foreColor != null;
+        }
+
+        /**
+         * Gets the font metrics.
+         * 
+         * @return the font metrics
+         */
+        @SuppressWarnings("deprecation")
+        public FontMetrics getFontMetrics() {
+            return toolkit.getFontMetrics(Component.this.getFont());
+        }
+
+        /**
+         * Gets the bounding rectangle.
+         * 
+         * @return the bounding rectangle
+         */
+        public Rectangle getBounds() {
+            return new Rectangle(x, y, w, h);
+        }
+
+        /**
+         * Gets the size of the bounding rectangle.
+         * 
+         * @return the size of the bounding rectangle
+         */
+        public Dimension getSize() {
+            return new Dimension(w, h);
+        }
+
+        /**
+         * Gets the window id.
+         * 
+         * @return the window id
+         */
+        public long getWindowId() {
+            NativeWindow win = getNativeWindow();
+            return (win != null) ? win.getId() : 0;
+        }
+
+        /**
+         * Gets the default minimum size.
+         * 
+         * @return the default minimum size
+         */
+        public Dimension getDefaultMinimumSize() {
+            if (defaultMinimumSize == null) {
+                calculate();
+            }
+            return defaultMinimumSize;
+        }
+
+        /**
+         * Sets the default minimum size.
+         * 
+         * @param size the new default minimum size
+         */
+        public void setDefaultMinimumSize(Dimension size) {
+            defaultMinimumSize = size;
+        }
+
+        /**
+         * Reset the default minimum size to null.
+         */
+        public void reset() {
+            defaultMinimumSize = null;
+        }
+
+        /**
+         * Calculate the default minimum size: to be overridden.
+         */
+        public void calculate() {
+            // to be overridden
+        }
+    }
+
+    //???AWT: private transient AccessibleContext accessibleContext;
+
+    /** The behaviour. */
+    final transient ComponentBehavior behaviour;
+
+    //???AWT: Container parent;
+
+    /** The name. */
+    private String name;
+
+    /** The auto name. */
+    private boolean autoName = true;
+
+    /** The font. */
+    private Font font;
+
+    /** The back color. */
+    private Color backColor;
+
+    /** The fore color. */
+    private Color foreColor;
+
+    /** The deprecated event handler. */
+    boolean deprecatedEventHandler = true;
+
+    /** The enabled events. */
+    private long enabledEvents;
+
+    /** The enabled awt events. */
+    private long enabledAWTEvents;
+
+    /** The component listeners. */
+    private final AWTListenerList<ComponentListener> componentListeners = new AWTListenerList<ComponentListener>(
+            this);
+
+    /** The focus listeners. */
+    private final AWTListenerList<FocusListener> focusListeners = new AWTListenerList<FocusListener>(
+            this);
+
+    /** The hierarchy listeners. */
+    private final AWTListenerList<HierarchyListener> hierarchyListeners = new AWTListenerList<HierarchyListener>(
+            this);
+
+    /** The hierarchy bounds listeners. */
+    private final AWTListenerList<HierarchyBoundsListener> hierarchyBoundsListeners = new AWTListenerList<HierarchyBoundsListener>(
+            this);
+
+    /** The key listeners. */
+    private final AWTListenerList<KeyListener> keyListeners = new AWTListenerList<KeyListener>(
+            this);
+
+    /** The mouse listeners. */
+    private final AWTListenerList<MouseListener> mouseListeners = new AWTListenerList<MouseListener>(
+            this);
+
+    /** The mouse motion listeners. */
+    private final AWTListenerList<MouseMotionListener> mouseMotionListeners = new AWTListenerList<MouseMotionListener>(
+            this);
+
+    /** The mouse wheel listeners. */
+    private final AWTListenerList<MouseWheelListener> mouseWheelListeners = new AWTListenerList<MouseWheelListener>(
+            this);
+
+    /** The input method listeners. */
+    private final AWTListenerList<InputMethodListener> inputMethodListeners = new AWTListenerList<InputMethodListener>(
+            this);
+
+    /** The x. */
+    int x;
+
+    /** The y. */
+    int y;
+
+    /** The w. */
+    int w;
+
+    /** The h. */
+    int h;
+
+    /** The maximum size. */
+    private Dimension maximumSize;
+
+    /** The minimum size. */
+    private Dimension minimumSize;
+
+    /** The preferred size. */
+    private Dimension preferredSize;
+
+    /** The bounds mask param. */
+    private int boundsMaskParam;
+
+    /** The ignore repaint. */
+    private boolean ignoreRepaint;
+
+    /** The enabled. */
+    private boolean enabled = true;
+
+    /** The input methods enabled. */
+    private boolean inputMethodsEnabled = true;
+
+    /** The dispatch to im. */
+    transient boolean dispatchToIM = true;
+
+    /** The focusable. */
+    private boolean focusable = true; // By default, all Components return
+
+    // true from isFocusable() method
+    /** The visible. */
+    boolean visible = true;
+
+    /** The called set focusable. */
+    private boolean calledSetFocusable;
+
+    /** The overriden is focusable. */
+    private boolean overridenIsFocusable = true;
+
+    /** The focus traversal keys enabled. */
+    private boolean focusTraversalKeysEnabled = true;
+
+    /** Possible keys are: FORWARD_TRAVERSAL_KEYS, BACKWARD_TRAVERSAL_KEYS, UP_CYCLE_TRAVERSAL_KEYS. */
+    private final Map<Integer, Set<? extends AWTKeyStroke>> traversalKeys = new HashMap<Integer, Set<? extends AWTKeyStroke>>();
+
+    /** The traversal i ds. */
+    int[] traversalIDs;
+
+    /** The locale. */
+    private Locale locale;
+
+    /** The orientation. */
+    private ComponentOrientation orientation;
+
+    /** The property change support. */
+    private PropertyChangeSupport propertyChangeSupport;
+
+    //???AWT: private ArrayList<PopupMenu> popups;
+
+    /** The coalescer. */
+    private boolean coalescer;
+
+    /** The events table. */
+    private Hashtable<Integer, LinkedList<AWTEvent>> eventsTable;
+
+    /** Cashed reference used during EventQueue.postEvent() */
+    private LinkedList<AWTEvent> eventsList;
+
+    /** The hierarchy changing counter. */
+    private int hierarchyChangingCounter;
+
+    /** The was showing. */
+    private boolean wasShowing;
+
+    /** The was displayable. */
+    private boolean wasDisplayable;
+
+    /** The cursor. */
+    Cursor cursor;
+
+    //???AWT: DropTarget dropTarget;
+
+    /** The mouse exited expected. */
+    private boolean mouseExitedExpected;
+
+    /** The repaint region. */
+    transient MultiRectArea repaintRegion;
+
+    //???AWT: transient RedrawManager redrawManager;
+    /** The redraw manager. */
+    transient Object redrawManager;
+
+    /** The valid. */
+    private boolean valid;
+
+    /** The updated images. */
+    private HashMap<Image, ImageParameters> updatedImages;
+
+    /**
+     * The lock object for private component's data which don't affect the
+     * component hierarchy.
+     */
+    private class ComponentLock {
+    }
+
+    /** The component lock. */
+    private final transient Object componentLock = new ComponentLock();
+    static {
+        PrivilegedAction<String[]> action = new PrivilegedAction<String[]>() {
+            public String[] run() {
+                String properties[] = new String[2];
+                properties[0] = System.getProperty("awt.image.redrawrate", "100"); //$NON-NLS-1$ //$NON-NLS-2$
+                properties[1] = System.getProperty("awt.image.incrementaldraw", "true"); //$NON-NLS-1$ //$NON-NLS-2$
+                return properties;
+            }
+        };
+        String properties[] = AccessController.doPrivileged(action);
+        // FIXME: rate is never used, can this code and the get property above
+        // be removed?
+        // int rate;
+        //
+        // try {
+        // rate = Integer.decode(properties[0]).intValue();
+        // } catch (NumberFormatException e) {
+        // rate = 100;
+        // }
+        incrementalImageUpdate = properties[1].equals("true"); //$NON-NLS-1$
+    }
+
+    /**
+     * Instantiates a new component.
+     */
+    protected Component() {
+        toolkit.lockAWT();
+        try {
+            orientation = ComponentOrientation.UNKNOWN;
+            redrawManager = null;
+            //???AWT
+            /*
+            traversalIDs = this instanceof Container ? KeyboardFocusManager.contTraversalIDs
+                    : KeyboardFocusManager.compTraversalIDs;
+            for (int element : traversalIDs) {
+                traversalKeys.put(new Integer(element), null);
+            }
+            behaviour = createBehavior();
+            */
+            behaviour = null;
+            
+            deriveCoalescerFlag();
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Determine that the class inherited from Component declares the method
+     * coalesceEvents(), and put the results to the childClassesFlags map.
+     */
+    private void deriveCoalescerFlag() {
+        Class<?> thisClass = getClass();
+        boolean flag = true;
+        synchronized (childClassesFlags) {
+            Boolean flagWrapper = childClassesFlags.get(thisClass);
+            if (flagWrapper == null) {
+                Method coalesceMethod = null;
+                for (Class<?> c = thisClass; c != Component.class; c = c.getSuperclass()) {
+                    try {
+                        coalesceMethod = c.getDeclaredMethod("coalesceEvents", new Class[] { //$NON-NLS-1$
+                                Class.forName("java.awt.AWTEvent"), //$NON-NLS-1$
+                                Class.forName("java.awt.AWTEvent") }); //$NON-NLS-1$
+                    } catch (Exception e) {
+                    }
+                    if (coalesceMethod != null) {
+                        break;
+                    }
+                }
+                flag = (coalesceMethod != null);
+                childClassesFlags.put(thisClass, Boolean.valueOf(flag));
+            } else {
+                flag = flagWrapper.booleanValue();
+            }
+        }
+        coalescer = flag;
+        if (flag) {
+            eventsTable = new Hashtable<Integer, LinkedList<AWTEvent>>();
+        } else {
+            eventsTable = null;
+        }
+    }
+
+    /**
+     * Sets the name of the Component.
+     * 
+     * @param name the new name of the Component.
+     */
+    public void setName(String name) {
+        String oldName;
+        toolkit.lockAWT();
+        try {
+            autoName = false;
+            oldName = this.name;
+            this.name = name;
+        } finally {
+            toolkit.unlockAWT();
+        }
+        firePropertyChange("name", oldName, name); //$NON-NLS-1$
+    }
+
+    /**
+     * Gets the name of this Component.
+     * 
+     * @return the name of this Component.
+     */
+    public String getName() {
+        toolkit.lockAWT();
+        try {
+            if ((name == null) && autoName) {
+                name = autoName();
+            }
+            return name;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Auto name.
+     * 
+     * @return the string
+     */
+    String autoName() {
+        String name = getClass().getName();
+        if (name.indexOf("$") != -1) { //$NON-NLS-1$
+            return null;
+        }
+        //???AWT
+        //int number = toolkit.autoNumber.nextComponent++;
+        int number = 0;
+        name = name.substring(name.lastIndexOf(".") + 1) + Integer.toString(number); //$NON-NLS-1$
+        return name;
+    }
+
+    /**
+     * Returns the string representation of the Component.
+     * 
+     * @return the string representation of the Component.
+     */
+    @Override
+    public String toString() {
+        /*
+         * The format is based on 1.5 release behavior which can be revealed by
+         * the following code:
+         * 
+         * Component c = new Component(){}; c.setVisible(false);
+         * System.out.println(c);
+         */
+        toolkit.lockAWT();
+        try {
+            return getClass().getName() + "[" + paramString() + "]"; //$NON-NLS-1$ //$NON-NLS-2$
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    //???AWT
+    /*
+    public void add(PopupMenu popup) {
+        toolkit.lockAWT();
+        try {
+            if (popup.getParent() == this) {
+                return;
+            }
+            if (popups == null) {
+                popups = new ArrayList<PopupMenu>();
+            }
+            popup.setParent(this);
+            popups.add(popup);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+    */
+
+    /**
+     * Returns true, if the component contains the specified Point.
+     * 
+     * @param p the Point.
+     * 
+     * @return true, if the component contains the specified Point,
+     * false otherwise.
+     */
+    public boolean contains(Point p) {
+        toolkit.lockAWT();
+        try {
+            return contains(p.x, p.y);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Returns true, if the component contains the point with 
+     * the specified coordinates.
+     * 
+     * @param x the x coordinate.
+     * @param y the y coordinate.
+     * 
+     * @return true, if the component contains the point with 
+     * the specified coordinates, false otherwise.
+     */
+    public boolean contains(int x, int y) {
+        toolkit.lockAWT();
+        try {
+            return inside(x, y);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Deprecated: replaced by replaced by getSize() method.
+     * 
+     * @return the dimension.
+     * 
+     * @deprecated Replaced by getSize() method.
+     */
+    @Deprecated
+    public Dimension size() {
+        toolkit.lockAWT();
+        try {
+            return new Dimension(w, h);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+    
+    //???AWT
+    /*
+    public Container getParent() {
+        toolkit.lockAWT();
+        try {
+            return parent;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+    */
+    
+    /**
+     * List.
+     * 
+     * @param out the out
+     * @param indent the indent
+     * 
+     * @return the nearest heavyweight ancestor in hierarchy or
+     * <code>null</code> if not found
+     */
+    //???AWT
+    /*
+    Component getHWAncestor() {
+        return (parent != null ? parent.getHWSurface() : null);
+    }
+    */
+    
+    /**
+     * @return heavyweight component that is equal to or is a nearest
+     *         heavyweight container of the current component, or
+     *         <code>null</code> if not found
+     */
+    //???AWT
+    /*
+    Component getHWSurface() {
+        Component parent;
+        for (parent = this; (parent != null) && (parent.isLightweight()); parent = parent
+                .getParent()) {
+            ;
+        }
+        return parent;
+    }
+
+    Window getWindowAncestor() {
+        Component par;
+        for (par = this; par != null && !(par instanceof Window); par = par.getParent()) {
+            ;
+        }
+        return (Window) par;
+    }
+    */
+    
+    /** To be called by container */
+    //???AWT
+    /*
+    void setParent(Container parent) {
+        this.parent = parent;
+        setRedrawManager();
+    }
+
+    void setRedrawManager() {
+        redrawManager = getRedrawManager();
+    }
+
+    public void remove(MenuComponent menu) {
+        toolkit.lockAWT();
+        try {
+            if (menu.getParent() == this) {
+                menu.setParent(null);
+                popups.remove(menu);
+            }
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+    */
+    /**
+     * Prints a list of this component with the specified number of 
+     * leading whitespace characters to the specified PrintStream.
+     * 
+     * @param out the output PrintStream object.
+     * @param indent how many leading whitespace characters to prepend
+     */
+    public void list(PrintStream out, int indent) {
+        toolkit.lockAWT();
+        try {
+            out.println(getIndentStr(indent) + this);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Prints a list of this component to the specified PrintWriter.
+     * 
+     * @param out the output PrintWriter object.
+     */
+    public void list(PrintWriter out) {
+        toolkit.lockAWT();
+        try {
+            list(out, 1);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Prints a list of this component with the specified number of 
+     * leading whitespace characters to the specified PrintWriter.
+     * 
+     * @param out the output PrintWriter object.
+     * @param indent how many leading whitespace characters to prepend
+     */
+    public void list(PrintWriter out, int indent) {
+        toolkit.lockAWT();
+        try {
+            out.println(getIndentStr(indent) + this);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Gets a string composed of the desired number of 
+     * whitespace characters.
+     * 
+     * @param indent the length of the String to return
+     * 
+     * @return the string composed of the desired number of 
+     * whitespace characters
+     */
+    String getIndentStr(int indent) {
+        char[] ind = new char[indent];
+        for (int i = 0; i < indent; ind[i++] = ' ') {
+            ;
+        }
+        return new String(ind);
+    }
+
+    /**
+     * Prints a list of this component to the specified PrintStream
+     * 
+     * @param out the output PrintStream object.
+     */
+    public void list(PrintStream out) {
+        toolkit.lockAWT();
+        try {
+            // default indent = 1
+            list(out, 1);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Prints a list of this component to the standard system 
+     * output stream.
+     */
+    public void list() {
+        toolkit.lockAWT();
+        try {
+            list(System.out);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Prints this component. 
+     * 
+     * @param g the Graphics to be used for painting. 
+     */
+    public void print(Graphics g) {
+        toolkit.lockAWT();
+        try {
+            paint(g);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Prints the component and all of its subcomponents.
+     * 
+     * @param g the Graphics to be used for painting.
+     */
+    public void printAll(Graphics g) {
+        toolkit.lockAWT();
+        try {
+            paintAll(g);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Sets the size of the Component specified by width and height
+     * parameters.
+     * 
+     * @param width the width of the Component.
+     * @param height the height of the Component.
+     */
+    public void setSize(int width, int height) {
+        toolkit.lockAWT();
+        try {
+            resize(width, height);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Sets the size of the Component specified by Dimension object.
+     * 
+     * @param d the new size of the Component.
+     */
+    public void setSize(Dimension d) {
+        toolkit.lockAWT();
+        try {
+            resize(d);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Deprecated: replaced by setSize(int, int) method.
+     * 
+     * @param width the width.
+     * @param height the height.
+     * 
+     * @deprecated Replaced by setSize(int, int) method.
+     */
+    @Deprecated
+    public void resize(int width, int height) {
+        toolkit.lockAWT();
+        try {
+            boundsMaskParam = NativeWindow.BOUNDS_NOMOVE;
+            setBounds(x, y, width, height);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Deprecated: replaced by setSize(int, int) method.
+     * 
+     * @param size the size.
+     * 
+     * @deprecated Replaced by setSize(int, int) method.
+     */
+    @Deprecated
+    public void resize(Dimension size) {
+        toolkit.lockAWT();
+        try {
+            setSize(size.width, size.height);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Checks whether or not this component is completely opaque.
+     * 
+     * @return true, if this component is completely opaque, 
+     *  false by default.
+     */
+    public boolean isOpaque() {
+        toolkit.lockAWT();
+        try {
+            return behaviour.isOpaque();
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Disables.
+     * 
+     * @deprecated Replaced by setEnabled(boolean) method.
+     */
+    @Deprecated
+    public void disable() {
+        toolkit.lockAWT();
+        try {
+            setEnabledImpl(false);
+        } finally {
+            toolkit.unlockAWT();
+        }
+        //???AWT: fireAccessibleStateChange(AccessibleState.ENABLED, false);
+    }
+
+    /**
+     * Enables this component.
+     * 
+     * @deprecated Replaced by setEnabled(boolean) method.
+     */
+    @Deprecated
+    public void enable() {
+        toolkit.lockAWT();
+        try {
+            setEnabledImpl(true);
+        } finally {
+            toolkit.unlockAWT();
+        }
+        //???AWT: fireAccessibleStateChange(AccessibleState.ENABLED, true);
+    }
+
+    /**
+     * Enables or disable this component.
+     * 
+     * @param b the boolean parameter.
+     * 
+     * @deprecated Replaced by setEnabled(boolean) method. 
+     */
+    @Deprecated
+    public void enable(boolean b) {
+        toolkit.lockAWT();
+        try {
+            if (b) {
+                enable();
+            } else {
+                disable();
+            }
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Stores the location of this component to the specified Point object;
+     * returns the point of the component's top-left corner.
+     * 
+     * @param rv the Point object where the component's top-left corner
+     * position will be stored.
+     * 
+     * @return the Point which specifies the component's top-left corner.
+     */
+    public Point getLocation(Point rv) {
+        toolkit.lockAWT();
+        try {
+            if (rv == null) {
+                rv = new Point();
+            }
+            rv.setLocation(getX(), getY());
+            return rv;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Gets the location of this component on the form;
+     * returns the point of the component's top-left corner.
+     * 
+     * @return the Point which specifies the component's top-left corner.
+     */
+    public Point getLocation() {
+        toolkit.lockAWT();
+        try {
+            return location();
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Gets the size of this Component.
+     * 
+     * @return the size of this Component.
+     */
+    public Dimension getSize() {
+        toolkit.lockAWT();
+        try {
+            return size();
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Stores the size of this Component to the specified Dimension 
+     * object.
+     * 
+     * @param rv the Dimension object where the size of the Component 
+     * will be stored.
+     * 
+     * @return the Dimension of this Component.
+     */
+    public Dimension getSize(Dimension rv) {
+        toolkit.lockAWT();
+        try {
+            if (rv == null) {
+                rv = new Dimension();
+            }
+            rv.setSize(getWidth(), getHeight());
+            return rv;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Checks whether or not this Component is valid. A component is valid 
+     * if it is correctly sized and positioned within its parent container
+     *  and all its children are also valid. 
+     * 
+     * @return true, if the Component is valid, false otherwise.
+     */
+    public boolean isValid() {
+        toolkit.lockAWT();
+        try {
+            return valid && behaviour.isDisplayable();
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Deprecated: replaced by getComponentAt(int, int) method.
+     * 
+     * @return the Point.
+     * 
+     * @deprecated Replaced by getComponentAt(int, int) method.
+     */
+    @Deprecated
+    public Point location() {
+        toolkit.lockAWT();
+        try {
+            return new Point(x, y);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Connects this Component to a native screen resource and makes it 
+     * displayable. This method not be called directly by user applications.
+     */
+    public void addNotify() {
+        toolkit.lockAWT();
+        try {
+            prepare4HierarchyChange();
+            behaviour.addNotify();
+            //???AWT
+//            finishHierarchyChange(this, parent, 0);
+//            if (dropTarget != null) {
+//                dropTarget.addNotify(peer);
+//            }
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Map to display.
+     * 
+     * @param b the b
+     */
+    void mapToDisplay(boolean b) {
+        //???AWT
+        /*
+        if (b && !isDisplayable()) {
+            if ((this instanceof Window) || ((parent != null) && parent.isDisplayable())) {
+                addNotify();
+            }
+        } else if (!b && isDisplayable()) {
+            removeNotify();
+        }
+        */
+    }
+
+    /**
+     * Gets the toolkit.
+     * 
+     * @return accessible context specific for particular component
+     */
+    //???AWT
+    /*
+    AccessibleContext createAccessibleContext() {
+        return null;
+    }
+
+    public AccessibleContext getAccessibleContext() {
+        toolkit.lockAWT();
+        try {
+            if (accessibleContext == null) {
+                accessibleContext = createAccessibleContext();
+            }
+            return accessibleContext;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+    */
+ 
+    /**
+     * Gets Toolkit for the current Component.
+     * 
+     * @return the Toolkit of this Component.
+     */
+    public Toolkit getToolkit() {
+        return toolkit;
+    }
+
+    /**
+     * Gets this component's locking object for AWT component tree 
+     * and layout operations.
+     * 
+     * @return the tree locking object.
+     */
+    public final Object getTreeLock() {
+        return toolkit.awtTreeLock;
+    }
+
+    /**
+     * @param evt the Event.
+     * @param what the event's key.
+     * 
+     * @return true, if successful.
+     * 
+     * @deprecated Use ActionListener class for registering event listener.   
+     */
+    @Deprecated
+    public boolean action(Event evt, Object what) {
+        // to be overridden: do nothing,
+        // just return false to propagate event up to the parent container
+        return false;
+    }
+
+
+    /**
+     * Gets the property change support.
+     * 
+     * @return the property change support
+     */
+    private PropertyChangeSupport getPropertyChangeSupport() {
+        synchronized (componentLock) {
+            if (propertyChangeSupport == null) {
+                propertyChangeSupport = new PropertyChangeSupport(this);
+            }
+            return propertyChangeSupport;
+        }
+    }
+    
+    //???AWT
+    /*
+    public void addPropertyChangeListener(PropertyChangeListener listener) {
+        getPropertyChangeSupport().addPropertyChangeListener(listener);
+    }
+
+    public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
+        getPropertyChangeSupport().addPropertyChangeListener(propertyName, listener);
+    }
+
+    public void applyComponentOrientation(ComponentOrientation orientation) {
+        toolkit.lockAWT();
+        try {
+            setComponentOrientation(orientation);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+    */
+
+    /**
+     * Returns true if the set of focus traversal keys for the given focus 
+     * traversal operation has been explicitly defined for this Component. 
+     * 
+     * @param id the ID of traversal key.
+     * 
+     * @return true, if the set of focus traversal keys for the given focus 
+     * traversal operation has been explicitly defined for this Component,
+     * false otherwise. 
+     */
+    public boolean areFocusTraversalKeysSet(int id) {
+        toolkit.lockAWT();
+        try {
+            Integer Id = new Integer(id);
+            if (traversalKeys.containsKey(Id)) {
+                return traversalKeys.get(Id) != null;
+            }
+            // awt.14F=invalid focus traversal key identifier
+            throw new IllegalArgumentException(Messages.getString("awt.14F")); //$NON-NLS-1$
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Gets the bounds of the Component.
+     * 
+     * @return the rectangle bounds of the Component.
+     * 
+     * @deprecated Use getBounds() methood.
+     */
+    @Deprecated
+    public Rectangle bounds() {
+        toolkit.lockAWT();
+        try {
+            return new Rectangle(x, y, w, h);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Returns the construction status of a specified image
+     * with the specified width and height that is being created.
+     * 
+     * 
+     * @param image the image to be checked.
+     * @param width the width of scaled image which status is being checked, or -1.
+     * @param height the height of scaled image which status is being checked, or -1.
+     * @param observer the ImageObserver object to be notified while 
+     * the image is being prepared.
+     * 
+     * @return the ImageObserver flags of the current state of the image data.
+     */
+    public int checkImage(Image image, int width, int height, ImageObserver observer) {
+        toolkit.lockAWT();
+        try {
+            return toolkit.checkImage(image, width, height, observer);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Returns the construction status of a specified image that is being created.
+     * 
+     * 
+     * @param image the image to be checked.
+     * @param observer the ImageObserver object to be notified while 
+     * the image is being prepared.
+     * 
+     * @return the ImageObserver flags of the current state of the image data.
+     */
+    public int checkImage(Image image, ImageObserver observer) {
+        toolkit.lockAWT();
+        try {
+            return toolkit.checkImage(image, -1, -1, observer);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Coalesces the existed event with new event.
+     * 
+     * @param existingEvent the existing event in the EventQueue.
+     * @param newEvent the new event to be posted to the EventQueue.
+     * 
+     * @return the coalesced AWTEvent, or null if there is no coalescing done. 
+     */
+    protected AWTEvent coalesceEvents(AWTEvent existingEvent, AWTEvent newEvent) {
+        toolkit.lockAWT();
+        try {
+            // Nothing to do:
+            // 1. Mouse events coalesced at WTK level
+            // 2. Paint events handled by RedrawManager
+            // This method is for overriding only
+            return null;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Checks if this Component is a coalescer.
+     * 
+     * @return true, if is coalescer
+     */
+    boolean isCoalescer() {
+        return coalescer;
+    }
+
+    /**
+     * Gets the relative event.
+     * 
+     * @param id the id
+     * 
+     * @return the relative event
+     */
+    AWTEvent getRelativeEvent(int id) {
+        Integer idWrapper = new Integer(id);
+        eventsList = eventsTable.get(idWrapper);
+        if (eventsList == null) {
+            eventsList = new LinkedList<AWTEvent>();
+            eventsTable.put(idWrapper, eventsList);
+            return null;
+        }
+        if (eventsList.isEmpty()) {
+            return null;
+        }
+        return eventsList.getLast();
+    }
+
+    /**
+     * Adds the new event.
+     * 
+     * @param event the event
+     */
+    void addNewEvent(AWTEvent event) {
+        eventsList.addLast(event);
+    }
+
+    /**
+     * Removes the relative event.
+     */
+    void removeRelativeEvent() {
+        eventsList.removeLast();
+    }
+
+    /**
+     * Removes the next event.
+     * 
+     * @param id the id
+     */
+    void removeNextEvent(int id) {
+        eventsTable.get(new Integer(id)).removeFirst();
+    }
+
+    /**
+     * Creates the image with the specified ImageProducer.
+     * 
+     * @param producer the ImageProducer to be used for image creation.
+     * 
+     * @return the image with the specified ImageProducer.
+     */
+    public Image createImage(ImageProducer producer) {
+        toolkit.lockAWT();
+        try {
+            return toolkit.createImage(producer);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Creates an off-screen drawable image to be used for double buffering.
+     * 
+     * @param width the width of the image.
+     * @param height the height of the image.
+     * 
+     * @return the off-screen drawable image or null if the component is not 
+     * displayable or GraphicsEnvironment.isHeadless() method returns true.
+     */
+    public Image createImage(int width, int height) {
+        toolkit.lockAWT();
+        try {
+            if (!isDisplayable()) {
+                return null;
+            }
+            GraphicsConfiguration gc = getGraphicsConfiguration();
+            if (gc == null) {
+                return null;
+            }
+            ColorModel cm = gc.getColorModel(Transparency.OPAQUE);
+            WritableRaster wr = cm.createCompatibleWritableRaster(width, height);
+            Image image = new BufferedImage(cm, wr, cm.isAlphaPremultiplied(), null);
+            fillImageBackground(image, width, height);
+            return image;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Creates an off-screen drawable image with the specified width,
+     * height and ImageCapabilities.
+     * 
+     * @param width the width
+     * @param height the height
+     * @param caps the ImageCapabilities.
+     * 
+     * @return the volatile image
+     * 
+     * @throws AWTException if an image with the specified capabilities 
+     * cannot be created.
+     */
+    public VolatileImage createVolatileImage(int width, int height, ImageCapabilities caps)
+            throws AWTException {
+        toolkit.lockAWT();
+        try {
+            if (!isDisplayable()) {
+                return null;
+            }
+            GraphicsConfiguration gc = getGraphicsConfiguration();
+            if (gc == null) {
+                return null;
+            }
+            VolatileImage image = gc.createCompatibleVolatileImage(width, height, caps);
+            fillImageBackground(image, width, height);
+            return image;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Creates a volatile off-screen drawable image which is used 
+     * for double buffering.
+     * 
+     * @param width the width of image.
+     * @param height the height of image.
+     * 
+     * @return the volatile image a volatile off-screen drawable image 
+     * which is used for double buffering or null if the component 
+     * is not displayable, or GraphicsEnvironment.isHeadless() method
+     * returns true.
+     */
+    public VolatileImage createVolatileImage(int width, int height) {
+        toolkit.lockAWT();
+        try {
+            if (!isDisplayable()) {
+                return null;
+            }
+            GraphicsConfiguration gc = getGraphicsConfiguration();
+            if (gc == null) {
+                return null;
+            }
+            VolatileImage image = gc.createCompatibleVolatileImage(width, height);
+            fillImageBackground(image, width, height);
+            return image;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Fill the image being created by createImage() or createVolatileImage()
+     * with the component's background color to prepare it for double-buffered
+     * painting.
+     * 
+     * @param image the image
+     * @param width the width
+     * @param height the height
+     */
+    private void fillImageBackground(Image image, int width, int height) {
+        Graphics gr = image.getGraphics();
+        gr.setColor(getBackground());
+        gr.fillRect(0, 0, width, height);
+        gr.dispose();
+    }
+
+    /**
+     * Delivers event.
+     * 
+     * @param evt the event.
+     * 
+     * @deprecated Replaced by dispatchEvent(AWTEvent e) method.
+     */
+    @Deprecated
+    public void deliverEvent(Event evt) {
+        postEvent(evt);
+    }
+
+    /**
+     * Prompts the layout manager to lay out this component. 
+     */
+    public void doLayout() {
+        toolkit.lockAWT();
+        try {
+            layout();
+        } finally {
+            toolkit.unlockAWT();
+        }
+        // Implemented in Container
+    }
+
+    /**
+     * Fire property change impl.
+     * 
+     * @param propertyName the property name
+     * @param oldValue the old value
+     * @param newValue the new value
+     */
+    private void firePropertyChangeImpl(String propertyName, Object oldValue, Object newValue) {
+        PropertyChangeSupport pcs;
+        synchronized (componentLock) {
+            if (propertyChangeSupport == null) {
+                return;
+            }
+            pcs = propertyChangeSupport;
+        }
+        pcs.firePropertyChange(propertyName, oldValue, newValue);
+    }
+
+    /**
+     * Reports a bound property changes for int properties.
+     * 
+     * @param propertyName the property name.
+     * @param oldValue the old property's value.
+     * @param newValue the new property's value.
+     */
+    protected void firePropertyChange(String propertyName, int oldValue, int newValue) {
+        firePropertyChangeImpl(propertyName, new Integer(oldValue), new Integer(newValue));
+    }
+
+    /**
+     * Report a bound property change for a boolean-valued property. 
+     *  
+     * @param propertyName the property name.
+     * @param oldValue the property's old value.
+     * @param newValue the property's new value.
+     */
+    protected void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {
+        firePropertyChangeImpl(propertyName, Boolean.valueOf(oldValue), Boolean
+                .valueOf(newValue));
+    }
+
+    /**
+     * Reports a bound property change for an Object-valued property. 
+     * 
+     * @param propertyName the property name.
+     * @param oldValue the property's old value
+     * @param newValue the property's new value
+     */
+    protected void firePropertyChange(final String propertyName, final Object oldValue,
+            final Object newValue) {
+        firePropertyChangeImpl(propertyName, oldValue, newValue);
+    }
+
+    /**
+     * Report a bound property change for a byte-valued property. 
+     * 
+     * @param propertyName the property name.
+     * @param oldValue the property's old value.
+     * @param newValue the property's new value.
+     */
+    public void firePropertyChange(String propertyName, byte oldValue, byte newValue) {
+        firePropertyChangeImpl(propertyName, new Byte(oldValue), new Byte(newValue));
+    }
+
+    /**
+     * Report a bound property change for a char-valued property. 
+     * 
+     * @param propertyName the property name.
+     * @param oldValue the old property's value.
+     * @param newValue the new property's value.
+     */
+    public void firePropertyChange(String propertyName, char oldValue, char newValue) {
+        firePropertyChangeImpl(propertyName, new Character(oldValue), new Character(newValue));
+    }
+
+    /**
+     * Report a bound property change for a short-valued property. 
+     * 
+     * @param propertyName the property name.
+     * @param oldValue the old property's value.
+     * @param newValue the new property's value.
+     */
+    public void firePropertyChange(String propertyName, short oldValue, short newValue) {
+        firePropertyChangeImpl(propertyName, new Short(oldValue), new Short(newValue));
+    }
+
+    /**
+     * Report a bound property change for a long-valued property. 
+     * 
+     * @param propertyName the property name.
+     * @param oldValue the old property's value.
+     * @param newValue the new property's value.
+     */
+    public void firePropertyChange(String propertyName, long oldValue, long newValue) {
+        firePropertyChangeImpl(propertyName, new Long(oldValue), new Long(newValue));
+    }
+
+    /**
+     * Report a bound property change for a float-valued property. 
+     * 
+     * @param propertyName the property name.
+     * @param oldValue the old property's value.
+     * @param newValue the new property's value.
+     */
+    public void firePropertyChange(String propertyName, float oldValue, float newValue) {
+        firePropertyChangeImpl(propertyName, new Float(oldValue), new Float(newValue));
+    }
+
+    /**
+     * Report a bound property change for a double-valued property. 
+     * 
+     * @param propertyName the property name.
+     * @param oldValue the old property's value.
+     * @param newValue the new property's value.
+     */
+    public void firePropertyChange(String propertyName, double oldValue, double newValue) {
+        firePropertyChangeImpl(propertyName, new Double(oldValue), new Double(newValue));
+    }
+
+    /**
+     * Gets the alignment along the x axis. 
+     * 
+     * @return the alignment along the x axis. 
+     */
+    public float getAlignmentX() {
+        toolkit.lockAWT();
+        try {
+            return CENTER_ALIGNMENT;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Gets the alignment along the y axis. 
+     * 
+     * @return the alignment along y axis.
+     */
+    public float getAlignmentY() {
+        toolkit.lockAWT();
+        try {
+            return CENTER_ALIGNMENT;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Gets the background color for this component.
+     * 
+     * @return the background color for this component.
+     */
+    public Color getBackground() {
+        toolkit.lockAWT();
+        try {
+            //???AWT
+            /*
+            if ((backColor == null) && (parent != null)) {
+                return parent.getBackground();
+            }
+            */
+            return backColor;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Gets the bounding rectangle of this component.
+     * 
+     * @return the bounding rectangle of this component.
+     */
+    public Rectangle getBounds() {
+        toolkit.lockAWT();
+        try {
+            return bounds();
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Writes the data of the bounding rectangle to the specified 
+     * Rectangle object.
+     * 
+     * @param rv the Rectangle object where the bounding rectangle's data is stored.  
+     * 
+     * @return the bounding rectangle.
+     */
+    public Rectangle getBounds(Rectangle rv) {
+        toolkit.lockAWT();
+        try {
+            if (rv == null) {
+                rv = new Rectangle();
+            }
+            rv.setBounds(x, y, w, h);
+            return rv;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Gets the color model of the Component.
+     * 
+     * @return the color model of the Component.
+     */
+    public ColorModel getColorModel() {
+        toolkit.lockAWT();
+        try {
+            return getToolkit().getColorModel();
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Gets the Component which contains the specified Point.
+     * 
+     * @param p the Point.
+     * 
+     * @return the Component which contains the specified Point.
+     */
+    public Component getComponentAt(Point p) {
+        toolkit.lockAWT();
+        try {
+            return getComponentAt(p.x, p.y);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Gets the Component which contains the point with the
+     * specified coordinates.
+     * 
+     * @param x the x coordinate of the point.
+     * @param y the y coordinate of the point.
+     * 
+     * @return the Component which contains the point with the
+     * specified coordinates.
+     */
+    public Component getComponentAt(int x, int y) {
+        toolkit.lockAWT();
+        try {
+            return locate(x, y);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Gets the component's orientation.
+     * 
+     * @return the component's orientation.
+     */
+    public ComponentOrientation getComponentOrientation() {
+        toolkit.lockAWT();
+        try {
+            return orientation;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Gets the cursor of the Component.
+     * 
+     * @return the Cursor.
+     */
+    public Cursor getCursor() {
+        toolkit.lockAWT();
+        try {
+            if (cursor != null) {
+                return cursor;
+            //???AWT
+            /*
+            } else if (parent != null) {
+                return parent.getCursor();
+            */
+            }
+            return Cursor.getDefaultCursor();
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    //???AWT
+    /*
+    public DropTarget getDropTarget() {
+        toolkit.lockAWT();
+        try {
+            return dropTarget;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+    
+    public Container getFocusCycleRootAncestor() {
+        toolkit.lockAWT();
+        try {
+            for (Container c = parent; c != null; c = c.getParent()) {
+                if (c.isFocusCycleRoot()) {
+                    return c;
+                }
+            }
+            return null;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+    
+    @SuppressWarnings("unchecked")
+    public Set<AWTKeyStroke> getFocusTraversalKeys(int id) {
+        toolkit.lockAWT();
+        try {
+            Integer kId = new Integer(id);
+            KeyboardFocusManager.checkTraversalKeysID(traversalKeys, kId);
+            Set<? extends AWTKeyStroke> keys = traversalKeys.get(kId);
+            if (keys == null && parent != null) {
+                keys = parent.getFocusTraversalKeys(id);
+            }
+            if (keys == null) {
+                keys = KeyboardFocusManager.getCurrentKeyboardFocusManager()
+                        .getDefaultFocusTraversalKeys(id);
+            }
+            return (Set<AWTKeyStroke>) keys;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+    */
+    
+    /**
+     * Checks if the the focus traversal keys are enabled for this component.
+     * 
+     * @return true, if the the focus traversal keys are enabled for 
+     * this component, false otherwise.
+     */
+    public boolean getFocusTraversalKeysEnabled() {
+        toolkit.lockAWT();
+        try {
+            return focusTraversalKeysEnabled;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Gets the font metrics of the specified Font.
+     * 
+     * @param f the Font.
+     * 
+     * @return the FontMetrics of the specified Font.
+     */
+    @SuppressWarnings("deprecation")
+    public FontMetrics getFontMetrics(Font f) {
+        return toolkit.getFontMetrics(f);
+    }
+
+    /**
+     * Gets the foreground color of the Component.
+     * 
+     * @return the foreground color of the Component.
+     */
+    public Color getForeground() {
+        toolkit.lockAWT();
+        try {
+            //???AWT
+            /*
+            if (foreColor == null && parent != null) {
+                return parent.getForeground();
+            }
+            */
+            return foreColor;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Gets the Graphics of the Component or null if this Component
+     * is not displayable.
+     * 
+     * @return the Graphics of the Component or null if this Component
+     * is not displayable.
+     */
+    public Graphics getGraphics() {
+        toolkit.lockAWT();
+        try {
+            if (!isDisplayable()) {
+                return null;
+            }
+            Graphics g = behaviour.getGraphics(0, 0, w, h);
+            g.setColor(foreColor);
+            g.setFont(font);
+            return g;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+
+    /**
+     * Gets the GraphicsConfiguration associated with this Component.
+     * 
+     * @return the GraphicsConfiguration associated with this Component.
+     */
+    public GraphicsConfiguration getGraphicsConfiguration() {
+        //???AWT
+        /*
+        toolkit.lockAWT();
+        try {
+            Window win = getWindowAncestor();
+            if (win == null) {
+                return null;
+            }
+            return win.getGraphicsConfiguration();
+        } finally {
+            toolkit.unlockAWT();
+        }
+        */
+        return null;
+    }
+
+    /**
+     * Gets the height of the Component.
+     * 
+     * @return the height of the Component.
+     */
+    public int getHeight() {
+        toolkit.lockAWT();
+        try {
+            return h;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Returns true if paint messages received from the operating system 
+     * should be ignored.
+     * 
+     * @return true if paint messages received from the operating system 
+     * should be ignored, false otherwise.
+     */
+    public boolean getIgnoreRepaint() {
+        toolkit.lockAWT();
+        try {
+            return ignoreRepaint;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Gets the input context of this component for handling 
+     * the communication with input methods when text is entered 
+     * in this component.
+     * 
+     * @return the InputContext used by this Component or 
+     * null if no context is specifined.
+     */
+    public InputContext getInputContext() {
+        toolkit.lockAWT();
+        try {
+            //???AWT
+            /*
+            Container parent = getParent();
+            if (parent != null) {
+                return parent.getInputContext();
+            }
+            */
+            return null;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Gets the input method request handler which supports requests
+     * from input methods for this component, or null for default.
+     * 
+     * @return the input method request handler which supports requests
+     * from input methods for this component, or null for default.
+     */
+    public InputMethodRequests getInputMethodRequests() {
+        return null;
+    }
+
+    /**
+     * Gets the locale of this Component.
+     * 
+     * @return the locale of this Component.
+     */
+    public Locale getLocale() {
+        toolkit.lockAWT();
+        try {
+            //???AWT
+            /*
+            if (locale == null) {
+                if (parent == null) {
+                    if (this instanceof Window) {
+                        return Locale.getDefault();
+                    }
+                    // awt.150=no parent
+                    throw new IllegalComponentStateException(Messages.getString("awt.150")); //$NON-NLS-1$
+                }
+                return getParent().getLocale();
+            }
+            */
+            return locale;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Gets the location of this component in the form of a point 
+     * specifying the component's top-left corner in the 
+     * screen's coordinate space.
+     * 
+     * @return the Point giving the component's location in the 
+     * screen's coordinate space.
+     * 
+     * @throws IllegalComponentStateException if the component is 
+     * not shown on the screen.
+     */
+    public Point getLocationOnScreen() throws IllegalComponentStateException {
+        toolkit.lockAWT();
+        try {
+            Point p = new Point();
+            if (isShowing()) {
+                //???AWT
+                /*
+                Component comp;
+                for (comp = this; comp != null && !(comp instanceof Window); comp = comp
+                        .getParent()) {
+                    p.translate(comp.getX(), comp.getY());
+                }
+                if (comp instanceof Window) {
+                    p.translate(comp.getX(), comp.getY());
+                }
+                */
+                return p;
+            }
+            // awt.151=component must be showing on the screen to determine its location
+            throw new IllegalComponentStateException(Messages.getString("awt.151")); //$NON-NLS-1$
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Gets the peer. This method should not be called directly by
+     * user applications.
+     * 
+     * @return the ComponentPeer.
+     * 
+     * @deprecated Replaced by isDisplayable().
+     */
+    @Deprecated
+    public ComponentPeer getPeer() {
+        toolkit.lockAWT();
+        try {
+            if (behaviour.isDisplayable()) {
+                return peer;
+            }
+            return null;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Gets an array of the property change listeners registered to
+     * this Component.
+     * 
+     * @return an array of the PropertyChangeListeners registered to
+     * this Component.
+     */
+    public PropertyChangeListener[] getPropertyChangeListeners() {
+        return getPropertyChangeSupport().getPropertyChangeListeners();
+    }
+
+    /**
+     * Gets an array of PropertyChangeListener objects registered
+     * to this Component for the specified property.
+     * 
+     * @param propertyName the property name.
+     * 
+     * @return an array of PropertyChangeListener objects registered
+     * to this Component for the specified property.
+     */
+    public PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
+        return getPropertyChangeSupport().getPropertyChangeListeners(propertyName);
+    }
+
+    /**
+     * Gets the width of the Component.
+     * 
+     * @return the width of the Component.
+     */
+    public int getWidth() {
+        toolkit.lockAWT();
+        try {
+            return w;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Gets the x coordinate of the component's top-left corner.
+     * 
+     * @return the x coordinate of the component's top-left corner.
+     */
+    public int getX() {
+        toolkit.lockAWT();
+        try {
+            return x;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Gets the y coordinate of the component's top-left corner.
+     * 
+     * @return the y coordinate of the component's top-left corner.
+     */
+    public int getY() {
+        toolkit.lockAWT();
+        try {
+            return y;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Got the focus.
+     * 
+     * @param evt the Event.
+     * @param what the Object.
+     * 
+     * @return true, if successful.
+     * 
+     * @deprecated Replaced by processFocusEvent(FocusEvent) method.
+     */
+    @Deprecated
+    public boolean gotFocus(Event evt, Object what) {
+        // to be overridden: do nothing,
+        // just return false to propagate event up to the parent container
+        return false;
+    }
+
+    /**
+     * Handles event.
+     * 
+     * @param evt the Event.
+     * 
+     * @return true, if successful.
+     * 
+     * @deprecated Replaced by processEvent(AWTEvent) method.
+     */
+    @Deprecated
+    public boolean handleEvent(Event evt) {
+        switch (evt.id) {
+            case Event.ACTION_EVENT:
+                return action(evt, evt.arg);
+            case Event.GOT_FOCUS:
+                return gotFocus(evt, null);
+            case Event.LOST_FOCUS:
+                return lostFocus(evt, null);
+            case Event.MOUSE_DOWN:
+                return mouseDown(evt, evt.x, evt.y);
+            case Event.MOUSE_DRAG:
+                return mouseDrag(evt, evt.x, evt.y);
+            case Event.MOUSE_ENTER:
+                return mouseEnter(evt, evt.x, evt.y);
+            case Event.MOUSE_EXIT:
+                return mouseExit(evt, evt.x, evt.y);
+            case Event.MOUSE_MOVE:
+                return mouseMove(evt, evt.x, evt.y);
+            case Event.MOUSE_UP:
+                return mouseUp(evt, evt.x, evt.y);
+            case Event.KEY_ACTION:
+            case Event.KEY_PRESS:
+                return keyDown(evt, evt.key);
+            case Event.KEY_ACTION_RELEASE:
+            case Event.KEY_RELEASE:
+                return keyUp(evt, evt.key);
+        }
+        return false;// event not handled
+    }
+
+    /**
+     * Checks whether the Component is the focus owner or not.
+     * 
+     * @return true, if the Component is the focus owner, false otherwise.
+     */
+    public boolean hasFocus() {
+        toolkit.lockAWT();
+        try {
+            //???AWT: return isFocusOwner();
+            return false;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Hides the Component.
+     * 
+     * @deprecated Replaced by setVisible(boolean) method.
+     */
+    @Deprecated
+    public void hide() {
+        toolkit.lockAWT();
+        try {
+            if (!visible) {
+                return;
+            }
+            prepare4HierarchyChange();
+            visible = false;
+            moveFocusOnHide();
+            behaviour.setVisible(false);
+            postEvent(new ComponentEvent(this, ComponentEvent.COMPONENT_HIDDEN));
+            //???AWT: finishHierarchyChange(this, parent, 0);
+            notifyInputMethod(null);
+            //???AWT: invalidateRealParent();
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Checks whether or not the point with the specified coordinates 
+     * belongs to the Commponent.
+     * 
+     * @param x the x coordinate of the Point.
+     * @param y the y coordinate of the Point.
+     * 
+     * @return true, if the point with the specified coordinates 
+     * belongs to the Commponent, false otherwise.
+     * 
+     * @deprecated Replaced by contains(int, int) method.
+     */
+    @Deprecated
+    public boolean inside(int x, int y) {
+        toolkit.lockAWT();
+        try {
+            return x >= 0 && x < getWidth() && y >= 0 && y < getHeight();
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Invalidates the component, this component and all parents 
+     * above it are marked as needing to be laid out. 
+     */
+    public void invalidate() {
+        toolkit.lockAWT();
+        try {
+            valid = false;
+            resetDefaultSize();
+            //???AWT: invalidateRealParent();
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Checks whether or not the background color is set to this Component.
+     * 
+     * @return true, if the background color is set to this Component,
+     * false otherwise.
+     */
+    public boolean isBackgroundSet() {
+        toolkit.lockAWT();
+        try {
+            return backColor != null;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Checks whether or not a cursor is set for the Component.
+     * 
+     * @return true, if a cursor is set for the Component,
+     * false otherwise.
+     */
+    public boolean isCursorSet() {
+        toolkit.lockAWT();
+        try {
+            return cursor != null;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Checks whether or not this Component is displayable.
+     * 
+     * @return true, if this Component is displayable, false otherwise.
+     */
+    public boolean isDisplayable() {
+        toolkit.lockAWT();
+        try {
+            return behaviour.isDisplayable();
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Checks whether or not this component is painted to an buffer
+     * which is copied to the screen later.
+     * 
+     * @return true, if this component is painted to an buffer
+     * which is copied to the screen later, false otherwise.
+     */
+    public boolean isDoubleBuffered() {
+        toolkit.lockAWT();
+        try {
+            // false by default
+            return false;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Checks whether or not this Component is enabled.
+     * 
+     * @return true, if this Component is enabled, false otherwise.
+     */
+    public boolean isEnabled() {
+        toolkit.lockAWT();
+        try {
+            return enabled;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * "Recursive" isEnabled().
+     * 
+     * @return true if not only component itself is enabled but its heavyweight
+     * parent is also "indirectly" enabled
+     */
+    boolean isIndirectlyEnabled() {
+        Component comp = this;
+        while (comp != null) {
+            if (!comp.isLightweight() && !comp.isEnabled()) {
+                return false;
+            }
+            //???AWT: comp = comp.getRealParent();
+        }
+        return true;
+    }
+
+    /**
+     * Checks if the component is key enabled.
+     * 
+     * @return true, if the component is enabled and indirectly enabled
+     */
+    boolean isKeyEnabled() {
+        if (!isEnabled()) {
+            return false;
+        }
+        return isIndirectlyEnabled();
+    }
+
+    /**
+     * Gets only parent of a child component, but not owner of a window.
+     * 
+     * @return parent of child component, null if component is a top-level
+     * (Window instance)
+     */
+    //???AWT
+    /*
+    Container getRealParent() {
+        return (!(this instanceof Window) ? getParent() : null);
+    }
+
+    public boolean isFocusCycleRoot(Container container) {
+        toolkit.lockAWT();
+        try {
+            return getFocusCycleRootAncestor() == container;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    public boolean isFocusOwner() {
+        toolkit.lockAWT();
+        try {
+            return KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() == this;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+    */
+    
+    /**
+     * Checks whether or not this Component can be focusable.
+     * 
+     * @return true, if this Component can be focusable, false otherwise.
+     * 
+     * @deprecated Replaced by isFocusable(). 
+     */
+    @Deprecated
+    public boolean isFocusTraversable() {
+        toolkit.lockAWT();
+        try {
+            overridenIsFocusable = false;
+            return focusable; // a Component must either be both focusable and
+            // focus traversable, or neither
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Checks if this Component can be focusable or not.
+     * 
+     * @return true, if this Component can be focusable, false otherwise.
+     */
+    public boolean isFocusable() {
+        toolkit.lockAWT();
+        try {
+            return isFocusTraversable();
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Checks if the Font is set for this Component or not.
+     * 
+     * @return true, if the Font is set, false otherwise.
+     */
+    public boolean isFontSet() {
+        toolkit.lockAWT();
+        try {
+            return font != null;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Checks if foreground color is set for the Component or not.
+     * 
+     * @return true, if is foreground color is set for the Component,
+     * false otherwise.
+     */
+    public boolean isForegroundSet() {
+        toolkit.lockAWT();
+        try {
+            return foreColor != null;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Returns true if this component has a lightweight peer.
+     * 
+     * @return true, if this component has a lightweight peer,
+     * false if it has a native peer or no peer.
+     */
+    public boolean isLightweight() {
+        toolkit.lockAWT();
+        try {
+            return behaviour.isLightweight();
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+
+    /**
+     * Checks whether or not this Component is shown.
+     * 
+     * @return true, if this Component is shown, false otherwise.
+     */
+    public boolean isShowing() {
+        //???AWT
+        /*
+        toolkit.lockAWT();
+        try {
+            return (isVisible() && isDisplayable() && (parent != null) && parent.isShowing());
+        } finally {
+            toolkit.unlockAWT();
+        }
+        */
+        return false;
+    }
+
+    /**
+     * Checks whether or not this Component is visible.
+     * 
+     * @return true, if the Component is visible, false otherwise.
+     */
+    public boolean isVisible() {
+        toolkit.lockAWT();
+        try {
+            return visible;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Deprecated: replaced by processKeyEvent(KeyEvent) method.
+     * 
+     * @param evt the Event.
+     * @param key the key code.
+     * 
+     * @return true, if successful.
+     * 
+     * @deprecated Replaced by replaced by processKeyEvent(KeyEvent) method.
+     */
+    @Deprecated
+    public boolean keyDown(Event evt, int key) {
+        // to be overridden: do nothing,
+        // just return false to propagate event up to the parent container
+        return false;
+    }
+
+    /**
+     * Deprecated: replaced by processKeyEvent(KeyEvent) method.
+     * 
+     * @param evt the Event.
+     * @param key the key code.
+     * 
+     * @return true, if successful.
+     * 
+     * @deprecated Replaced by processKeyEvent(KeyEvent) method.
+     */
+    @Deprecated
+    public boolean keyUp(Event evt, int key) {
+        // to be overridden: do nothing,
+        // just return false to propagate event up to the parent container
+        return false;
+    }
+
+    /**
+     * Deprecated: Replaced by doLayout() method.
+     * 
+     * @deprecated Replaced by doLayout() method.
+     */
+    @Deprecated
+    public void layout() {
+        toolkit.lockAWT();
+        try {
+            // Implemented in Container
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Deprecated: replaced by getComponentAt(int, int) method.
+     * 
+     * @param x the x coordinate.
+     * @param y the y coordinate.
+     * 
+     * @return The component.
+     * 
+     * @deprecated Replaced by getComponentAt(int, int) method.
+     */
+    @Deprecated
+    public Component locate(int x, int y) {
+        toolkit.lockAWT();
+        try {
+            if (contains(x, y)) {
+                return this;
+            }
+            return null;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Deprecated: replaced by processFocusEvent(FocusEvent). 
+     * 
+     * @param evt the Event.
+     * @param what the Object.
+     * 
+     * @return true, if successful.
+     * 
+     * @deprecated Replaced by processFocusEvent(FocusEvent).
+     */
+    @Deprecated
+    public boolean lostFocus(Event evt, Object what) {
+        // to be overridden: do nothing,
+        // just return false to propagate event up to the parent container
+        return false;
+    }
+
+    /**
+     * Deprecated: replaced by processMouseEvent(MouseEvent) method.
+     * 
+     * @param evt the MouseEvent.
+     * @param x the x coordinate.
+     * @param y the y coordinate.
+     * 
+     * @return true, if successful.
+     * 
+     * @deprecated Replaced by processMouseEvent(MouseEvent) method.
+     */
+    @Deprecated
+    public boolean mouseDown(Event evt, int x, int y) {
+        // to be overridden: do nothing,
+        // just return false to propagate event up to the parent container
+        return false;
+    }
+
+    /**
+     * Deprecated: replaced by getMinimumSize() method.
+     * 
+     * @param evt the Event.
+     * @param x the x coordinate.
+     * @param y the y coordinate.
+     * 
+     * @return true, if successful.
+     * 
+     * @deprecated Replaced by getMinimumSize() method.
+     */
+    @Deprecated
+    public boolean mouseDrag(Event evt, int x, int y) {
+        // to be overridden: do nothing,
+        // just return false to propagate event up to the parent container
+        return false;
+    }
+
+    /**
+     * Replaced by processMouseEvent(MouseEvent) method.
+     * 
+     * @param evt the Event.
+     * @param x the x coordinate.
+     * @param y the y coordinate.
+     * 
+     * @return true, if successful.
+     * 
+     * @deprecated replaced by processMouseEvent(MouseEvent) method.
+     */
+    @Deprecated
+    public boolean mouseEnter(Event evt, int x, int y) {
+        // to be overridden: do nothing,
+        // just return false to propagate event up to the parent container
+        return false;
+    }
+
+    /**
+     * Replaced by processMouseEvent(MouseEvent) method.
+     * 
+     * @param evt the Event.
+     * @param x the x coordinate.
+     * @param y the y coordinate.
+     * 
+     * @return true, if successful.
+     * 
+     * @deprecated Replaced by processMouseEvent(MouseEvent) method.
+     */
+    @Deprecated
+    public boolean mouseExit(Event evt, int x, int y) {
+        // to be overridden: do nothing,
+        // just return false to propagate event up to the parent container
+        return false;
+    }
+
+    /**
+     * Replaced by processMouseEvent(MouseEvent) method.
+     * 
+     * @param evt the Event.
+     * @param x the x coordinate.
+     * @param y the y coordinate.
+     * 
+     * @deprecated Replaced by processMouseEvent(MouseEvent) method.
+     * 
+     * @return true, if successful.
+     */
+    @Deprecated
+    public boolean mouseMove(Event evt, int x, int y) {
+        // to be overridden: do nothing,
+        // just return false to propagate event up to the parent container
+        return false;
+    }
+
+    /**
+     * Replaced by processMouseEvent(MouseEvent) method.
+     * 
+     * @param evt the Event.
+     * @param x the x coordinate.
+     * @param y the y coordinate.
+     * 
+     * @return true, if successful.
+     * 
+     * @deprecated Replaced by processMouseEvent(MouseEvent) method.
+     */
+    @Deprecated
+    public boolean mouseUp(Event evt, int x, int y) {
+        // to be overridden: do nothing,
+        // just return false to propagate event up to the parent container
+        return false;
+    }
+
+    /**
+     * Deprecated: replaced by setLocation(int, int) method.
+     * 
+     * @param x the x coordinates.
+     * @param y the y coordinates.
+     * 
+     * @deprecated Replaced by setLocation(int, int) method.
+     */
+    @Deprecated
+    public void move(int x, int y) {
+        toolkit.lockAWT();
+        try {
+            boundsMaskParam = NativeWindow.BOUNDS_NOSIZE;
+            setBounds(x, y, w, h);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    //???AWT
+    /*
+    @Deprecated
+    public void nextFocus() {
+        toolkit.lockAWT();
+        try {
+            transferFocus(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+    */
+
+    /**
+     * Returns a string representation of the component's state.
+     * 
+     * @return the string representation of the component's state.
+     */
+    protected String paramString() {
+        /*
+         * The format is based on 1.5 release behavior which can be revealed by
+         * the following code:
+         * 
+         * Component c = new Component(){}; c.setVisible(false);
+         * System.out.println(c);
+         */
+        toolkit.lockAWT();
+        try {
+            return getName() + "," + getX() + "," + getY() + "," + getWidth() + "x" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+                    + getHeight() + (!isVisible() ? ",hidden" : ""); //$NON-NLS-1$ //$NON-NLS-2$
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    @Deprecated
+    @SuppressWarnings("deprecation")
+    public boolean postEvent(Event evt) {
+        boolean handled = handleEvent(evt);
+        if (handled) {
+            return true;
+        }
+        //???AWT
+        /*
+
+        // propagate non-handled events up to parent
+        Component par = parent;
+        // try to call postEvent only on components which
+        // override any of deprecated method handlers
+        // while (par != null && !par.deprecatedEventHandler) {
+        // par = par.parent;
+        // }
+        // translate event coordinates before posting it to parent
+        if (par != null) {
+            evt.translate(x, y);
+            par.postEvent(evt);
+        }
+        
+        */
+        return false;
+    }
+
+    /**
+     * Prepares an image for rendering on the Component. 
+     *  
+     * @param image the Image to be prepared.
+     * @param observer the ImageObserver object to be notified as soon as 
+     * the image is prepared.
+     * 
+     * @return true if the image has been fully prepared,
+     * false otherwise.
+     */
+    public boolean prepareImage(Image image, ImageObserver observer) {
+        toolkit.lockAWT();
+        try {
+            return toolkit.prepareImage(image, -1, -1, observer);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Prepares an image for rendering on the Component with the
+     * specified width, height, and ImageObserver. 
+     * 
+     * @param image the Image to be prepared.
+     * @param width the width of scaled image.
+     * @param height the height of scaled height.
+     * @param observer the ImageObserver object to be notified as soon as 
+     * the image is prepared.
+     * 
+     * @return true if the image is been fully prepared,
+     * false otherwise.
+     */
+    public boolean prepareImage(Image image, int width, int height, ImageObserver observer) {
+        toolkit.lockAWT();
+        try {
+            return toolkit.prepareImage(image, width, height, observer);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Makes this Component undisplayable.
+     */
+    public void removeNotify() {
+        toolkit.lockAWT();
+        try {
+            //???AWT
+            /*
+            if (dropTarget != null) {
+                dropTarget.removeNotify(peer);
+            }
+            */
+            prepare4HierarchyChange();
+            ///???AWT: moveFocus();
+            behaviour.removeNotify();
+            //???AWT: finishHierarchyChange(this, parent, 0);
+            removeNotifyInputContext();
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Calls InputContext.removeNotify
+     */
+    private void removeNotifyInputContext() {
+        if (!inputMethodsEnabled) {
+            return;
+        }
+        InputContext ic = getInputContext();
+        if (ic != null) {
+            //???AWT: ic.removeNotify(this);
+        }
+    }
+
+    /**
+     * This method is called when some property of a component changes, making
+     * it unfocusable, e. g. hide(), removeNotify(), setEnabled(false),
+     * setFocusable(false) is called, and therefore automatic forward focus
+     * traversal is necessary
+     */
+    //???AWT
+    /*
+    void moveFocus() {
+        // don't use transferFocus(), but query focus traversal policy directly
+        // and if it returns null, transfer focus up cycle
+        // and find next focusable component there
+        KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
+        Container root = kfm.getCurrentFocusCycleRoot();
+        Component nextComp = this;
+        boolean success = !isFocusOwner();
+        while (!success) {
+            if (root != nextComp.getFocusCycleRootAncestor()) {
+                // component was probably removed from container
+                // so focus will be lost in some time
+                return;
+            }
+            nextComp = root.getFocusTraversalPolicy().getComponentAfter(root, nextComp);
+            if (nextComp == this) {
+                nextComp = null; // avoid looping
+            }
+            if (nextComp != null) {
+                success = nextComp.requestFocusInWindow();
+            } else {
+                nextComp = root;
+                root = root.getFocusCycleRootAncestor();
+                // if no acceptable component is found at all - clear global
+                // focus owner
+                if (root == null) {
+                    if (nextComp instanceof Window) {
+                        Window wnd = (Window) nextComp;
+                        wnd.setFocusOwner(null);
+                        wnd.setRequestedFocus(null);
+                    }
+                    kfm.clearGlobalFocusOwner();
+                    return;
+                }
+            }
+        }
+    }
+    */
+
+    /**
+     * For Container there's a difference between moving focus when being made
+     * invisible or made unfocusable in some other way, because when container
+     * is made invisible, component still remains visible, i. e. its hide() or
+     * setVisible() is not called.
+     */
+    void moveFocusOnHide() {
+        //???AWT: moveFocus();
+    }
+
+    /**
+     * Removes the property change listener registered for this component.
+     * 
+     * @param listener the PropertyChangeListener.
+     */
+    public void removePropertyChangeListener(PropertyChangeListener listener) {
+        getPropertyChangeSupport().removePropertyChangeListener(listener);
+    }
+
+    /**
+     * Removes the property change listener registered fot this component 
+     * for the specified propertyy.
+     * 
+     * @param propertyName the property name.
+     * @param listener the PropertyChangeListener.
+     */
+    public void removePropertyChangeListener(String propertyName,
+            PropertyChangeListener listener) {
+        getPropertyChangeSupport().removePropertyChangeListener(propertyName, listener);
+    }
+
+
+    /**
+     * Repaints the specified rectangle of this component within 
+     * tm milliseconds.
+     * 
+     * @param tm the time in milliseconds before updating.
+     * @param x the x coordinate of Rectangle.
+     * @param y the y coordinate of Rectangle.
+     * @param width the width of Rectangle.
+     * @param height the height of Rectangle.
+     */
+    public void repaint(long tm, int x, int y, int width, int height) {
+        //???AWT
+        /*
+        toolkit.lockAWT();
+        try {
+            if (width <= 0 || height <= 0 || (redrawManager == null) || !isShowing()) {
+                return;
+            }
+            if (behaviour instanceof LWBehavior) {
+                if (parent == null || !parent.visible || !parent.behaviour.isDisplayable()) {
+                    return;
+                }
+                if (repaintRegion == null) {
+                    repaintRegion = new MultiRectArea(new Rectangle(x, y, width, height));
+                }
+                repaintRegion.intersect(new Rectangle(0, 0, this.w, this.h));
+                repaintRegion.translate(this.x, this.y);
+                parent.repaintRegion = repaintRegion;
+                repaintRegion = null;
+                parent.repaint(tm, x + this.x, y + this.y, width, height);
+            } else {
+                if (repaintRegion != null) {
+                    redrawManager.addUpdateRegion(this, repaintRegion);
+                    repaintRegion = null;
+                } else {
+                    redrawManager.addUpdateRegion(this, new Rectangle(x, y, width, height));
+                }
+                toolkit.getSystemEventQueueCore().notifyEventMonitor(toolkit);
+            }
+        } finally {
+            toolkit.unlockAWT();
+        }
+        */
+    }
+
+    /**
+     * Post event.
+     * 
+     * @param e the e
+     */
+    void postEvent(AWTEvent e) {
+        getToolkit().getSystemEventQueueImpl().postEvent(e);
+    }
+
+    /**
+     * Repaints the specified Rectangle of this Component.
+     * 
+     * @param x the x coordinate of Rectangle.
+     * @param y the y coordinate of Rectangle.
+     * @param width the width of Rectangle.
+     * @param height the height of Rectangle.
+     */
+    public void repaint(int x, int y, int width, int height) {
+        toolkit.lockAWT();
+        try {
+            repaint(0, x, y, width, height);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Repaints this component.
+     */
+    public void repaint() {
+        toolkit.lockAWT();
+        try {
+            if (w > 0 && h > 0) {
+                repaint(0, 0, 0, w, h);
+            }
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Repaints the component within tm milliseconds.
+     * 
+     * @param tm the time in milliseconds before updating.
+     */
+    public void repaint(long tm) {
+        toolkit.lockAWT();
+        try {
+            repaint(tm, 0, 0, w, h);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Requests that this Component get the input focus temporarily. 
+     * This component must be displayable, visible, and focusable.
+     * 
+     * @param temporary this parameter is true if the focus change 
+     * is temporary, when the window loses the focus.
+     * 
+     * @return true if the focus change request is succeeded,
+     * false otherwise.
+     */
+    protected boolean requestFocus(boolean temporary) {
+        toolkit.lockAWT();
+        try {
+            //???AWT: return requestFocusImpl(temporary, true, false);
+        } finally {
+            toolkit.unlockAWT();
+        }
+        //???AWT
+        return false;
+    }
+
+    /**
+     * Requests that this Component get the input focus. 
+     * This component must be displayable, visible, and focusable.
+     */
+    public void requestFocus() {
+        toolkit.lockAWT();
+        try {
+            requestFocus(false);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    //???AWT
+    /*
+    protected boolean requestFocusInWindow(boolean temporary) {
+        toolkit.lockAWT();
+        try {
+            Window wnd = getWindowAncestor();
+            if ((wnd == null) || !wnd.isFocused()) {
+                return false;
+            }
+            return requestFocusImpl(temporary, false, false);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    boolean requestFocusImpl(boolean temporary, boolean crossWindow, boolean rejectionRecovery) {
+        if (!rejectionRecovery && isFocusOwner()) {
+            return true;
+        }
+        Window wnd = getWindowAncestor();
+        Container par = getRealParent();
+        if ((par != null) && par.isRemoved) {
+            return false;
+        }
+        if (!isShowing() || !isFocusable() || !wnd.isFocusableWindow()) {
+            return false;
+        }
+        return KeyboardFocusManager.getCurrentKeyboardFocusManager().requestFocus(this,
+                temporary, crossWindow, true);
+    }
+
+    public boolean requestFocusInWindow() {
+        toolkit.lockAWT();
+        try {
+            return requestFocusInWindow(false);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+    */
+
+    /**
+     * Deprecated: replaced by setBounds(int, int, int, int) method.
+     * 
+     * @param x the x coordinate.
+     * @param y the y coordinate.
+     * @param w the width. 
+     * @param h the height.
+     * 
+     * @deprecated Replaced by setBounds(int, int, int, int) method.
+     */
+    @Deprecated
+    public void reshape(int x, int y, int w, int h) {
+        toolkit.lockAWT();
+        try {
+            setBounds(x, y, w, h, boundsMaskParam, true);
+            boundsMaskParam = 0;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Sets rectangle for this Component to be the rectangle with the specified 
+     * x,y coordinates of the top-left corner and the width and height.
+     * 
+     * @param x the x coordinate of the rectangle's top-left corner.
+     * @param y the y coordinate of the rectangle's top-left corner.
+     * @param w the width of rectangle.
+     * @param h the height of rectangle. 
+     */
+    public void setBounds(int x, int y, int w, int h) {
+        toolkit.lockAWT();
+        try {
+            reshape(x, y, w, h);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Sets rectangle for this Component to be the rectangle with the specified 
+     * x,y coordinates of the top-left corner and the width and height
+     * and posts the appropriate events.
+     * 
+     * @param x the x coordinate of the rectangle's top-left corner.
+     * @param y the y coordinate of the rectangle's top-left corner.
+     * @param w the width of rectangle.
+     * @param h the height of rectangle. 
+     * @param bMask the bitmask of bounds options
+     * @param updateBehavior the whether to update the behavoir's bounds as well
+     */
+    void setBounds(int x, int y, int w, int h, int bMask, boolean updateBehavior) {
+        int oldX = this.x;
+        int oldY = this.y;
+        int oldW = this.w;
+        int oldH = this.h;
+        setBoundsFields(x, y, w, h, bMask);
+        // Moved
+        if ((oldX != this.x) || (oldY != this.y)) {
+            //???AWT: invalidateRealParent();
+            postEvent(new ComponentEvent(this, ComponentEvent.COMPONENT_MOVED));
+            spreadHierarchyBoundsEvents(this, HierarchyEvent.ANCESTOR_MOVED);
+        }
+        // Resized
+        if ((oldW != this.w) || (oldH != this.h)) {
+            invalidate();
+            postEvent(new ComponentEvent(this, ComponentEvent.COMPONENT_RESIZED));
+            spreadHierarchyBoundsEvents(this, HierarchyEvent.ANCESTOR_RESIZED);
+        }
+        if (updateBehavior) {
+            behaviour.setBounds(this.x, this.y, this.w, this.h, bMask);
+        }
+        notifyInputMethod(new Rectangle(x, y, w, h));
+    }
+
+    /**
+     * Calls InputContextImpl.notifyClientWindowChanged.
+     * 
+     * @param bounds the bounds
+     */
+    void notifyInputMethod(Rectangle bounds) {
+        // only Window actually notifies IM of bounds change
+    }
+
+    /**
+     * Sets the bounds fields.
+     * 
+     * @param x the x
+     * @param y the y
+     * @param w the w
+     * @param h the h
+     * @param bMask the b mask
+     */
+    private void setBoundsFields(int x, int y, int w, int h, int bMask) {
+        if ((bMask & NativeWindow.BOUNDS_NOSIZE) == 0) {
+            this.w = w;
+            this.h = h;
+        }
+        if ((bMask & NativeWindow.BOUNDS_NOMOVE) == 0) {
+            this.x = x;
+            this.y = y;
+        }
+    }
+
+    /**
+     * Gets the native insets.
+     * 
+     * @return the native insets
+     */
+    Insets getNativeInsets() {
+        return new Insets(0, 0, 0, 0);
+    }
+
+    /**
+     * Gets the insets.
+     * 
+     * @return the insets
+     */
+    Insets getInsets() {
+        return new Insets(0, 0, 0, 0);
+    }
+
+    /**
+     * Checks if is mouse exited expected.
+     * 
+     * @return true, if is mouse exited expected
+     */
+    boolean isMouseExitedExpected() {
+        return mouseExitedExpected;
+    }
+
+    /**
+     * Sets the mouse exited expected.
+     * 
+     * @param expected the new mouse exited expected
+     */
+    void setMouseExitedExpected(boolean expected) {
+        mouseExitedExpected = expected;
+    }
+
+    /**
+     * Sets the new bounding rectangle for this Component.
+     * 
+     * @param r the new bounding rectangle.
+     */
+    public void setBounds(Rectangle r) {
+        toolkit.lockAWT();
+        try {
+            setBounds(r.x, r.y, r.width, r.height);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Sets the component orientation which affects the component's
+     * elements and text within this component. 
+     * 
+     * @param o the ComponentOrientation object.
+     */
+    public void setComponentOrientation(ComponentOrientation o) {
+        ComponentOrientation oldOrientation;
+        toolkit.lockAWT();
+        try {
+            oldOrientation = orientation;
+            orientation = o;
+        } finally {
+            toolkit.unlockAWT();
+        }
+        firePropertyChange("componentOrientation", oldOrientation, orientation); //$NON-NLS-1$
+        invalidate();
+    }
+
+    /**
+     * Sets the specified cursor for this Component.
+     * 
+     * @param cursor the new Cursor.
+     */
+    public void setCursor(Cursor cursor) {
+        toolkit.lockAWT();
+        try {
+            this.cursor = cursor;
+            setCursor();
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Set current cursor shape to Component's Cursor.
+     */
+    void setCursor() {
+        if (isDisplayable() && isShowing()) {
+            Rectangle absRect = new Rectangle(getLocationOnScreen(), getSize());
+            Point absPointerPos = toolkit.dispatcher.mouseDispatcher.getPointerPos();
+            //???AWT
+            /*
+            if (absRect.contains(absPointerPos)) {
+                // set Cursor only on top-level Windows(on X11)
+                Window topLevelWnd = getWindowAncestor();
+                if (topLevelWnd != null) {
+                    Point pointerPos = MouseDispatcher.convertPoint(null, absPointerPos,
+                            topLevelWnd);
+                    Component compUnderCursor = topLevelWnd.findComponentAt(pointerPos);
+                    // if (compUnderCursor == this ||
+                    // compUnderCursor.getCursorAncestor() == this) {
+                    NativeWindow wnd = topLevelWnd.getNativeWindow();
+                    if (compUnderCursor != null && wnd != null) {
+                        compUnderCursor.getRealCursor().getNativeCursor()
+                                .setCursor(wnd.getId());
+                    }
+                    // }
+                }
+            }
+            */
+        }
+    }
+
+    /**
+     * Gets the ancestor Cursor if Component is disabled (directly or via an
+     * ancestor) even if Cursor is explicitly set.
+     * 
+     * @param value the value
+     * 
+     * @return actual Cursor to be displayed
+     */
+    //???AWT
+    /*
+    Cursor getRealCursor() {
+        Component cursorAncestor = getCursorAncestor();
+        return cursorAncestor != null ? cursorAncestor.getCursor() : Cursor.getDefaultCursor();
+    }
+    */
+
+    /**
+     * Gets the ancestor(or component itself) whose cursor is set when pointer
+     * is inside component
+     * 
+     * @return actual Cursor to be displayed
+     */
+    //???AWT
+    /*
+    Component getCursorAncestor() {
+        Component comp;
+        for (comp = this; comp != null; comp = comp.getParent()) {
+            if (comp instanceof Window || comp.isCursorSet() && comp.isKeyEnabled()) {
+                return comp;
+            }
+        }
+        return null;
+    }
+
+    public void setDropTarget(DropTarget dt) {
+        toolkit.lockAWT();
+        try {
+            if (dropTarget == dt) {
+                return;
+            }
+            DropTarget oldDropTarget = dropTarget;
+            dropTarget = dt;
+            if (oldDropTarget != null) {
+                if (behaviour.isDisplayable()) {
+                    oldDropTarget.removeNotify(peer);
+                }
+                oldDropTarget.setComponent(null);
+            }
+            if (dt != null) {
+                dt.setComponent(this);
+                if (behaviour.isDisplayable()) {
+                    dt.addNotify(peer);
+                }
+            }
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+    */
+    
+    /**
+     * Sets this component to the "enabled" or "disabled" state depending
+     * on the specified boolean parameter.
+     * 
+     * @param value true if this component should be enabled; false
+     * if this component should be disabled.
+     */
+    public void setEnabled(boolean value) {
+        toolkit.lockAWT();
+        try {
+            enable(value);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Sets the enabled impl.
+     * 
+     * @param value the new enabled impl
+     */
+    void setEnabledImpl(boolean value) {
+        if (enabled != value) {
+            enabled = value;
+            setCursor();
+            if (!enabled) {
+                moveFocusOnHide();
+            }
+            behaviour.setEnabled(value);
+        }
+    }
+
+    //???AWT
+    /*
+    private void fireAccessibleStateChange(AccessibleState state, boolean value) {
+        if (behaviour.isLightweight()) {
+            return;
+        }
+        AccessibleContext ac = getAccessibleContext();
+        if (ac != null) {
+            AccessibleState oldValue = null;
+            AccessibleState newValue = null;
+            if (value) {
+                newValue = state;
+            } else {
+                oldValue = state;
+            }
+            ac.firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY, oldValue,
+                    newValue);
+        }
+    }
+    */
+
+    //???AWT
+    /*
+    public void setFocusTraversalKeys(int id, Set<? extends AWTKeyStroke> keystrokes) {
+        Set<? extends AWTKeyStroke> oldTraversalKeys;
+        String propName = "FocusTraversalKeys"; //$NON-NLS-1$
+        toolkit.lockAWT();
+        try {
+            Integer kId = new Integer(id);
+            KeyboardFocusManager.checkTraversalKeysID(traversalKeys, kId);
+            Map<Integer, Set<? extends AWTKeyStroke>> keys = new HashMap<Integer, Set<? extends AWTKeyStroke>>();
+            for (int kid : traversalIDs) {
+                Integer key = new Integer(kid);
+                keys.put(key, getFocusTraversalKeys(kid));
+            }
+            KeyboardFocusManager.checkKeyStrokes(traversalIDs, keys, kId, keystrokes);
+            oldTraversalKeys = traversalKeys.get(new Integer(id));
+            // put a copy of keystrokes object into map:
+            Set<? extends AWTKeyStroke> newKeys = keystrokes;
+            if (keystrokes != null) {
+                newKeys = new HashSet<AWTKeyStroke>(keystrokes);
+            }
+            traversalKeys.put(kId, newKeys);
+            String direction = ""; //$NON-NLS-1$
+            switch (id) {
+                case KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS:
+                    direction = "forward"; //$NON-NLS-1$
+                    break;
+                case KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS:
+                    direction = "backward"; //$NON-NLS-1$
+                    break;
+                case KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS:
+                    direction = "upCycle"; //$NON-NLS-1$
+                    break;
+                case KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS:
+                    direction = "downCycle"; //$NON-NLS-1$
+                    break;
+            }
+            propName = direction + propName;
+        } finally {
+            toolkit.unlockAWT();
+        }
+        firePropertyChange(propName, oldTraversalKeys, keystrokes);
+    }
+    */
+
+    /**
+     * Sets the focus traversal keys state for this component.
+     * 
+     * @param value true if the focus traversal keys state is enabled,
+     * false if the focus traversal keys state is disabled.
+     */
+    public void setFocusTraversalKeysEnabled(boolean value) {
+        boolean oldFocusTraversalKeysEnabled;
+        toolkit.lockAWT();
+        try {
+            oldFocusTraversalKeysEnabled = focusTraversalKeysEnabled;
+            focusTraversalKeysEnabled = value;
+        } finally {
+            toolkit.unlockAWT();
+        }
+        firePropertyChange("focusTraversalKeysEnabled", oldFocusTraversalKeysEnabled, //$NON-NLS-1$
+                focusTraversalKeysEnabled);
+    }
+
+    //???AWT
+    /*
+    public void setFocusable(boolean focusable) {
+        boolean oldFocusable;
+        toolkit.lockAWT();
+        try {
+            calledSetFocusable = true;
+            oldFocusable = this.focusable;
+            this.focusable = focusable;
+            if (!focusable) {
+                moveFocus();
+            }
+        } finally {
+            toolkit.unlockAWT();
+        }
+        firePropertyChange("focusable", oldFocusable, focusable); //$NON-NLS-1$
+    }
+
+    public Font getFont() {
+        toolkit.lockAWT();
+        try {
+            return (font == null) && (parent != null) ? parent.getFont() : font;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+    */
+
+    /**
+     * Sets the font for this Component.
+     * 
+     * @param f the new font of the Component.
+     */
+    public void setFont(Font f) {
+        Font oldFont;
+        toolkit.lockAWT();
+        try {
+            oldFont = font;
+            setFontImpl(f);
+        } finally {
+            toolkit.unlockAWT();
+        }
+        firePropertyChange("font", oldFont, font); //$NON-NLS-1$
+    }
+
+    /**
+     * Sets the font impl.
+     * 
+     * @param f the new font impl
+     */
+    void setFontImpl(Font f) {
+        font = f;
+        invalidate();
+        if (isShowing()) {
+            repaint();
+        }
+    }
+
+
+    /**
+     * Invalidate the component if it inherits the font from the parent. This
+     * method is overridden in Container.
+     * 
+     * @return true if the component was invalidated, false otherwise
+     */
+    boolean propagateFont() {
+        if (font == null) {
+            invalidate();
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Sets the foreground color for this Component.
+     * 
+     * @param c the new foreground color.
+     */
+    public void setForeground(Color c) {
+        Color oldFgColor;
+        toolkit.lockAWT();
+        try {
+            oldFgColor = foreColor;
+            foreColor = c;
+        } finally {
+            toolkit.unlockAWT();
+        }
+        firePropertyChange("foreground", oldFgColor, foreColor); //$NON-NLS-1$
+        repaint();
+    }
+
+    /**
+     * Sets the background color for the Component.
+     * 
+     * @param c the new background color for this component.
+     */
+    public void setBackground(Color c) {
+        Color oldBkColor;
+        toolkit.lockAWT();
+        try {
+            oldBkColor = backColor;
+            backColor = c;
+        } finally {
+            toolkit.unlockAWT();
+        }
+        firePropertyChange("background", oldBkColor, backColor); //$NON-NLS-1$
+        repaint();
+    }
+
+    /**
+     * Sets the flag for whether paint messages received from the operating 
+     * system should be ignored or not. 
+     * 
+     * @param value true if paint messages received from the operating 
+     * system should be ignored, false otherwise.
+     */
+    public void setIgnoreRepaint(boolean value) {
+        toolkit.lockAWT();
+        try {
+            ignoreRepaint = value;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Sets the locale of the component.
+     * 
+     * @param locale the new Locale.
+     */
+    public void setLocale(Locale locale) {
+        Locale oldLocale;
+        toolkit.lockAWT();
+        try {
+            oldLocale = this.locale;
+            this.locale = locale;
+        } finally {
+            toolkit.unlockAWT();
+        }
+        firePropertyChange("locale", oldLocale, locale); //$NON-NLS-1$
+    }
+
+    /**
+     * Sets the location of the Component to the specified point.
+     * 
+     * @param p the new location of the Component
+     */
+    public void setLocation(Point p) {
+        toolkit.lockAWT();
+        try {
+            setLocation(p.x, p.y);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Sets the location of the Component to the specified x, y coordinates.  
+     * 
+     * @param x the x coordinate.
+     * @param y the y coordinate.
+     */
+    public void setLocation(int x, int y) {
+        toolkit.lockAWT();
+        try {
+            move(x, y);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Sets the visibility state of the component.
+     * 
+     * @param b true if the component is visible, false if the component
+     * is not shown.
+     */
+    public void setVisible(boolean b) {
+        // show() & hide() are not deprecated for Window,
+        // so have to call them from setVisible()
+        show(b);
+    }
+
+    /**
+     * Deprecated: replaced by setVisible(boolean) method.
+     * 
+     * @deprecated Replaced by setVisible(boolean) method.
+     */
+    @Deprecated
+    public void show() {
+        toolkit.lockAWT();
+        try {
+            if (visible) {
+                return;
+            }
+            prepare4HierarchyChange();
+            mapToDisplay(true);
+            validate();
+            visible = true;
+            behaviour.setVisible(true);
+            postEvent(new ComponentEvent(this, ComponentEvent.COMPONENT_SHOWN));
+            //???AWT: finishHierarchyChange(this, parent, 0);
+            notifyInputMethod(new Rectangle(x, y, w, h));
+            //???AWT: invalidateRealParent();
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Deprecated: replaced by setVisible(boolean) method.
+     * 
+     * @param b the visibility's state.
+     * 
+     * @deprecated Replaced by setVisible(boolean) method.
+     */
+    @Deprecated
+    public void show(boolean b) {
+        if (b) {
+            show();
+        } else {
+            hide();
+        }
+    }
+
+    //???AWT
+    /*
+    void transferFocus(int dir) {
+        Container root = null;
+        if (this instanceof Container) {
+            Container cont = (Container) this;
+            if (cont.isFocusCycleRoot()) {
+                root = cont.getFocusTraversalRoot();
+            }
+        }
+        if (root == null) {
+            root = getFocusCycleRootAncestor();
+        }
+        // transfer focus up cycle if root is unreachable
+        Component comp = this;
+        while ((root != null)
+                && !(root.isFocusCycleRoot() && root.isShowing() && root.isEnabled() && root
+                        .isFocusable())) {
+            comp = root;
+            root = root.getFocusCycleRootAncestor();
+        }
+        if (root == null) {
+            return;
+        }
+        FocusTraversalPolicy policy = root.getFocusTraversalPolicy();
+        Component nextComp = null;
+        switch (dir) {
+            case KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS:
+                nextComp = policy.getComponentAfter(root, comp);
+                break;
+            case KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS:
+                nextComp = policy.getComponentBefore(root, comp);
+                break;
+        }
+        if (nextComp != null) {
+            nextComp.requestFocus(false);
+        }
+    }
+    
+    public void transferFocus() {
+        toolkit.lockAWT();
+        try {
+            nextFocus();
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    public void transferFocusBackward() {
+        toolkit.lockAWT();
+        try {
+            transferFocus(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    public void transferFocusUpCycle() {
+        toolkit.lockAWT();
+        try {
+            KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
+            Container root = kfm.getCurrentFocusCycleRoot();
+            
+            if(root == null) {
+                return;
+            }
+            
+            boolean success = false;
+            Component nextComp = null;
+            Container newRoot = root;
+            do {
+                nextComp = newRoot instanceof Window ? newRoot.getFocusTraversalPolicy()
+                        .getDefaultComponent(newRoot) : newRoot;
+                newRoot = newRoot.getFocusCycleRootAncestor();
+                if (nextComp == null) {
+                    break;
+                }
+                success = nextComp.requestFocusInWindow();
+                if (newRoot == null) {
+                    break;
+                }
+                kfm.setGlobalCurrentFocusCycleRoot(newRoot);
+            } while (!success);
+            if (!success && root != newRoot) {
+                kfm.setGlobalCurrentFocusCycleRoot(root);
+            }
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+    */
+
+    /**
+     * Validates that this component has a valid layout.
+     */
+    public void validate() {
+        toolkit.lockAWT();
+        try {
+            if (!behaviour.isDisplayable()) {
+                return;
+            }
+            validateImpl();
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Validate impl.
+     */
+    void validateImpl() {
+        valid = true;
+    }
+
+    /**
+     * Gets the native window.
+     * 
+     * @return the native window
+     */
+    NativeWindow getNativeWindow() {
+        return behaviour.getNativeWindow();
+    }
+
+    /**
+     * Checks whether or not a maximum size is set for the Component.
+     * 
+     * @return true, if the maximum size is set for the Component,
+     * false otherwise.
+     */
+    public boolean isMaximumSizeSet() {
+        toolkit.lockAWT();
+        try {
+            return maximumSize != null;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Checks whether or not the minimum size is set for the component.
+     * 
+     * @return true, if the minimum size is set for the component,
+     * false otherwise.
+     */
+    public boolean isMinimumSizeSet() {
+        toolkit.lockAWT();
+        try {
+            return minimumSize != null;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Checks whether or not the preferred size is set for the Component.
+     * 
+     * @return true, if the preferred size is set for the Component,
+     * false otherwise.
+     */
+    public boolean isPreferredSizeSet() {
+        toolkit.lockAWT();
+        try {
+            return preferredSize != null;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Gets the maximum size of the Component.
+     * 
+     * @return the maximum size of the Component.
+     */
+    public Dimension getMaximumSize() {
+        toolkit.lockAWT();
+        try {
+            return isMaximumSizeSet() ? new Dimension(maximumSize) : new Dimension(
+                    Short.MAX_VALUE, Short.MAX_VALUE);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Gets the minimum size of the Component.
+     * 
+     * @return the minimum size of the Component.
+     */
+    public Dimension getMinimumSize() {
+        toolkit.lockAWT();
+        try {
+            return minimumSize();
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Deprecated: replaced by getMinimumSize() method.
+     * 
+     * @return the Dimension.
+     * 
+     * @deprecated Replaced by getMinimumSize() method.
+     */
+    @Deprecated
+    public Dimension minimumSize() {
+        toolkit.lockAWT();
+        try {
+            if (isMinimumSizeSet()) {
+                return (Dimension)minimumSize.clone();
+            }
+            Dimension defSize = getDefaultMinimumSize();
+            if (defSize != null) {
+                return (Dimension)defSize.clone();
+            }
+            return isDisplayable()? new Dimension(1, 1) : new Dimension(w, h);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Gets the preferred size of the Component.
+     * 
+     * @return the preferred size of the Component.
+     */
+    public Dimension getPreferredSize() {
+        toolkit.lockAWT();
+        try {
+            return preferredSize();
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Deprecated: replaced by getPreferredSize() method.
+     * 
+     * @return the Dimension.
+     * 
+     * @deprecated Replaced by getPreferredSize() method.
+     */
+    @Deprecated
+    public Dimension preferredSize() {
+        toolkit.lockAWT();
+        try {
+            if (isPreferredSizeSet()) {
+                return new Dimension(preferredSize);
+            }
+            Dimension defSize = getDefaultPreferredSize();
+            if (defSize != null) {
+                return new Dimension(defSize);
+            }
+            return new Dimension(getMinimumSize());
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Sets the maximum size of the Component.
+     * 
+     * @param maximumSize the new maximum size of the Component.
+     */
+    public void setMaximumSize(Dimension maximumSize) {
+        Dimension oldMaximumSize;
+        toolkit.lockAWT();
+        try {
+            oldMaximumSize = this.maximumSize;
+            if (oldMaximumSize != null) {
+                oldMaximumSize = oldMaximumSize.getSize();
+            }
+            if (this.maximumSize == null) {
+                if (maximumSize != null) {
+                    this.maximumSize = new Dimension(maximumSize);
+                }
+            } else {
+                if (maximumSize != null) {
+                    this.maximumSize.setSize(maximumSize);
+                } else {
+                    this.maximumSize = null;
+                }
+            }
+        } finally {
+            toolkit.unlockAWT();
+        }
+        firePropertyChange("maximumSize", oldMaximumSize, this.maximumSize); //$NON-NLS-1$
+        toolkit.lockAWT();
+        try {
+            //???AWT: invalidateRealParent();
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Sets the minimum size of the Component.
+     * 
+     * @param minimumSize the new minimum size of the Component.
+     */
+    public void setMinimumSize(Dimension minimumSize) {
+        Dimension oldMinimumSize;
+        toolkit.lockAWT();
+        try {
+            oldMinimumSize = this.minimumSize;
+            if (oldMinimumSize != null) {
+                oldMinimumSize = oldMinimumSize.getSize();
+            }
+            if (this.minimumSize == null) {
+                if (minimumSize != null) {
+                    this.minimumSize = new Dimension(minimumSize);
+                }
+            } else {
+                if (minimumSize != null) {
+                    this.minimumSize.setSize(minimumSize);
+                } else {
+                    this.minimumSize = null;
+                }
+            }
+        } finally {
+            toolkit.unlockAWT();
+        }
+        firePropertyChange("minimumSize", oldMinimumSize, this.minimumSize); //$NON-NLS-1$
+        toolkit.lockAWT();
+        try {
+            //???AWT: invalidateRealParent();
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Sets the preferred size of the Component.
+     * 
+     * @param preferredSize the new preferred size of the Component.
+     */
+    public void setPreferredSize(Dimension preferredSize) {
+        Dimension oldPreferredSize;
+        toolkit.lockAWT();
+        try {
+            oldPreferredSize = this.preferredSize;
+            if (oldPreferredSize != null) {
+                oldPreferredSize = oldPreferredSize.getSize();
+            }
+            if (this.preferredSize == null) {
+                if (preferredSize != null) {
+                    this.preferredSize = new Dimension(preferredSize);
+                }
+            } else {
+                if (preferredSize != null) {
+                    this.preferredSize.setSize(preferredSize);
+                } else {
+                    this.preferredSize = null;
+                }
+            }
+        } finally {
+            toolkit.unlockAWT();
+        }
+        firePropertyChange("preferredSize", oldPreferredSize, this.preferredSize); //$NON-NLS-1$
+        toolkit.lockAWT();
+        try {
+            //???AWT: invalidateRealParent();
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    //???AWT
+    /*
+    RedrawManager getRedrawManager() {
+        if (parent == null) {
+            return null;
+        }
+        return parent.getRedrawManager();
+    }
+    */
+
+    /**
+     * Checks if is focusability explicitly set.
+     * 
+     * @return true if component has a focusable peer
+     */
+    //???AWT
+    /*
+    boolean isPeerFocusable() {
+        // The recommendations for Windows and Unix are that
+        // Canvases, Labels, Panels, Scrollbars, ScrollPanes, Windows,
+        // and lightweight Components have non-focusable peers,
+        // and all other Components have focusable peers.
+        if (this instanceof Canvas || this instanceof Label || this instanceof Panel
+                || this instanceof Scrollbar || this instanceof ScrollPane
+                || this instanceof Window || isLightweight()) {
+            return false;
+        }
+        return true;
+    }
+    */
+
+    /**
+     * @return true if focusability was explicitly set via a call to
+     *         setFocusable() or via overriding isFocusable() or
+     *         isFocusTraversable()
+     */
+    boolean isFocusabilityExplicitlySet() {
+        return calledSetFocusable || overridenIsFocusable;
+    }
+
+    /**
+     * Paints the component and all of its subcomponents.
+     * 
+     * @param g the Graphics to be used for painting.
+     */
+    public void paintAll(Graphics g) {
+        toolkit.lockAWT();
+        try {
+            paint(g);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Updates this Component.
+     * 
+     * @param g the Graphics to be used for updating.
+     */
+    public void update(Graphics g) {
+        toolkit.lockAWT();
+        try {
+            if (!isLightweight() && !isPrepainter()) {
+                g.setColor(getBackground());
+                g.fillRect(0, 0, w, h);
+                g.setColor(getForeground());
+            }
+            paint(g);
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Paints this component.
+     * 
+     * @param g the Graphics to be used for painting.
+     */
+    public void paint(Graphics g) {
+        toolkit.lockAWT();
+        try {
+            // Just to nothing
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Prepares the component to be painted.
+     * 
+     * @param g the Graphics to be used for painting.
+     */
+    void prepaint(Graphics g) {
+        // Just to nothing. For overriding.
+    }
+
+    /**
+     * Checks if is prepainter.
+     * 
+     * @return true, if is prepainter
+     */
+    boolean isPrepainter() {
+        return false;
+    }
+
+    /**
+     * Prepare4 hierarchy change.
+     */
+    void prepare4HierarchyChange() {
+        if (hierarchyChangingCounter++ == 0) {
+            wasShowing = isShowing();
+            wasDisplayable = isDisplayable();
+            prepareChildren4HierarchyChange();
+        }
+    }
+
+    /**
+     * Prepare children4 hierarchy change.
+     */
+    void prepareChildren4HierarchyChange() {
+        // To be inherited by Container
+    }
+
+    //???AWT
+    /*
+    void finishHierarchyChange(Component changed, Container changedParent, int ancestorFlags) {
+        if (--hierarchyChangingCounter == 0) {
+            int changeFlags = ancestorFlags;
+            if (wasShowing != isShowing()) {
+                changeFlags |= HierarchyEvent.SHOWING_CHANGED;
+            }
+            if (wasDisplayable != isDisplayable()) {
+                changeFlags |= HierarchyEvent.DISPLAYABILITY_CHANGED;
+            }
+            if (changeFlags > 0) {
+                postEvent(new HierarchyEvent(this, HierarchyEvent.HIERARCHY_CHANGED, changed,
+                        changedParent, changeFlags));
+            }
+            finishChildrenHierarchyChange(changed, changedParent, ancestorFlags);
+        }
+    }
+
+
+    void finishChildrenHierarchyChange(Component changed, Container changedParent,
+            int ancestorFlags) {
+        // To be inherited by Container
+    }
+
+    void postHierarchyBoundsEvents(Component changed, int id) {
+        postEvent(new HierarchyEvent(this, id, changed, null, 0));
+    }
+    */
+    
+    /**
+     * Spread hierarchy bounds events.
+     * 
+     * @param changed the changed
+     * @param id the id
+     */
+    void spreadHierarchyBoundsEvents(Component changed, int id) {
+        // To be inherited by Container
+    }
+
+    /**
+     * Dispatches an event to this component.
+     * 
+     * @param e the Event.
+     */
+    public final void dispatchEvent(AWTEvent e) {
+        //???AWT
+        /*
+        if (e.isConsumed()) {
+            return;
+        }
+        if (e instanceof PaintEvent) {
+            toolkit.dispatchAWTEvent(e);
+            processPaintEvent((PaintEvent) e);
+            return;
+        }
+        KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
+        if (!e.dispatchedByKFM && kfm.dispatchEvent(e)) {
+            return;
+        }
+        if (e instanceof KeyEvent) {
+            KeyEvent ke = (KeyEvent) e;
+            // consumes KeyEvent which represents a focus traversal key
+            if (getFocusTraversalKeysEnabled()) {
+                kfm.processKeyEvent(this, ke);
+                if (ke.isConsumed()) {
+                    return;
+                }
+            }
+        }
+        if (inputMethodsEnabled && dispatchToIM && e.isPosted && dispatchEventToIM(e)) {
+            return;
+        }
+        if (e.getID() == WindowEvent.WINDOW_ICONIFIED) {
+            notifyInputMethod(null);
+        }
+        AWTEvent.EventDescriptor descriptor = toolkit.eventTypeLookup.getEventDescriptor(e);
+        toolkit.dispatchAWTEvent(e);
+        if (descriptor != null) {
+            if (isEventEnabled(descriptor.eventMask)
+                    || (getListeners(descriptor.listenerType).length > 0)) {
+                processEvent(e);
+            }
+            // input events can be consumed by user listeners:
+            if (!e.isConsumed() && ((enabledAWTEvents & descriptor.eventMask) != 0)) {
+                postprocessEvent(e, descriptor.eventMask);
+            }
+        }
+        postDeprecatedEvent(e);
+        */
+    }
+
+    /**
+     * Post deprecated event.
+     * 
+     * @param e the e
+     */
+    private void postDeprecatedEvent(AWTEvent e) {
+        if (deprecatedEventHandler) {
+            Event evt = e.getEvent();
+            if (evt != null) {
+                postEvent(evt);
+            }
+        }
+    }
+
+    /**
+     * Postprocess event.
+     * 
+     * @param e the e
+     * @param eventMask the event mask
+     */
+    void postprocessEvent(AWTEvent e, long eventMask) {
+        toolkit.lockAWT();
+        try {
+            // call system listeners under AWT lock
+            if (eventMask == AWTEvent.FOCUS_EVENT_MASK) {
+                preprocessFocusEvent((FocusEvent) e);
+            } else if (eventMask == AWTEvent.KEY_EVENT_MASK) {
+                preprocessKeyEvent((KeyEvent) e);
+            } else if (eventMask == AWTEvent.MOUSE_EVENT_MASK) {
+                preprocessMouseEvent((MouseEvent) e);
+            } else if (eventMask == AWTEvent.MOUSE_MOTION_EVENT_MASK) {
+                preprocessMouseMotionEvent((MouseEvent) e);
+            } else if (eventMask == AWTEvent.COMPONENT_EVENT_MASK) {
+                preprocessComponentEvent((ComponentEvent) e);
+            } else if (eventMask == AWTEvent.MOUSE_WHEEL_EVENT_MASK) {
+                preprocessMouseWheelEvent((MouseWheelEvent) e);
+            } else if (eventMask == AWTEvent.INPUT_METHOD_EVENT_MASK) {
+                preprocessInputMethodEvent((InputMethodEvent) e);
+            }
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Preprocess input method event.
+     * 
+     * @param e the e
+     */
+    private void preprocessInputMethodEvent(InputMethodEvent e) {
+        processInputMethodEventImpl(e, inputMethodListeners.getSystemListeners());
+    }
+
+    /**
+     * Preprocess mouse wheel event.
+     * 
+     * @param e the e
+     */
+    private void preprocessMouseWheelEvent(MouseWheelEvent e) {
+        processMouseWheelEventImpl(e, mouseWheelListeners.getSystemListeners());
+    }
+
+    /**
+     * Process mouse wheel event impl.
+     * 
+     * @param e the e
+     * @param c the c
+     */
+    private void processMouseWheelEventImpl(MouseWheelEvent e, Collection<MouseWheelListener> c) {
+        for (MouseWheelListener listener : c) {
+            switch (e.getID()) {
+                case MouseEvent.MOUSE_WHEEL:
+                    listener.mouseWheelMoved(e);
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Preprocess component event.
+     * 
+     * @param e the e
+     */
+    private void preprocessComponentEvent(ComponentEvent e) {
+        processComponentEventImpl(e, componentListeners.getSystemListeners());
+    }
+
+    /**
+     * Preprocess mouse motion event.
+     * 
+     * @param e the e
+     */
+    void preprocessMouseMotionEvent(MouseEvent e) {
+        processMouseMotionEventImpl(e, mouseMotionListeners.getSystemListeners());
+    }
+
+    /**
+     * Preprocess mouse event.
+     * 
+     * @param e the e
+     */
+    void preprocessMouseEvent(MouseEvent e) {
+        processMouseEventImpl(e, mouseListeners.getSystemListeners());
+    }
+
+    /**
+     * Preprocess key event.
+     * 
+     * @param e the e
+     */
+    void preprocessKeyEvent(KeyEvent e) {
+        processKeyEventImpl(e, keyListeners.getSystemListeners());
+    }
+
+    /**
+     * Preprocess focus event.
+     * 
+     * @param e the e
+     */
+    void preprocessFocusEvent(FocusEvent e) {
+        processFocusEventImpl(e, focusListeners.getSystemListeners());
+    }
+
+    /**
+     * Processes AWTEvent occurred on this component. 
+     * 
+     * @param e the AWTEvent.
+     */
+    protected void processEvent(AWTEvent e) {
+        long eventMask = toolkit.eventTypeLookup.getEventMask(e);
+        if (eventMask == AWTEvent.COMPONENT_EVENT_MASK) {
+            processComponentEvent((ComponentEvent) e);
+        } else if (eventMask == AWTEvent.FOCUS_EVENT_MASK) {
+            processFocusEvent((FocusEvent) e);
+        } else if (eventMask == AWTEvent.KEY_EVENT_MASK) {
+            processKeyEvent((KeyEvent) e);
+        } else if (eventMask == AWTEvent.MOUSE_EVENT_MASK) {
+            processMouseEvent((MouseEvent) e);
+        } else if (eventMask == AWTEvent.MOUSE_WHEEL_EVENT_MASK) {
+            processMouseWheelEvent((MouseWheelEvent) e);
+        } else if (eventMask == AWTEvent.MOUSE_MOTION_EVENT_MASK) {
+            processMouseMotionEvent((MouseEvent) e);
+        } else if (eventMask == AWTEvent.HIERARCHY_EVENT_MASK) {
+            processHierarchyEvent((HierarchyEvent) e);
+        } else if (eventMask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) {
+            processHierarchyBoundsEvent((HierarchyEvent) e);
+        } else if (eventMask == AWTEvent.INPUT_METHOD_EVENT_MASK) {
+            processInputMethodEvent((InputMethodEvent) e);
+        }
+    }
+
+    /**
+     * Gets an array of all listener's objects based on the specified
+     * listener type and registered to this Component.
+     * 
+     * @param listenerType the listener type.
+     * 
+     * @return an array of all listener's objects based on the specified
+     * listener type and registered to this Component. 
+     */
+    @SuppressWarnings("unchecked")
+    public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
+        if (ComponentListener.class.isAssignableFrom(listenerType)) {
+            return (T[]) getComponentListeners();
+        } else if (FocusListener.class.isAssignableFrom(listenerType)) {
+            return (T[]) getFocusListeners();
+        } else if (HierarchyBoundsListener.class.isAssignableFrom(listenerType)) {
+            return (T[]) getHierarchyBoundsListeners();
+        } else if (HierarchyListener.class.isAssignableFrom(listenerType)) {
+            return (T[]) getHierarchyListeners();
+        } else if (InputMethodListener.class.isAssignableFrom(listenerType)) {
+            return (T[]) getInputMethodListeners();
+        } else if (KeyListener.class.isAssignableFrom(listenerType)) {
+            return (T[]) getKeyListeners();
+        } else if (MouseWheelListener.class.isAssignableFrom(listenerType)) {
+            return (T[]) getMouseWheelListeners();
+        } else if (MouseMotionListener.class.isAssignableFrom(listenerType)) {
+            return (T[]) getMouseMotionListeners();
+        } else if (MouseListener.class.isAssignableFrom(listenerType)) {
+            return (T[]) getMouseListeners();
+        } else if (PropertyChangeListener.class.isAssignableFrom(listenerType)) {
+            return (T[]) getPropertyChangeListeners();
+        }
+        return (T[]) Array.newInstance(listenerType, 0);
+    }
+
+    /**
+     * Process paint event.
+     * 
+     * @param event the event
+     */
+    private void processPaintEvent(PaintEvent event) {
+        if (redrawManager == null) {
+            return;
+        }
+        Rectangle clipRect = event.getUpdateRect();
+        if ((clipRect.width <= 0) || (clipRect.height <= 0)) {
+            return;
+        }
+        Graphics g = getGraphics();
+        if (g == null) {
+            return;
+        }
+        initGraphics(g, event);
+        if (!getIgnoreRepaint()) {
+            if (event.getID() == PaintEvent.PAINT) {
+                paint(g);
+            } else {
+                update(g);
+            }
+        }
+        g.dispose();
+    }
+
+    /**
+     * Inits the graphics.
+     * 
+     * @param g the g
+     * @param e the e
+     */
+    void initGraphics(Graphics g, PaintEvent e) {
+        Rectangle clip = e.getUpdateRect();
+        if (clip instanceof ClipRegion) {
+            g.setClip(((ClipRegion) clip).getClip());
+        } else {
+            g.setClip(clip);
+        }
+        if (isPrepainter()) {
+            prepaint(g);
+        } else if (!isLightweight() && (e.getID() == PaintEvent.PAINT)) {
+            g.setColor(getBackground());
+            g.fillRect(0, 0, w, h);
+        }
+        g.setFont(getFont());
+        g.setColor(getForeground());
+    }
+
+    /**
+     * Enables the events with the specified event mask to be delivered to 
+     * this component.
+     * 
+     * @param eventsToEnable the events mask which specifies the types 
+     * of events to enable.
+     */
+    protected final void enableEvents(long eventsToEnable) {
+        toolkit.lockAWT();
+        try {
+            enabledEvents |= eventsToEnable;
+            deprecatedEventHandler = false;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Enable awt events.
+     * 
+     * @param eventsToEnable the events to enable
+     */
+    private void enableAWTEvents(long eventsToEnable) {
+        enabledAWTEvents |= eventsToEnable;
+    }
+
+    /**
+     * Disables the events with types specified by the specified event mask 
+     * from being delivered to this component.
+     * 
+     * @param eventsToDisable the event mask specifying the event types. 
+     */
+    protected final void disableEvents(long eventsToDisable) {
+        toolkit.lockAWT();
+        try {
+            enabledEvents &= ~eventsToDisable;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /*
+     * For use in MouseDispatcher only. Really it checks not only mouse events.
+     */
+    /**
+     * Checks if is mouse event enabled.
+     * 
+     * @param eventMask the event mask
+     * 
+     * @return true, if is mouse event enabled
+     */
+    boolean isMouseEventEnabled(long eventMask) {
+        return (isEventEnabled(eventMask) || (enabledAWTEvents & eventMask) != 0);
+    }
+
+    /**
+     * Checks if is event enabled.
+     * 
+     * @param eventMask the event mask
+     * 
+     * @return true, if is event enabled
+     */
+    boolean isEventEnabled(long eventMask) {
+        return ((enabledEvents & eventMask) != 0);
+    }
+
+    /**
+     * Enables or disables input method support for this component. 
+     * 
+     * @param enable true to enable input method support, false to disable it. 
+     */
+    public void enableInputMethods(boolean enable) {
+        toolkit.lockAWT();
+        try {
+            if (!enable) {
+                removeNotifyInputContext();
+            }
+            inputMethodsEnabled = enable;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Gets an array of all component's listeners registered for this
+     * component.
+     * 
+     * @return an array of all component's listeners registered for this
+     * component.
+     */
+    public ComponentListener[] getComponentListeners() {
+        return componentListeners.getUserListeners(new ComponentListener[0]);
+    }
+
+    /**
+     * Adds the specified component listener to the Component for receiving
+     * component's event.
+     * 
+     * @param l the ComponentListener.
+     */
+    public void addComponentListener(ComponentListener l) {
+        componentListeners.addUserListener(l);
+    }
+
+    /**
+     * Removes the component listener registered for this Component.
+     * 
+     * @param l the ComponentListener.
+     */
+    public void removeComponentListener(ComponentListener l) {
+        componentListeners.removeUserListener(l);
+    }
+
+    /**
+     * Processes a component event that has occurred on this component 
+     * by dispatching them to any registered ComponentListener objects.
+     * 
+     * @param e the ComponentEvent.
+     */
+    protected void processComponentEvent(ComponentEvent e) {
+        processComponentEventImpl(e, componentListeners.getUserListeners());
+    }
+
+    /**
+     * Process component event impl.
+     * 
+     * @param e the e
+     * @param c the c
+     */
+    private void processComponentEventImpl(ComponentEvent e, Collection<ComponentListener> c) {
+        for (ComponentListener listener : c) {
+            switch (e.getID()) {
+                case ComponentEvent.COMPONENT_HIDDEN:
+                    listener.componentHidden(e);
+                    break;
+                case ComponentEvent.COMPONENT_MOVED:
+                    listener.componentMoved(e);
+                    break;
+                case ComponentEvent.COMPONENT_RESIZED:
+                    listener.componentResized(e);
+                    break;
+                case ComponentEvent.COMPONENT_SHOWN:
+                    listener.componentShown(e);
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Gets an array of focus listeners registered for this Component.
+     * 
+     * @return the array of focus listeners registered for this Component.
+     */
+    public FocusListener[] getFocusListeners() {
+        return focusListeners.getUserListeners(new FocusListener[0]);
+    }
+
+    /**
+     * Adds the specified focus listener to the Component for receiving
+     * focus events.
+     * 
+     * @param l the FocusListener.
+     */
+    public void addFocusListener(FocusListener l) {
+        focusListeners.addUserListener(l);
+    }
+
+    /**
+     * Adds the awt focus listener.
+     * 
+     * @param l the l
+     */
+    void addAWTFocusListener(FocusListener l) {
+        enableAWTEvents(AWTEvent.FOCUS_EVENT_MASK);
+        focusListeners.addSystemListener(l);
+    }
+
+    /**
+     * Removes the focus listener registered for this Component.
+     * 
+     * @param l the FocusListener.
+     */
+    public void removeFocusListener(FocusListener l) {
+        focusListeners.removeUserListener(l);
+    }
+
+    /**
+     * Processes a FocusEvent that has occurred on this component
+     * by dispatching it to the registered listeners.
+     *  
+     * @param e the FocusEvent.
+     */
+    protected void processFocusEvent(FocusEvent e) {
+        processFocusEventImpl(e, focusListeners.getUserListeners());
+    }
+
+    /**
+     * Process focus event impl.
+     * 
+     * @param e the e
+     * @param c the c
+     */
+    private void processFocusEventImpl(FocusEvent e, Collection<FocusListener> c) {
+        for (FocusListener listener : c) {
+            switch (e.getID()) {
+                case FocusEvent.FOCUS_GAINED:
+                    listener.focusGained(e);
+                    break;
+                case FocusEvent.FOCUS_LOST:
+                    listener.focusLost(e);
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Gets an array of registered HierarchyListeners for
+     * this Component.
+     * 
+     * @return an array of registered HierarchyListeners for
+     * this Component.
+     */
+    public HierarchyListener[] getHierarchyListeners() {
+        return hierarchyListeners.getUserListeners(new HierarchyListener[0]);
+    }
+
+    /**
+     * Adds the specified hierarchy listener.
+     * 
+     * @param l the HierarchyListener.
+     */
+    public void addHierarchyListener(HierarchyListener l) {
+        hierarchyListeners.addUserListener(l);
+    }
+
+    /**
+     * Removes the hierarchy listener registered for this component.
+     * 
+     * @param l the HierarchyListener.
+     */
+    public void removeHierarchyListener(HierarchyListener l) {
+        hierarchyListeners.removeUserListener(l);
+    }
+
+    /**
+     * Processes a hierarchy event that has occurred on this component
+     * by dispatching it to the registered listeners. 
+     * 
+     * @param e the HierarchyEvent.
+     */
+    protected void processHierarchyEvent(HierarchyEvent e) {
+        for (HierarchyListener listener : hierarchyListeners.getUserListeners()) {
+            switch (e.getID()) {
+                case HierarchyEvent.HIERARCHY_CHANGED:
+                    listener.hierarchyChanged(e);
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Gets an array of HierarchyBoundsListener objects registered
+     * to this Component.
+     * 
+     * @return an array of HierarchyBoundsListener objects.
+     */
+    public HierarchyBoundsListener[] getHierarchyBoundsListeners() {
+        return hierarchyBoundsListeners.getUserListeners(new HierarchyBoundsListener[0]);
+    }
+
+    /**
+     * Adds the specified hierarchy bounds listener.
+     * 
+     * @param l the HierarchyBoundsListener.
+     */
+    public void addHierarchyBoundsListener(HierarchyBoundsListener l) {
+        hierarchyBoundsListeners.addUserListener(l);
+    }
+
+    /**
+     * Removes the hierarchy bounds listener registered for this Component.
+     * 
+     * @param l the HierarchyBoundsListener.
+     */
+    public void removeHierarchyBoundsListener(HierarchyBoundsListener l) {
+        hierarchyBoundsListeners.removeUserListener(l);
+    }
+
+    /**
+     * Processes a hierarchy bounds event that has occurred on this component
+     * by dispatching it to the registered listeners.
+     *  
+     * @param e the HierarchyBoundsEvent.
+     */
+    protected void processHierarchyBoundsEvent(HierarchyEvent e) {
+        for (HierarchyBoundsListener listener : hierarchyBoundsListeners.getUserListeners()) {
+            switch (e.getID()) {
+                case HierarchyEvent.ANCESTOR_MOVED:
+                    listener.ancestorMoved(e);
+                    break;
+                case HierarchyEvent.ANCESTOR_RESIZED:
+                    listener.ancestorResized(e);
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Gets an array of the key listeners registered to the Component.
+     * 
+     * @return an array of the key listeners registered to the Component.
+     */
+    public KeyListener[] getKeyListeners() {
+        return keyListeners.getUserListeners(new KeyListener[0]);
+    }
+
+    /**
+     * Adds the specified key listener.
+     * 
+     * @param l the KeyListener.
+     */
+    public void addKeyListener(KeyListener l) {
+        keyListeners.addUserListener(l);
+    }
+
+    /**
+     * Adds the awt key listener.
+     * 
+     * @param l the l
+     */
+    void addAWTKeyListener(KeyListener l) {
+        enableAWTEvents(AWTEvent.KEY_EVENT_MASK);
+        keyListeners.addSystemListener(l);
+    }
+
+    /**
+     * Removes the key listener registered for this Component.
+     * 
+     * @param l the KeyListener.
+     */
+    public void removeKeyListener(KeyListener l) {
+        keyListeners.removeUserListener(l);
+    }
+
+    /**
+     * Processes a key event that has occurred on this component
+     * by dispatching it to the registered listeners.
+     * 
+     * @param e the KeyEvent.
+     */
+    protected void processKeyEvent(KeyEvent e) {
+        processKeyEventImpl(e, keyListeners.getUserListeners());
+    }
+
+    /**
+     * Process key event impl.
+     * 
+     * @param e the e
+     * @param c the c
+     */
+    private void processKeyEventImpl(KeyEvent e, Collection<KeyListener> c) {
+        for (KeyListener listener : c) {
+            switch (e.getID()) {
+                case KeyEvent.KEY_PRESSED:
+                    listener.keyPressed(e);
+                    break;
+                case KeyEvent.KEY_RELEASED:
+                    listener.keyReleased(e);
+                    break;
+                case KeyEvent.KEY_TYPED:
+                    listener.keyTyped(e);
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Gets an array of the mouse listeners registered to the Component.
+     * 
+     * @return an array of the mouse listeners registered to the Component.
+     */
+    public MouseListener[] getMouseListeners() {
+        return mouseListeners.getUserListeners(new MouseListener[0]);
+    }
+
+    /**
+     * Adds the specified mouse listener.
+     * 
+     * @param l the MouseListener.
+     */
+    public void addMouseListener(MouseListener l) {
+        mouseListeners.addUserListener(l);
+    }
+
+    /**
+     * Adds the awt mouse listener.
+     * 
+     * @param l the l
+     */
+    void addAWTMouseListener(MouseListener l) {
+        enableAWTEvents(AWTEvent.MOUSE_EVENT_MASK);
+        mouseListeners.addSystemListener(l);
+    }
+
+    /**
+     * Adds the awt mouse motion listener.
+     * 
+     * @param l the l
+     */
+    void addAWTMouseMotionListener(MouseMotionListener l) {
+        enableAWTEvents(AWTEvent.MOUSE_MOTION_EVENT_MASK);
+        mouseMotionListeners.addSystemListener(l);
+    }
+
+    /**
+     * Adds the awt component listener.
+     * 
+     * @param l the l
+     */
+    void addAWTComponentListener(ComponentListener l) {
+        enableAWTEvents(AWTEvent.COMPONENT_EVENT_MASK);
+        componentListeners.addSystemListener(l);
+    }
+
+    /**
+     * Adds the awt input method listener.
+     * 
+     * @param l the l
+     */
+    void addAWTInputMethodListener(InputMethodListener l) {
+        enableAWTEvents(AWTEvent.INPUT_METHOD_EVENT_MASK);
+        inputMethodListeners.addSystemListener(l);
+    }
+
+    /**
+     * Adds the awt mouse wheel listener.
+     * 
+     * @param l the l
+     */
+    void addAWTMouseWheelListener(MouseWheelListener l) {
+        enableAWTEvents(AWTEvent.MOUSE_WHEEL_EVENT_MASK);
+        mouseWheelListeners.addSystemListener(l);
+    }
+
+    /**
+     * Removes the mouse listener registered for this Component.
+     * 
+     * @param l the MouseListener.
+     */
+    public void removeMouseListener(MouseListener l) {
+        mouseListeners.removeUserListener(l);
+    }
+
+    /**
+     * Processes a mouse event that has occurred on this component
+     * by dispatching it to the registered listeners.
+     * 
+     * @param e the MouseEvent.
+     */
+    protected void processMouseEvent(MouseEvent e) {
+        processMouseEventImpl(e, mouseListeners.getUserListeners());
+    }
+
+    /**
+     * Process mouse event impl.
+     * 
+     * @param e the e
+     * @param c the c
+     */
+    private void processMouseEventImpl(MouseEvent e, Collection<MouseListener> c) {
+        for (MouseListener listener : c) {
+            switch (e.getID()) {
+                case MouseEvent.MOUSE_CLICKED:
+                    listener.mouseClicked(e);
+                    break;
+                case MouseEvent.MOUSE_ENTERED:
+                    listener.mouseEntered(e);
+                    break;
+                case MouseEvent.MOUSE_EXITED:
+                    listener.mouseExited(e);
+                    break;
+                case MouseEvent.MOUSE_PRESSED:
+                    listener.mousePressed(e);
+                    break;
+                case MouseEvent.MOUSE_RELEASED:
+                    listener.mouseReleased(e);
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Process mouse motion event impl.
+     * 
+     * @param e the e
+     * @param c the c
+     */
+    private void processMouseMotionEventImpl(MouseEvent e, Collection<MouseMotionListener> c) {
+        for (MouseMotionListener listener : c) {
+            switch (e.getID()) {
+                case MouseEvent.MOUSE_DRAGGED:
+                    listener.mouseDragged(e);
+                    break;
+                case MouseEvent.MOUSE_MOVED:
+                    listener.mouseMoved(e);
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Gets an array of the mouse motion listeners registered to
+     * the Component.
+     * 
+     * @return an array of the MouseMotionListeners registered to
+     * the Component.
+     */
+    public MouseMotionListener[] getMouseMotionListeners() {
+        return mouseMotionListeners.getUserListeners(new MouseMotionListener[0]);
+    }
+
+    /**
+     * Adds the specified mouse motion listener.
+     * 
+     * @param l the MouseMotionListener.
+     */
+    public void addMouseMotionListener(MouseMotionListener l) {
+        mouseMotionListeners.addUserListener(l);
+    }
+
+    /**
+     * Removes the mouse motion listener registered for this component.
+     * 
+     * @param l the MouseMotionListener.
+     */
+    public void removeMouseMotionListener(MouseMotionListener l) {
+        mouseMotionListeners.removeUserListener(l);
+    }
+
+    /**
+     * Processes a mouse motion event that has occurred on this component
+     * by dispatching it to the registered listeners.
+     * 
+     * @param e the MouseEvent.
+     */
+    protected void processMouseMotionEvent(MouseEvent e) {
+        processMouseMotionEventImpl(e, mouseMotionListeners.getUserListeners());
+    }
+
+    /**
+     * Gets an array of the mouse wheel listeners registered to
+     * the Component.
+     * 
+     * @return an array of the MouseWheelListeners registered to
+     * the Component.
+     */
+    public MouseWheelListener[] getMouseWheelListeners() {
+        return mouseWheelListeners.getUserListeners(new MouseWheelListener[0]);
+    }
+
+    /**
+     * Adds the specified mouse wheel listener.
+     * 
+     * @param l the MouseWheelListener.
+     */
+    public void addMouseWheelListener(MouseWheelListener l) {
+        mouseWheelListeners.addUserListener(l);
+    }
+
+    /**
+     * Removes the mouse wheel listener registered for this component.
+     * 
+     * @param l the MouseWheelListener.
+     */
+    public void removeMouseWheelListener(MouseWheelListener l) {
+        mouseWheelListeners.removeUserListener(l);
+    }
+
+    /**
+     * Processes a mouse wheel event that has occurred on this component
+     * by dispatching it to the registered listeners.
+     * 
+     * @param e the MouseWheelEvent.
+     */
+    protected void processMouseWheelEvent(MouseWheelEvent e) {
+        processMouseWheelEventImpl(e, mouseWheelListeners.getUserListeners());
+    }
+
+    /**
+     * Gets an array of the InputMethodListener listeners 
+     * registered to the Component.
+     * 
+     * @return an array of the InputMethodListener listeners 
+     * registered to the Component.
+     */
+    public InputMethodListener[] getInputMethodListeners() {
+        return inputMethodListeners.getUserListeners(new InputMethodListener[0]);
+    }
+
+    /**
+     * Adds the specified input method listener.
+     * 
+     * @param l the InputMethodListener.
+     */
+    public void addInputMethodListener(InputMethodListener l) {
+        inputMethodListeners.addUserListener(l);
+    }
+
+    /**
+     * Removes the input method listener registered for this component.
+     * 
+     * @param l the InputMethodListener.
+     */
+    public void removeInputMethodListener(InputMethodListener l) {
+        inputMethodListeners.removeUserListener(l);
+    }
+
+    /**
+     * Processes an input method event that has occurred on this component
+     * by dispatching it to the registered listeners.
+     * 
+     * @param e the InputMethodEvent.
+     */
+    protected void processInputMethodEvent(InputMethodEvent e) {
+        processInputMethodEventImpl(e, inputMethodListeners.getUserListeners());
+    }
+
+    /**
+     * Process input method event impl.
+     * 
+     * @param e the e
+     * @param c the c
+     */
+    private void processInputMethodEventImpl(InputMethodEvent e,
+            Collection<InputMethodListener> c) {
+        for (InputMethodListener listener : c) {
+            switch (e.getID()) {
+                case InputMethodEvent.CARET_POSITION_CHANGED:
+                    listener.caretPositionChanged(e);
+                    break;
+                case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED:
+                    listener.inputMethodTextChanged(e);
+                    break;
+            }
+        }
+    }
+
+    //???AWT
+    /*
+    public Point getMousePosition() throws HeadlessException {
+        Point absPointerPos = MouseInfo.getPointerInfo().getLocation();
+        Window winUnderPtr = toolkit.dispatcher.mouseDispatcher.findWindowAt(absPointerPos);
+        Point pointerPos = MouseDispatcher.convertPoint(null, absPointerPos, winUnderPtr);
+        boolean isUnderPointer = false;
+        if (winUnderPtr == null) {
+            return null;
+        }
+        isUnderPointer = winUnderPtr.isComponentAt(this, pointerPos);
+        if (isUnderPointer) {
+            return MouseDispatcher.convertPoint(null, absPointerPos, this);
+        }
+        return null;
+    }
+    */
+
+    /**
+     * Set native caret at the given position <br>
+     * Note: this method takes AWT lock inside because it walks through the
+     * component hierarchy.
+     * 
+     * @param x the x
+     * @param y the y
+     */
+    void setCaretPos(final int x, final int y) {
+        Runnable r = new Runnable() {
+            public void run() {
+                toolkit.lockAWT();
+                try {
+                    setCaretPosImpl(x, y);
+                } finally {
+                    toolkit.unlockAWT();
+                }
+            }
+        };
+        if (Thread.currentThread() instanceof EventDispatchThread) {
+            r.run();
+        } else {
+            toolkit.getSystemEventQueueImpl().postEvent(new InvocationEvent(this, r));
+        }
+    }
+
+    /**
+     * This method should be called only at event dispatch thread.
+     * 
+     * @param x the x
+     * @param y the y
+     */
+    void setCaretPosImpl(int x, int y) {
+        Component c = this;
+        while ((c != null) && c.behaviour.isLightweight()) {
+            x += c.x;
+            y += c.y;
+            //???AWT: c = c.getParent();
+        }
+        if (c == null) {
+            return;
+        }
+        //???AWT
+        /*
+        if (c instanceof Window) {
+            Insets insets = c.getNativeInsets();
+            x -= insets.left;
+            y -= insets.top;
+        }
+        toolkit.getWindowFactory().setCaretPosition(x, y);
+        */
+    }
+
+    // to be overridden in standard components such as Button and List
+    /**
+     * Gets the default minimum size.
+     * 
+     * @return the default minimum size
+     */
+    Dimension getDefaultMinimumSize() {
+        return null;
+    }
+
+    // to be overridden in standard components such as Button and List
+    /**
+     * Gets the default preferred size.
+     * 
+     * @return the default preferred size
+     */
+    Dimension getDefaultPreferredSize() {
+        return null;
+    }
+
+    // to be overridden in standard components such as Button and List
+    /**
+     * Reset default size.
+     */
+    void resetDefaultSize() {
+    }
+
+    //???AWT
+    /*
+    ComponentBehavior createBehavior() {
+        return new LWBehavior(this);
+    }
+    */
+
+    /**
+     * Gets the default background.
+     * 
+     * @return the default background
+     */
+    Color getDefaultBackground() {
+        //???AWT: return getWindowAncestor().getDefaultBackground();
+        return getBackground();
+    }
+
+    /**
+     * Gets the default foreground.
+     * 
+     * @return the default foreground
+     */
+    Color getDefaultForeground() {
+        //???AWT return getWindowAncestor().getDefaultForeground();
+        return getForeground();
+    }
+
+    /**
+     * Called when native resource for this component is created (for
+     * heavyweights only).
+     * 
+     * @param win the win
+     */
+    void nativeWindowCreated(NativeWindow win) {
+        // to be overridden
+    }
+
+    /**
+     * Determine the component's area hidden behind the windows that have higher
+     * Z-order, including windows of other applications.
+     * 
+     * @param image the image
+     * @param destLocation the dest location
+     * @param destSize the dest size
+     * @param source the source
+     * 
+     * @return the calculated region, or null if it cannot be determined
+     */
+    //???AWT
+    /*
+    MultiRectArea getObscuredRegion(Rectangle part) {
+        if (!visible || parent == null || !parent.visible) {
+            return null;
+        }
+        Rectangle r = new Rectangle(0, 0, w, h);
+        if (part != null) {
+            r = r.intersection(part);
+        }
+        if (r.isEmpty()) {
+            return null;
+        }
+        r.translate(x, y);
+        MultiRectArea ret = parent.getObscuredRegion(r);
+        if (ret != null) {
+            parent.addObscuredRegions(ret, this);
+            ret.translate(-x, -y);
+            ret.intersect(new Rectangle(0, 0, w, h));
+        }
+        return ret;
+    }
+    */
+
+    //???AWT
+    /*
+    private void readObject(ObjectInputStream stream) throws IOException,
+            ClassNotFoundException {
+        stream.defaultReadObject();
+        FieldsAccessor accessor = new FieldsAccessor(Component.class, this);
+        accessor.set("toolkit", Toolkit.getDefaultToolkit()); //$NON-NLS-1$
+        accessor.set("behaviour", createBehavior()); //$NON-NLS-1$
+        accessor.set("componentLock", new Object()); // $NON-LOCK-1$ //$NON-NLS-1$
+    }
+    */
+
+    final void onDrawImage(Image image, Point destLocation, Dimension destSize, Rectangle source) {
+        ImageParameters imageParams;
+        if (updatedImages == null) {
+            updatedImages = new HashMap<Image, ImageParameters>();
+        }
+        imageParams = updatedImages.get(image);
+        if (imageParams == null) {
+            imageParams = new ImageParameters();
+            updatedImages.put(image, imageParams);
+        }
+        imageParams.addDrawing(destLocation, destSize, source);
+    }
+
+    public boolean imageUpdate(Image img, int infoflags, int x, int y, int w, int h) {
+        toolkit.lockAWT();
+        try {
+            boolean done = false;
+            if ((infoflags & (ALLBITS | FRAMEBITS)) != 0) {
+                done = true;
+            } else if ((infoflags & SOMEBITS) != 0 && incrementalImageUpdate) {
+                done = true;
+            }
+            if (done) {
+                repaint();
+            }
+            return (infoflags & (ABORT | ALLBITS)) == 0;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    //???AWT
+    /*
+    private void invalidateRealParent() {
+        Container realParent = getRealParent();
+        if ((realParent != null) && realParent.isValid()) {
+            realParent.invalidate();
+        }
+    }
+    */
+
+    /**
+     * The Class ImageParameters.
+     */
+    private class ImageParameters {
+        
+        /** The drawing params. */
+        private final LinkedList<DrawingParameters> drawingParams = new LinkedList<DrawingParameters>();
+
+        /** The size. */
+        Dimension size = new Dimension(Component.this.w, Component.this.h);
+
+        /**
+         * Adds the drawing.
+         * 
+         * @param destLocation the dest location
+         * @param destSize the dest size
+         * @param source the source
+         */
+        void addDrawing(Point destLocation, Dimension destSize, Rectangle source) {
+            drawingParams.add(new DrawingParameters(destLocation, destSize, source));
+        }
+
+        /**
+         * Drawing parameters iterator.
+         * 
+         * @return the iterator< drawing parameters>
+         */
+        Iterator<DrawingParameters> drawingParametersIterator() {
+            return drawingParams.iterator();
+        }
+
+        /**
+         * The Class DrawingParameters.
+         */
+        class DrawingParameters {
+            
+            /** The dest location. */
+            Point destLocation;
+
+            /** The dest size. */
+            Dimension destSize;
+
+            /** The source. */
+            Rectangle source;
+
+            /**
+             * Instantiates a new drawing parameters.
+             * 
+             * @param destLocation the dest location
+             * @param destSize the dest size
+             * @param source the source
+             */
+            DrawingParameters(Point destLocation, Dimension destSize, Rectangle source) {
+                this.destLocation = new Point(destLocation);
+                if (destSize != null) {
+                    this.destSize = new Dimension(destSize);
+                } else {
+                    this.destSize = null;
+                }
+                if (source != null) {
+                    this.source = new Rectangle(source);
+                } else {
+                    this.source = null;
+                }
+            }
+        }
+    }
+
+    /**
+     * TextComponent support.
+     * 
+     * @param e the e
+     * 
+     * @return true, if dispatch event to im
+     */
+    //???AWT
+    /*
+    private TextKit textKit = null;
+
+    TextKit getTextKit() {
+        return textKit;
+    }
+
+    void setTextKit(TextKit kit) {
+        textKit = kit;
+    }
+    */
+
+    /**
+     * TextField support
+     */
+    //???AWT
+    /*
+    private TextFieldKit textFieldKit = null;
+
+    TextFieldKit getTextFieldKit() {
+        return textFieldKit;
+    }
+
+    void setTextFieldKit(TextFieldKit kit) {
+        textFieldKit = kit;
+    }
+    */
+
+    /**
+     * Dispatches input & focus events to input method
+     * context.
+     * @param e event to pass to InputContext.dispatchEvent()
+     * @return true if event was consumed by IM, false otherwise
+     */
+    private boolean dispatchEventToIM(AWTEvent e) {
+        InputContext ic = getInputContext();
+        if (ic == null) {
+            return false;
+        }
+        int id = e.getID();
+        boolean isInputEvent = ((id >= KeyEvent.KEY_FIRST) && (id <= KeyEvent.KEY_LAST))
+                || ((id >= MouseEvent.MOUSE_FIRST) && (id <= MouseEvent.MOUSE_LAST));
+        if (((id >= FocusEvent.FOCUS_FIRST) && (id <= FocusEvent.FOCUS_LAST)) || isInputEvent) {
+            ic.dispatchEvent(e);
+        }
+        return e.isConsumed();
+    }
+}
diff --git a/awt/java/awt/ComponentBehavior.java b/awt/java/awt/ComponentBehavior.java
new file mode 100644
index 0000000..89c9999
--- /dev/null
+++ b/awt/java/awt/ComponentBehavior.java
@@ -0,0 +1,56 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Dmitry A. Durnev
+ * @version $Revision$
+ */
+package java.awt;
+
+import org.apache.harmony.awt.wtk.NativeWindow;
+
+/**
+ * The interface of the helper object that encapsulates the difference
+ * between lightweight and heavyweight components. 
+ */
+interface ComponentBehavior {
+
+    void addNotify();
+
+    void setBounds(int x, int y, int w, int h, int bMask);
+
+    void setVisible(boolean b);
+
+    Graphics getGraphics(int translationX, int translationY, int width, int height);
+
+    NativeWindow getNativeWindow();
+
+    boolean isLightweight();
+
+    void onMove(int x, int y);
+
+    boolean isOpaque();
+
+    boolean isDisplayable();
+
+    void setEnabled(boolean value);
+
+    void removeNotify();
+
+    void setZOrder(int newIndex, int oldIndex);
+
+    boolean setFocus(boolean focus, Component opposite);
+}
diff --git a/awt/java/awt/ComponentOrientation.java b/awt/java/awt/ComponentOrientation.java
new file mode 100644
index 0000000..ddb118d
--- /dev/null
+++ b/awt/java/awt/ComponentOrientation.java
@@ -0,0 +1,140 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov, Dmitry A. Durnev
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.io.Serializable;
+import java.util.*;
+
+/**
+ * The ComponentOrientation class specifies the language-sensitive orientation 
+ * of component's elements or text. It is used to reflect the differences in this 
+ * ordering between different writting systems. The ComponentOrientation class 
+ * indicates the orientation of the elements/text in the horizontal direction
+ * ("left to right" or "right to left") and in the vertical direction
+ * ("top to bottom" or "bottom to top").
+ */
+public final class ComponentOrientation implements Serializable {
+    
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = -4113291392143563828L;
+
+    /** 
+     * The Constant LEFT_TO_RIGHT indicates that items run left to right.
+     */
+    public static final ComponentOrientation LEFT_TO_RIGHT = new ComponentOrientation(true, true);
+
+    /** 
+     * The Constant RIGHT_TO_LEFT indicates that items run right to left.
+     */
+    public static final ComponentOrientation RIGHT_TO_LEFT = new ComponentOrientation(true, false);
+
+    /** The Constant UNKNOWN indicates that a component's orientation is not set. */
+    public static final ComponentOrientation UNKNOWN = new ComponentOrientation(true, true);
+
+    /** The Constant rlLangs. */
+    private static final Set<String> rlLangs = new HashSet<String>(); //RIGHT_TO_LEFT languages
+
+    /** The horizontal. */
+    private final boolean horizontal;
+
+    /** The left2right. */
+    private final boolean left2right;
+
+    static {
+        rlLangs.add("ar"); //$NON-NLS-1$
+        rlLangs.add("fa"); //$NON-NLS-1$
+        rlLangs.add("iw"); //$NON-NLS-1$
+        rlLangs.add("ur"); //$NON-NLS-1$
+    }
+
+    /**
+     * Gets the orientation for the given ResourceBundle's localization.
+     * 
+     * @param bdl the ResourceBundle.
+     * 
+     * @return the ComponentOrientation.
+     * 
+     * @deprecated Use getOrientation(java.util.Locale) method.
+     */
+    @Deprecated
+    public static ComponentOrientation getOrientation(ResourceBundle bdl) {
+        Object obj = null;
+        try {
+            obj = bdl.getObject("Orientation"); //$NON-NLS-1$
+        }
+        catch (MissingResourceException mre) {
+            obj = null;
+        }
+        if (obj instanceof ComponentOrientation) {
+            return (ComponentOrientation) obj;
+        }
+        Locale locale = bdl.getLocale();
+        if (locale == null) {
+            locale = Locale.getDefault();
+        }
+        return getOrientation(locale);
+    }
+
+    /**
+     * Gets the orientation for the specified locale.
+     * 
+     * @param locale the specified Locale.
+     * 
+     * @return the ComponentOrientation.
+     */
+    public static ComponentOrientation getOrientation(Locale locale) {
+        String lang = locale.getLanguage();
+        return rlLangs.contains(lang) ? RIGHT_TO_LEFT : LEFT_TO_RIGHT;
+    }
+
+    /**
+     * Instantiates a new component orientation.
+     * 
+     * @param hor whether the items should be arranged horizontally
+     * @param l2r whether this orientation specifies a left-to-right flow
+     */
+    private ComponentOrientation(boolean hor, boolean l2r) {
+        horizontal = hor;
+        left2right = l2r;
+    }
+
+    /**
+     * Returns true if the text of the of writing systems arranged
+     * horizontally.
+     * 
+     * @return true, if the text is written horizontally, false 
+     * for a vertical arrangement. 
+     */
+    public boolean isHorizontal() {
+        return horizontal;
+    }
+
+    /**
+     * Returns true if the text is arranged from left to right.
+     * 
+     * @return true, for writing systems written from left to right; 
+     * false for right-to-left.
+     */
+    public boolean isLeftToRight() {
+        return left2right;
+    }
+
+}
diff --git a/awt/java/awt/Composite.java b/awt/java/awt/Composite.java
new file mode 100644
index 0000000..8e5b90a
--- /dev/null
+++ b/awt/java/awt/Composite.java
@@ -0,0 +1,47 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.awt.image.ColorModel;
+
+/**
+ * The Composite interface allows the methods to compose a draw primitive 
+ * on the graphics area. The classes implementing this interface provides 
+ * the rules and a method to create the context for a particular operation.
+ */
+public interface Composite {
+
+    /**
+     * Creates a CompositeContext which defines the encapsulated and 
+     * optimized environment for a compositing operation. Several contexts 
+     * can exist for a single Composite object.
+     * 
+     * @param srcColorModel the source's ColorModel.
+     * @param dstColorModel the destination's ColorModel.
+     * @param hints the RenderingHints.
+     * 
+     * @return the CompositeContext object.
+     */
+    public CompositeContext createContext(ColorModel srcColorModel,
+            ColorModel dstColorModel, RenderingHints hints);
+
+}
+
diff --git a/awt/java/awt/CompositeContext.java b/awt/java/awt/CompositeContext.java
new file mode 100644
index 0000000..c676032
--- /dev/null
+++ b/awt/java/awt/CompositeContext.java
@@ -0,0 +1,49 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+
+/**
+ * The CompositeContext interface specifies the encapsulated and optimized 
+ * environment for a compositing operation. 
+ */
+public interface CompositeContext {
+
+    /**
+     * Composes the two source Raster objects and places the result in the 
+     * destination WritableRaster. 
+     * 
+     * @param src the source Raster.
+     * @param dstIn the destination Raster.
+     * @param dstOut the WritableRaster object where the result of
+     * composing operation is stored.
+     */
+    public void compose(Raster src, Raster dstIn, WritableRaster dstOut);
+
+    /**
+     * Releases resources allocated for a context.
+     */
+    public void dispose();
+
+}
+
diff --git a/awt/java/awt/Cursor.java b/awt/java/awt/Cursor.java
new file mode 100644
index 0000000..625686c
--- /dev/null
+++ b/awt/java/awt/Cursor.java
@@ -0,0 +1,372 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Dmitry A. Durnev
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+import org.apache.harmony.awt.wtk.NativeCursor;
+
+/**
+ * The Cursor class represents the bitmap of the mouse cursor.
+ */
+public class Cursor implements Serializable {
+    
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = 8028237497568985504L;
+    
+    /** The Constant DEFAULT_CURSOR indicates the default cursor type. */
+    public static final int DEFAULT_CURSOR = 0;
+
+    /** The Constant CROSSHAIR_CURSOR cursor type. */
+    public static final int CROSSHAIR_CURSOR = 1;
+
+    /** The Constant TEXT_CURSOR cursor type. */
+    public static final int TEXT_CURSOR = 2;
+
+    /** The Constant WAIT_CURSOR cursor type. */
+    public static final int WAIT_CURSOR = 3;
+
+    /** The Constant SW_RESIZE_CURSOR cursor type. */
+    public static final int SW_RESIZE_CURSOR = 4;
+
+    /** The Constant SE_RESIZE_CURSOR cursor type. */
+    public static final int SE_RESIZE_CURSOR = 5;
+
+    /** The Constant NW_RESIZE_CURSOR cursor type. */
+    public static final int NW_RESIZE_CURSOR = 6;
+
+    /** The Constant NE_RESIZE_CURSOR cursor type. */
+    public static final int NE_RESIZE_CURSOR = 7;
+
+    /** The Constant N_RESIZE_CURSOR cursor type. */
+    public static final int N_RESIZE_CURSOR = 8;
+
+    /** The Constant S_RESIZE_CURSOR cursor type. */
+    public static final int S_RESIZE_CURSOR = 9;
+
+    /** The Constant W_RESIZE_CURSOR cursor type. */
+    public static final int W_RESIZE_CURSOR = 10;
+
+    /** The Constant E_RESIZE_CURSOR cursor type. */
+    public static final int E_RESIZE_CURSOR = 11;
+
+    /** The Constant HAND_CURSOR cursor type. */
+    public static final int HAND_CURSOR = 12;
+
+    /** The Constant MOVE_CURSOR cursor type. */
+    public static final int MOVE_CURSOR = 13;
+
+    /** A mapping from names to system custom cursors. */
+    static Map<String, Cursor> systemCustomCursors;
+    
+    /** The cursor props. */
+    static Properties cursorProps;
+
+    /** The Constant predefinedNames. */
+    static final String[] predefinedNames = {
+            "Default", "Crosshair", "Text", "Wait", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+            "Southwest Resize", "Southeast Resize", //$NON-NLS-1$ //$NON-NLS-2$
+            "Northwest Resize", "Northeast Resize", //$NON-NLS-1$ //$NON-NLS-2$
+            "North Resize", "South Resize", "West Resize", "East Resize", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+            "Hand", "Move" //$NON-NLS-1$ //$NON-NLS-2$
+
+    };
+
+    /** The predefined set of cursors. */
+    protected static Cursor[] predefined = {
+            new Cursor(DEFAULT_CURSOR), null, null, null,
+            null, null, null, null,
+            null, null, null, null,
+            null, null
+    };
+
+    /** The Constant CUSTOM_CURSOR is associated with all custom cursor types. 
+     * (Those which are not predefined)
+     */
+    public static final int CUSTOM_CURSOR = -1;
+
+    /** The name of the cursor. */
+    protected String name;
+
+    /** The type of the cursor, chosen from the list of cursor type constants. */
+    private final int type;
+    
+    /** The native cursor. */
+    private transient NativeCursor nativeCursor;
+    
+    /** The exact point on the cursor image that indicates which point 
+     * the cursor is selecting (pointing to). The coordinates are given 
+     * with respect the origin of the Image (its upper left corner).
+     */
+    private Point hotSpot;
+    
+    /** The image to draw on the screen representing the cursor. */
+    private Image image;
+
+    /**
+     * Instantiates a new cursor with the specified name.
+     * 
+     * @param name the name of cursor.
+     */
+    protected Cursor(String name) {
+        this(name, null, new Point());
+    }
+
+    /**
+     * Instantiates a new cursor of the specified type.
+     * 
+     * @param type the type of cursor.
+     */
+    public Cursor(int type) {
+        checkType(type);
+        this.type = type;
+        if ((type >= 0) && (type < predefinedNames.length)) {
+            name = predefinedNames[type] + " Cursor"; //$NON-NLS-1$
+        }
+    }
+
+    /**
+     * Instantiates a new cursor.
+     * 
+     * @param name the name
+     * @param img the img
+     * @param hotSpot the hot spot
+     */
+    Cursor(String name, Image img, Point hotSpot) {
+        this.name = name;
+        type = CUSTOM_CURSOR;
+        this.hotSpot = hotSpot;
+        image = img;
+    }
+
+    /**
+     * Finalize method overrided finalize method from Object class.
+     * 
+     * @throws Throwable if the native cursor is not null and throws
+     * a throwable when destroyed.
+     */
+    @Override
+    protected void finalize() throws Throwable {
+        if (nativeCursor != null) {
+            nativeCursor.destroyCursor();
+        }
+    }
+
+    /**
+     * Gets the name of the cursor.
+     * 
+     * @return the name of the cursor.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Returns the String representation of the cursor.
+     * 
+     * @return the String representation of the cursor.
+     */
+    @Override
+    public String toString() {
+        return getClass().getName() + "[" + name + "]"; //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Gets the cursor type.
+     * 
+     * @return the cursor type
+     */
+    public int getType() {
+        return type;
+    }
+
+    /**
+     * Gets the predefined cursor with the specified type.
+     * 
+     * @param type the type of cursor.
+     * 
+     * @return the predefined cursor with the specified type.
+     */
+    public static Cursor getPredefinedCursor(int type) {
+        checkType(type);
+        Cursor cursor = predefined[type];
+        if (cursor == null) {
+            cursor = new Cursor(type);
+            predefined[type] = cursor;
+        }
+        return cursor;
+    }
+
+    /**
+     * Gets the default cursor.
+     * 
+     * @return the default cursor.
+     */
+    public static Cursor getDefaultCursor() {
+        return getPredefinedCursor(DEFAULT_CURSOR);
+    }
+
+    /**
+     * Gets the specified system custom cursor.
+     * 
+     * @param name the name of the desired system cursor.
+     * 
+     * @return the specific system cursor with the specified name.
+     * 
+     * @throws AWTException if the desired cursor has malformed data
+     * such as an incorrectly defined hot spot.
+     * @throws HeadlessException if the isHeadless method of the GraphicsEnvironment
+     * returns true.
+     */
+    public static Cursor getSystemCustomCursor(String name)
+    throws AWTException, HeadlessException {
+        Toolkit.checkHeadless();
+        return getSystemCustomCursorFromMap(name);
+    }
+
+    /**
+     * Gets the specified system custom cursor from the map of system custom cursors.
+     * 
+     * @param name the name of the desired cursor.
+     * 
+     * @return the desired system custom cursor from the 
+     * map of system custom cursors.
+     * 
+     * @throws AWTException the AWT exception
+     */
+    private static Cursor getSystemCustomCursorFromMap (String name)
+    throws AWTException {
+        loadCursorProps();
+        if (systemCustomCursors == null) {
+            systemCustomCursors = new HashMap<String, Cursor>();
+        }
+        Cursor cursor = systemCustomCursors.get(name);
+        if (cursor != null) {
+            return cursor;
+        }
+        // awt.141=failed to parse hotspot property for cursor:
+        String exMsg = Messages.getString("awt.141") + name; //$NON-NLS-1$
+        String nm = "Cursor." + name; //$NON-NLS-1$
+        String nameStr = cursorProps.getProperty(nm + ".Name"); //$NON-NLS-1$
+        String hotSpotStr = cursorProps.getProperty(nm + ".HotSpot"); //$NON-NLS-1$
+        String fileStr = cursorProps.getProperty(nm + ".File"); //$NON-NLS-1$
+        int idx = hotSpotStr.indexOf(',');
+        if (idx < 0) {
+            throw new AWTException(exMsg);
+        }
+        int x, y;
+        try {
+            x = new Integer(hotSpotStr.substring(0, idx)).intValue();
+            y = new Integer(hotSpotStr.substring(idx + 1,
+                                                 hotSpotStr.length())).intValue();
+        } catch (NumberFormatException nfe) {
+            throw new AWTException(exMsg);
+        }
+        Image img = Toolkit.getDefaultToolkit().createImage(fileStr);
+        cursor = new Cursor(nameStr, img, new Point(x, y));
+        systemCustomCursors.put(name, cursor);
+
+        return cursor;
+    }
+
+    /**
+     * Load cursor props.
+     * 
+     * @throws AWTException the AWT exception
+     */
+    private static void loadCursorProps() throws AWTException {
+        if (cursorProps != null) {
+            return;
+        }
+        String sep = File.separator;
+        String cursorsDir = "lib" + sep + "images" + sep + "cursors"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+        String cursorsAbsDir = System.getProperty("java.home") + sep + //$NON-NLS-1$
+                                cursorsDir;
+        String cursorPropsFileName = "cursors.properties"; //$NON-NLS-1$
+        String cursorPropsFullFileName = (cursorsAbsDir + sep +
+                                          cursorPropsFileName);
+        cursorProps = new Properties();
+        try {
+            cursorProps.load(new FileInputStream(new File(
+                    cursorPropsFullFileName)));
+        } catch (FileNotFoundException e) {
+            // awt.142=Exception: class {0} {1} occurred while loading: {2}
+            throw new AWTException(Messages.getString("awt.142",//$NON-NLS-1$
+                      new Object[]{e.getClass(), e.getMessage(), cursorPropsFullFileName}));
+        } catch (IOException e) {
+            throw new AWTException(e.getMessage());
+        }
+
+    }
+
+    /**
+     * Check type.
+     * 
+     * @param type the type
+     */
+    static void checkType(int type) {
+        // can't use predefined array here because it may not have been
+        // initialized yet
+        if ((type < 0) || (type >= predefinedNames.length)) {
+            // awt.143=illegal cursor type
+            throw new IllegalArgumentException(Messages.getString("awt.143")); //$NON-NLS-1$
+        }
+    }
+
+    // "lazily" create native cursors:
+    /**
+     * Gets the native cursor.
+     * 
+     * @return the native cursor
+     */
+    NativeCursor getNativeCursor() {
+        if (nativeCursor != null) {
+            return nativeCursor;
+        }
+        Toolkit toolkit = Toolkit.getDefaultToolkit();
+        if (type != CUSTOM_CURSOR) {
+            nativeCursor = toolkit.createNativeCursor(type);
+        } else {
+            nativeCursor = toolkit.createCustomNativeCursor(image, hotSpot,
+                                                            name);
+        }
+        return nativeCursor;
+    }
+
+    /**
+     * Sets the native cursor.
+     * 
+     * @param nativeCursor the new native cursor
+     */
+    void setNativeCursor(NativeCursor nativeCursor) {
+        this.nativeCursor = nativeCursor;
+    }
+}
+
diff --git a/awt/java/awt/Dimension.java b/awt/java/awt/Dimension.java
new file mode 100644
index 0000000..8137846
--- /dev/null
+++ b/awt/java/awt/Dimension.java
@@ -0,0 +1,185 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Denis M. Kishenko
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.awt.geom.Dimension2D;
+import java.io.Serializable;
+
+import org.apache.harmony.misc.HashCode;
+
+/**
+ * The Dimension represents the size (width and height) of a component.
+ * The width and height values can be negative, but in that case the 
+ * behavior of some methods is unexpected. 
+ */
+public class Dimension extends Dimension2D implements Serializable {
+
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = 4723952579491349524L;
+
+    /** The width dimension. */
+    public int width;
+    
+    /** The height dimension. */
+    public int height;
+
+    /**
+     * Instantiates a new Dimension with the same data as the specified Dimension.
+     * 
+     * @param d the Dimension to copy the data from when creating the 
+     * new Dimension object.
+     */
+    public Dimension(Dimension d) {
+        this(d.width, d.height);
+    }
+
+    /**
+     * Instantiates a new Dimension with zero width and height.
+     */
+    public Dimension() {
+        this(0, 0);
+    }
+
+    /**
+     * Instantiates a new Dimension with the specified width and height.
+     * 
+     * @param width the width of the new Dimension.
+     * @param height the height of the new Dimension.
+     */
+    public Dimension(int width, int height) {
+        setSize(width, height);
+    }
+
+    /**
+     * Returns the hash code of the Dimension.
+     * 
+     * @return the hash code of the Dimension.
+     */
+    @Override
+    public int hashCode() {
+        HashCode hash = new HashCode();
+        hash.append(width);
+        hash.append(height);
+        return hash.hashCode();
+    }
+
+    /**
+     * Compares this Dimension object with the specified object.
+     * 
+     * @param obj the Object to be compared.
+     * 
+     * @return true, if the specified Object is a Dimension with 
+     * the same width and height data as this Dimension. 
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (obj instanceof Dimension) {
+            Dimension d = (Dimension)obj;
+            return (d.width == width && d.height == height);
+        }
+        return false;
+    }
+
+    /**
+     * Returns the String associated to this Dimension object.
+     * 
+     * @return the String associated to this Dimension object.
+     */
+    @Override
+    public String toString() {
+        // The output format based on 1.5 release behaviour. It could be obtained in the following way
+        // System.out.println(new Dimension().toString())
+        return getClass().getName() + "[width=" + width + ",height=" + height + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+    }
+
+    /**
+     * Sets the size of this Dimension object with the specified width and height.
+     * 
+     * @param width the width of the Dimension.
+     * @param height the height of the Dimension.
+     */
+    public void setSize(int width, int height) {
+        this.width = width;
+        this.height = height;
+    }
+
+    /**
+     * Sets the size of this Dimension object by copying the 
+     * data from the specified Dimension object.
+     * 
+     * @param d the Dimension that gives the new size values.
+     */
+    public void setSize(Dimension d) {
+        setSize(d.width, d.height);
+    }
+
+    /**
+     * Sets the size of this Dimension object with the specified double width 
+     * and height.
+     * 
+     * @param width the width of the Dimension.
+     * @param height the height of the Dimension.
+     * 
+     * @see java.awt.geom.Dimension2D#setSize(double, double)
+     */
+    @Override
+    public void setSize(double width, double height) {
+        setSize((int)Math.ceil(width), (int)Math.ceil(height));
+    }
+
+    /**
+     * Gets the size of the Dimension.
+     * 
+     * @return the size of the Dimension.
+     */
+    public Dimension getSize() {
+        return new Dimension(width, height);
+    }
+
+    /**
+     * Gets the height of the Dimension.
+     * 
+     * @return the height of the Dimension.
+     * 
+     * @see java.awt.geom.Dimension2D#getHeight()
+     */
+    @Override
+    public double getHeight() {
+        return height;
+    }
+
+    /**
+     * Gets the width of the Dimension.
+     * 
+     * @return the width of the Dimension.
+     * 
+     * @see java.awt.geom.Dimension2D#getWidth()
+     */
+    @Override
+    public double getWidth() {
+        return width;
+    }
+
+}
+
diff --git a/awt/java/awt/Dispatcher.java b/awt/java/awt/Dispatcher.java
new file mode 100644
index 0000000..d457af4
--- /dev/null
+++ b/awt/java/awt/Dispatcher.java
@@ -0,0 +1,723 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov, Dmitry A. Durnev
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.awt.event.ComponentEvent;
+import java.awt.event.FocusEvent;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.event.PaintEvent;
+import java.awt.event.WindowEvent;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+import org.apache.harmony.awt.wtk.NativeEvent;
+import org.apache.harmony.awt.wtk.NativeWindow;
+
+
+/**
+ * Helper package-private class for managing lightweight components &
+ * dispatching events from heavyweight source
+ */
+class Dispatcher {
+
+    //???AWT: final PopupDispatcher popupDispatcher = new PopupDispatcher();
+
+    //???AWT: final FocusDispatcher focusDispatcher;
+
+    final MouseGrabManager mouseGrabManager = new MouseGrabManager();
+
+    final MouseDispatcher mouseDispatcher;
+
+    private final ComponentDispatcher componentDispatcher = new ComponentDispatcher();
+
+    private final KeyDispatcher keyDispatcher = new KeyDispatcher();
+
+    private final Toolkit toolkit;
+
+    int clickInterval = 250;
+
+    /**
+     * @param toolkit - AWT toolkit
+     */
+    Dispatcher(Toolkit toolkit) {
+        this.toolkit = toolkit;
+
+        //???AWT: focusDispatcher = new FocusDispatcher(toolkit);
+        mouseDispatcher = new MouseDispatcher(mouseGrabManager, toolkit);
+    }
+
+    /**
+     * Dispatch native event: produce appropriate AWT events, 
+     * update component's fields when needed
+     * @param event - native event to dispatch
+     * @return - true means default processing by OS is not needed
+     */
+    public boolean onEvent(NativeEvent event) {
+        int eventId = event.getEventId();
+
+        if (eventId == NativeEvent.ID_CREATED) {
+            return toolkit.onWindowCreated(event.getWindowId());
+        } else if (eventId == NativeEvent.ID_MOUSE_GRAB_CANCELED) {
+            return mouseGrabManager.onGrabCanceled();
+        //???AWT
+//        } else if (popupDispatcher.onEvent(event)) {
+//            return false;
+        } else {
+            Component src = toolkit.getComponentById(event.getWindowId());
+
+            if (src != null) {
+                if (((eventId >= ComponentEvent.COMPONENT_FIRST) && (eventId <= ComponentEvent.COMPONENT_LAST))
+                        || ((eventId >= WindowEvent.WINDOW_FIRST) && (eventId <= WindowEvent.WINDOW_LAST))
+                        || (eventId == NativeEvent.ID_INSETS_CHANGED)
+                        || (eventId == NativeEvent.ID_BOUNDS_CHANGED)
+                        || (eventId == NativeEvent.ID_THEME_CHANGED)) {
+                    return componentDispatcher.dispatch(src, event);
+                } else if ((eventId >= MouseEvent.MOUSE_FIRST)
+                        && (eventId <= MouseEvent.MOUSE_LAST)) {
+                    return mouseDispatcher.dispatch(src, event);
+                } else if (eventId == PaintEvent.PAINT) {
+                    //???AWT: src.redrawManager.addPaintRegion(src, event.getClipRects());
+                    return true;
+                }
+            }
+            if ((eventId >= FocusEvent.FOCUS_FIRST)
+                    && (eventId <= FocusEvent.FOCUS_LAST)) {
+
+                //???AWT: return focusDispatcher.dispatch(src, event);
+                return false;
+            } else if ((eventId >= KeyEvent.KEY_FIRST)
+                    && (eventId <= KeyEvent.KEY_LAST)) {
+                return keyDispatcher.dispatch(src, event);
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * The dispatcher of native events that affect 
+     * component's state or bounds
+     */
+    final class ComponentDispatcher {
+
+        /**
+         * Handle native event that affects component's state or bounds
+         * @param src - the component updated by the event
+         * @param event - the native event
+         * @return - as in Dispatcher.onEvent()
+         * @see Dispatcher#onEvent(NativeEvent)
+         */
+        boolean dispatch(Component src, NativeEvent event) {
+            int id = event.getEventId();
+
+            if ((id == NativeEvent.ID_INSETS_CHANGED)
+                    || (id == NativeEvent.ID_THEME_CHANGED)) {
+                return dispatchInsets(event, src);
+            } else if ((id >= WindowEvent.WINDOW_FIRST)
+                    && (id <= WindowEvent.WINDOW_LAST)) {
+                return dispatchWindow(event, src);
+            } else {
+                return dispatchPureComponent(event, src);
+            }
+        }
+
+        /**
+         * Handle the change of top-level window's native decorations 
+         * @param event - the native event
+         * @param src - the component updated by the event
+         * @return - as in Dispatcher.onEvent()
+         * @see Dispatcher#onEvent(NativeEvent)
+         */
+        boolean dispatchInsets(NativeEvent event, Component src) {
+            //???AWT
+            /*
+            if (src instanceof Window) {
+                ((Window) src).setNativeInsets(event.getInsets());
+            }
+            */
+            return false;
+        }
+
+        /**
+         * Handle the change of top-level window's state
+         * @param event - the native event
+         * @param src - the component updated by the event
+         * @return - as in Dispatcher.onEvent()
+         * @see Dispatcher#onEvent(NativeEvent)
+         */
+        boolean dispatchWindow(NativeEvent event, Component src) {
+            //???AWT
+            /*
+            Window window = (Window) src;
+            int id = event.getEventId();
+
+            if (id == WindowEvent.WINDOW_CLOSING) {
+                toolkit.getSystemEventQueueImpl().postEvent(
+                          new WindowEvent(window, WindowEvent.WINDOW_CLOSING));
+
+                return true;
+            } else if (id == WindowEvent.WINDOW_STATE_CHANGED) {
+                if (window instanceof Frame) {
+                    ((Frame) window)
+                            .updateExtendedState(event.getWindowState());
+                }
+            }
+            */
+
+            return false;
+        }
+
+        /**
+         * Handle the change of component's size and/or position
+         * @param event - the native event
+         * @param src - the component updated by the event
+         * @return - as in Dispatcher.onEvent()
+         * @see Dispatcher#onEvent(NativeEvent)
+         */
+        private boolean dispatchPureComponent(NativeEvent event, Component src) {
+            Rectangle rect = event.getWindowRect();
+            Point loc = rect.getLocation();
+            int mask;
+
+            switch (event.getEventId()) {
+            case NativeEvent.ID_BOUNDS_CHANGED:
+                mask = 0;
+                break;
+            case ComponentEvent.COMPONENT_MOVED:
+                mask = NativeWindow.BOUNDS_NOSIZE;
+                break;
+            case ComponentEvent.COMPONENT_RESIZED:
+                mask = NativeWindow.BOUNDS_NOMOVE;
+                break;
+            default:
+                // awt.12E=Unknown component event id.
+                throw new RuntimeException(Messages.getString("awt.12E")); //$NON-NLS-1$
+            }
+
+            //???AWT
+            /*
+            if (!(src instanceof Window)) {
+                Component compTo = src.getParent();
+                Component compFrom = src.getHWAncestor();
+
+                if ((compTo != null) && (compFrom != null)) {
+                    loc = MouseDispatcher.convertPoint(compFrom, loc, compTo);
+                }
+            } else {
+                int windowState = event.getWindowState();
+
+                if ((windowState >= 0) && (src instanceof Frame)) {
+                    ((Frame) src).updateExtendedState(windowState);
+                }
+            }
+            src.setBounds(loc.x, loc.y, rect.width, rect.height, mask, false);
+            */
+            
+            return false;
+        }
+
+    }
+
+    /**
+     * The dispatcher of the keyboard events
+     */
+    final class KeyDispatcher {
+
+        /**
+         * Handle the keyboard event using the KeyboardFocusManager
+         * @param src - the component receiving the event
+         * @param event - the native event
+         * @return - as in Dispatcher.onEvent()
+         * @see Dispatcher#onEvent(NativeEvent)
+         */
+        boolean dispatch(Component src, NativeEvent event) {
+            int id = event.getEventId();
+            int modifiers = event.getInputModifiers();
+            int location = event.getKeyLocation();
+            int code = event.getVKey();
+            StringBuffer chars = event.getKeyChars();
+            int charsLength = chars.length();
+            long time = event.getTime();
+            char keyChar = event.getLastChar();
+
+            //???AWT
+            /*
+            if (src == null) {
+                //retarget focus proxy key events to focusOwner:
+                Window focusProxyOwner = toolkit.getFocusProxyOwnerById(event
+                        .getWindowId());
+                if (focusProxyOwner == null) {
+                    return false;
+                }
+                src = KeyboardFocusManager.actualFocusOwner;
+            }
+            */
+
+            EventQueue eventQueue = toolkit.getSystemEventQueueImpl();
+            
+            if (src != null) {
+                eventQueue.postEvent(new KeyEvent(src, id, time, modifiers,
+                        code, keyChar, location));
+                // KEY_TYPED goes after KEY_PRESSED
+                if (id == KeyEvent.KEY_PRESSED) {
+                    for (int i = 0; i < charsLength; i++) {
+                        keyChar = chars.charAt(i);
+                        if (keyChar != KeyEvent.CHAR_UNDEFINED) {
+                            eventQueue.postEvent(new KeyEvent(src,
+                                    KeyEvent.KEY_TYPED, time, modifiers,
+                                    KeyEvent.VK_UNDEFINED, keyChar,
+                                    KeyEvent.KEY_LOCATION_UNKNOWN));
+                        }
+                    }
+                }
+            }
+
+            return false;
+        }
+
+    }
+
+    /**
+     * Retargets the mouse events to the grab owner when mouse is grabbed,
+     * grab and ungrab mouse when mouse buttons are pressed and released
+     */
+
+    static final class MouseGrabManager {
+
+        /** 
+         * The top-level window holding the mouse grab 
+         * that was explicitly started by startGrab() method
+         */
+        //???AWT: private Window nativeGrabOwner = null;
+        /** 
+         * The component that owns the synthetic 
+         * mouse grab while at least one of the
+         * mouse buttons is pressed
+         */
+        private Component syntheticGrabOwner = null;
+
+        /**
+         * Previous value of syntheticGrabOwner
+         */
+        private Component lastSyntheticGrabOwner = null;
+
+        /**
+         * Number of mouse buttons currently pressed
+         */
+        private int syntheticGrabDepth = 0;
+
+        /**
+         * The callback to be called when the explicit mouse grab ends
+         */
+        private Runnable whenCanceled;
+
+        /**
+         * Explicitly start the mouse grab
+         * @param grabWindow - the window that will own the grab
+         * @param whenCanceled - the callback to call when the grab ends. 
+         * This parameter can be null
+         */
+        //???AWT
+        /*
+        void startGrab(Window grabWindow, Runnable whenCanceled) {
+
+            if (nativeGrabOwner != null) {
+                // awt.12F=Attempt to start nested mouse grab
+                throw new RuntimeException(Messages.getString("awt.12F")); //$NON-NLS-1$
+            }
+
+            NativeWindow win = grabWindow.getNativeWindow();
+            if (win == null) {
+                // awt.130=Attempt to grab mouse in not displayable window
+                throw new RuntimeException(Messages.getString("awt.130")); //$NON-NLS-1$
+            }
+
+            nativeGrabOwner = grabWindow;
+            this.whenCanceled = whenCanceled;
+            win.grabMouse();
+        }
+        */
+
+        /**
+         * Ends the explicit mouse grab. If the non-null callback was provided
+         * in the startGrab() method, this callback is called 
+         */
+        void endGrab() {
+            //???AWT
+            /*
+            if (nativeGrabOwner == null) {
+                return;
+            }
+
+            Window grabWindow = nativeGrabOwner;
+            nativeGrabOwner = null;
+            NativeWindow win = grabWindow.getNativeWindow();
+
+            if (win != null) {
+                win.ungrabMouse();
+                if (whenCanceled != null) {
+                    whenCanceled.run();
+                    whenCanceled = null;
+                }
+            }
+            */
+        }
+
+        /**
+         * Ends both explicit and synthetic grans 
+         * @return - always returns false
+         */
+        boolean onGrabCanceled() {
+            endGrab();
+            resetSyntheticGrab();
+
+            return false;
+        }
+
+        /**
+         * Starts the synthetic mouse grab, increases the counter 
+         * of currently pressed mouse buttons
+         * @param source - the component where mouse press event occured
+         * @return - the component that owns the synthetic grab
+         */
+        Component onMousePressed(Component source) {
+            if (syntheticGrabDepth == 0) {
+                syntheticGrabOwner = source;
+                lastSyntheticGrabOwner = source;
+            }
+            syntheticGrabDepth++;
+
+            return syntheticGrabOwner;
+        }
+
+        /**
+         * Decreases the counter of currently pressed mouse buttons,
+         * ends the synthetic mouse grab, when this counter becomes zero
+         * @param source - the component where mouse press event occured
+         * @return - the component that owns the synthetic grab, 
+         * or source parameter if mouse grab was released
+         */
+        Component onMouseReleased(Component source) {
+            Component ret = source;
+
+            //???AWT
+            /*
+            if (syntheticGrabOwner != null && nativeGrabOwner == null) {
+                ret = syntheticGrabOwner;
+            }
+            */
+            syntheticGrabDepth--;
+            if (syntheticGrabDepth <= 0) {
+                resetSyntheticGrab();
+                lastSyntheticGrabOwner = null;
+            }
+
+            return ret;
+        }
+
+        /**
+         * Update the state of synthetic ouse gram 
+         * when the mouse is moved/dragged
+         * @param event - the native event
+         */
+        void preprocessEvent(NativeEvent event) {
+            int id = event.getEventId();
+            switch (id) {
+            case MouseEvent.MOUSE_MOVED:
+                if (syntheticGrabOwner != null) {
+                    syntheticGrabOwner = null;
+                    syntheticGrabDepth = 0;
+                }
+                if (lastSyntheticGrabOwner != null) {
+                    lastSyntheticGrabOwner = null;
+                }
+            case MouseEvent.MOUSE_DRAGGED:
+                if (syntheticGrabOwner == null
+                        && lastSyntheticGrabOwner != null) {
+                    syntheticGrabOwner = lastSyntheticGrabOwner;
+                    syntheticGrabDepth = 0;
+                    int mask = event.getInputModifiers();
+                    syntheticGrabDepth += (mask & InputEvent.BUTTON1_DOWN_MASK) != 0 ? 1
+                            : 0;
+                    syntheticGrabDepth += (mask & InputEvent.BUTTON2_DOWN_MASK) != 0 ? 1
+                            : 0;
+                    syntheticGrabDepth += (mask & InputEvent.BUTTON3_DOWN_MASK) != 0 ? 1
+                            : 0;
+                }
+            }
+        }
+
+        /**
+         * @return the component that currently owns the synthetic grab 
+         */
+        Component getSyntheticGrabOwner() {
+            return syntheticGrabOwner;
+        }
+
+        /**
+         * ends synthetic grab
+         */
+        private void resetSyntheticGrab() {
+            syntheticGrabOwner = null;
+            syntheticGrabDepth = 0;
+        }
+
+    }
+    
+    /**
+     * Dispatches native events related to the pop-up boxes 
+     * (the non-component windows such as menus and drop lists)
+     */
+//    final class PopupDispatcher {
+//
+//        private PopupBox activePopup;
+//
+//        private PopupBox underCursor;
+//
+//        private final MouseGrab grab = new MouseGrab();
+//
+//        /**
+//         * Handles the mouse grab for pop-up boxes
+//         */
+//        private final class MouseGrab {
+//            private int depth;
+//
+//            private PopupBox owner;
+//
+//            private final Point start = new Point();
+//
+//            /**
+//             * Starts the grab when mouse is pressed
+//             * @param src - the pop-up box where mouse event has occured
+//             * @param where - the mouse pointer location
+//             * @return - the grab owner
+//             */
+//            PopupBox mousePressed(PopupBox src, Point where) {
+//                if (depth == 0) {
+//                    owner = src;
+//                    start.setLocation(where);
+//                }
+//                depth++;
+//                return owner;
+//            }
+//
+//            /**
+//             * Ends the grab when all mousebuttons are released
+//             * @param src - the pop-up box where mouse event has occured
+//             * @param where - the mouse pointer location
+//             * @return - the grab owner, or src parameter if the grab has ended
+//             */
+//            PopupBox mouseReleased(PopupBox src, Point where) {
+//                PopupBox ret = (owner != null) ? owner : src;
+//                if (depth == 0) {
+//                    return ret;
+//                }
+//                depth--;
+//                if (depth == 0) {
+//                    PopupBox tgt = owner;
+//                    owner = null;
+//                    if (tgt != null && src == null) {
+//                        Point a = new Point(start);
+//                        Point b = new Point(where);
+//                        Point pos = tgt.getScreenLocation();
+//                        a.translate(-pos.x, -pos.y);
+//                        b.translate(-pos.x, -pos.y);
+//                        if (tgt.closeOnUngrab(a, b)) {
+//                            return null;
+//                        }
+//                    }
+//                }
+//                return ret;
+//            }
+//
+//            /**
+//             * Set the grab owner to null
+//             */
+//            void reset() {
+//                depth = 0;
+//                owner = null;
+//                start.setLocation(0, 0);
+//            }
+//
+//            /**
+//             * @return - the pop-up box currently owning the grab
+//             */
+//            public PopupBox getOwner() {
+//                return owner;
+//            }
+//        }
+//
+//        /**
+//         * Call the mouse event handler of the pop-up box
+//         * @param src - the pop-up box where the mouse event occured
+//         * @param eventId - the event ID, one of MouseEvent.MOUSE_* constants
+//         * @param where - the mouse pointer location
+//         * @param event - native event
+//         */
+//        private void mouseEvent(PopupBox src, int eventId, Point where,
+//                NativeEvent event) {
+//            Point pos = src.getScreenLocation();
+//            pos.setLocation(where.x - pos.x, where.y - pos.y);
+//
+//            src.onMouseEvent(eventId, pos, event.getMouseButton(), event
+//                    .getTime(), event.getInputModifiers(), event
+//                    .getWheelRotation());
+//        }
+//
+//        /**
+//         * Handle the native event targeted by a pop-up box. This could be 
+//         * paint event, mouse or keyboard event.
+//         * @param event - the native event
+//         * @return - false if the event was handled and doesn't 
+//         * need the further processing; true when the further 
+//         * processing is needed
+//         */
+//        boolean onEvent(NativeEvent event) {
+//            PopupBox src = toolkit.getPopupBoxById(event.getWindowId());
+//            int id = event.getEventId();
+//
+//            if ((id == PaintEvent.PAINT)) {
+//                if (src != null) {
+//                    src.paint(event.getClipRects());
+//                    return true;
+//                }
+//                Component c = toolkit.getComponentById(event.getWindowId());
+//                if ((c != null) && (c instanceof Frame)) {
+//                    ((Frame) c).paintMenuBar(event.getClipRects());
+//                }
+//                return false;
+//            }
+//
+//            if ((id >= MouseEvent.MOUSE_FIRST) && (id <= MouseEvent.MOUSE_LAST)) {
+//                Point where = event.getScreenPos();
+//
+//                if (src != underCursor) {
+//                    if (underCursor != null) {
+//                        mouseEvent(underCursor, MouseEvent.MOUSE_EXITED, where,
+//                                event);
+//                    }
+//                    underCursor = src;
+//                    if (underCursor != null) {
+//                        mouseEvent(underCursor, MouseEvent.MOUSE_ENTERED,
+//                                where, event);
+//                        underCursor.setDefaultCursor();
+//                    }
+//                }
+//                if (id == MouseEvent.MOUSE_EXITED) {
+//                    underCursor = null;
+//                }
+//
+//                if ((activePopup == null) && (src == null || !src.isMenuBar())) {
+//                    return false;
+//                }
+//
+//                if (id == MouseEvent.MOUSE_PRESSED) {
+//                    src = grab.mousePressed(src, where);
+//                } else if (id == MouseEvent.MOUSE_RELEASED) {
+//                    src = grab.mouseReleased(src, where);
+//                } else if (src == null) {
+//                    src = grab.getOwner();
+//                }
+//
+//                PopupBox wasActive = activePopup;
+//
+//                if (src != null) {
+//                    mouseEvent(src, id, where, event);
+//                    return src.isMenu() || src.contains(where);
+//                }
+//
+//                if (wasActive != null && activePopup == null) {
+//                    return wasActive.isMenu();
+//                }
+//
+//                if ((id == MouseEvent.MOUSE_PRESSED)
+//                        || (id == MouseEvent.MOUSE_RELEASED)) {
+//                    boolean isMenu = activePopup.isMenu();
+//                    deactivateAll();
+//                    return !isMenu;
+//                }
+//                return true;
+//            }
+//
+//            if (activePopup == null) {
+//                return false;
+//            }
+//
+//            if ((id >= KeyEvent.KEY_FIRST) && (id <= KeyEvent.KEY_LAST)) {
+//                boolean isMenu = activePopup.isMenu();
+//                activePopup.dispatchKeyEvent(id, event.getVKey(), event
+//                        .getTime(), event.getInputModifiers());
+//
+//                return isMenu;
+//            }
+//
+//            return false;
+//        }
+//
+//        /**
+//         * Remember the pop-up as active and grab the mouse on it
+//         * @param popup - the pop-up box to activate
+//         */
+//        void activate(final PopupBox popup) {
+//            if (activePopup == null) {
+//
+//                activePopup = popup;
+//                mouseGrabManager.startGrab(popup.getOwner(), new Runnable() {
+//                    public void run() {
+//                        deactivate(popup);
+//                    }
+//                });
+//            }
+//        }
+//
+//        /**
+//         * Deactivate the currently active pop-up box
+//         */
+//        void deactivateAll() {
+//            deactivate(activePopup);
+//        }
+//
+//        /**
+//         * Deactivate the pop-up box, end the mouse grab
+//         */
+//        void deactivate(PopupBox popup) {
+//            grab.reset();
+//
+//            if (activePopup != null && activePopup == popup) {
+//                activePopup = null;
+//                mouseGrabManager.endGrab();
+//                popup.hide();
+//                underCursor = null;
+//            }
+//        }
+//
+//        /**
+//         * Check that the pop-up box is currently active
+//         * @param popup - the pop-up box to check
+//         * @return - true if active
+//         */
+//        boolean isActive(PopupBox popup) {
+//            return (popup == activePopup) && (popup != null);
+//        }
+//    }
+
+}
\ No newline at end of file
diff --git a/awt/java/awt/DisplayMode.java b/awt/java/awt/DisplayMode.java
new file mode 100644
index 0000000..082c7b8
--- /dev/null
+++ b/awt/java/awt/DisplayMode.java
@@ -0,0 +1,147 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Alexey A. Petrenko
+ * @version $Revision$
+ */
+package java.awt;
+
+/**
+ * The DisplayMode class containes the bit depth, height, width and 
+ * refresh rate of a GraphicsDevice.
+ */
+public final class DisplayMode {
+    
+    /** The width. */
+    private final int width;
+
+    /** The height. */
+    private final int height;
+
+    /** The bit depth. */
+    private final int bitDepth;
+
+    /** The refresh rate. */
+    private final int refreshRate;
+
+   /** The Constant Value BIT_DEPTH_MULTI indicates the bit depth */
+
+    public static final int BIT_DEPTH_MULTI = -1;
+
+    /** The Constant REFRESH_RATE_UNKNOWN indicates the refresh rate. */
+    public static final int REFRESH_RATE_UNKNOWN = 0;
+
+   /**
+    * Creates a new DisplayMode object with the specified parameters.
+    *  
+    * @param width the width of the display.
+    * @param height the height of the display.
+    * @param bitDepth the bit depth of the display.
+    * @param refreshRate the refresh rate of the display.
+    */
+
+    public DisplayMode(int width, int height, int bitDepth, int refreshRate) {
+        this.width = width;
+        this.height = height;
+        this.bitDepth = bitDepth;
+        this.refreshRate = refreshRate;
+    }
+
+
+   /**
+    * Compares if this DisplayMode is equal to the specified object or not.
+    * 
+    * @param dm the Object to be compared.
+    * 
+    * @return true, if the specified object is a DisplayMode with the same
+    * data values as this DisplayMode, false otherwise.
+    */
+
+    @Override
+    public boolean equals(Object dm) {
+        if (dm instanceof DisplayMode) {
+            return equals((DisplayMode)dm);
+        }
+        return false;
+    }
+
+    /**
+    * Compares if this DisplayMode is equal to the specified DisplayMode object
+    * or not.
+    * 
+    * @param dm the DisplayMode to be compared.
+    * 
+    * @return true, if all of the data values of this DisplayMode are equal 
+    * to the values of the specified DisplayMode object, false otherwise.
+     */
+    public boolean equals(DisplayMode dm) {
+        if (dm == null) {
+            return false;
+        }
+        if (dm.bitDepth != bitDepth) {
+            return false;
+        }
+        if (dm.refreshRate != refreshRate) {
+            return false;
+        }
+        if (dm.width != width) {
+            return false;
+        }
+        if (dm.height != height) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Gets the bit depth of the DisplayMode, returns BIT_DEPTH_MULTI value
+     * if multiple bit depths are supported in this display mode.
+     * 
+     * @return the bit depth of the DisplayMode.
+     */
+    public int getBitDepth() {
+        return bitDepth;
+    }
+
+    /**
+     * Gets the height of the DisplayMode.
+     * 
+     * @return the height of the DisplayMode.
+     */
+    public int getHeight() {
+        return height;
+    }
+
+    /**
+     * Gets the refresh rate of the DisplayMode, returns REFRESH_RATE_UNKNOWN
+     * value if the information is not available.
+     * 
+     * @return the refresh rate of the DisplayMode.
+     */
+    public int getRefreshRate() {
+        return refreshRate;
+    }
+
+    /**
+     * Gets the width of the DisplayMode.
+     * 
+     * @return the width of the DisplayMode.
+     */
+    public int getWidth() {
+        return width;
+    }
+}
diff --git a/awt/java/awt/Event.java b/awt/java/awt/Event.java
new file mode 100644
index 0000000..f074258
--- /dev/null
+++ b/awt/java/awt/Event.java
@@ -0,0 +1,479 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Dmitry A. Durnev
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.io.Serializable;
+
+/**
+ * The Event Class is obsolete and has been replaced by AWTEvent class.
+ * 
+ */
+public class Event implements Serializable {
+    
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = 5488922509400504703L;
+    
+    /** 
+     * The Constant SHIFT_MASK indicates that the Shift key is down when 
+     * the event occurred.
+     */
+    public static final int SHIFT_MASK = 1;
+
+    /** 
+     * The Constant CTRL_MASK indicates that the Control key is down when 
+     * the event occurred.
+     */
+    public static final int CTRL_MASK = 2;
+
+    /** The Constant META_MASK indicates that the Meta key is down when t
+     * he event occurred (or the right mouse button). */
+    public static final int META_MASK = 4;
+
+    /** 
+     * The Constant ALT_MASK indicates that the Alt key is down when 
+     * the event occurred (or the middle mouse button). 
+     */
+    public static final int ALT_MASK = 8;
+
+    /** The Constant HOME indicates Home key. */
+    public static final int HOME = 1000;
+
+    /** The Constant END indicates End key. */
+    public static final int END = 1001;
+
+    /** The Constant PGUP indicates Page Up key. */
+    public static final int PGUP = 1002;
+
+    /** The Constant PGDN indicates Page Down key. */
+    public static final int PGDN = 1003;
+
+    /** The Constant UP indicates Up key. */
+    public static final int UP = 1004;
+
+    /** The Constant DOWN indicates Down key. */
+    public static final int DOWN = 1005;
+
+    /** The Constant LEFT indicates Left key. */
+    public static final int LEFT = 1006;
+
+    /** The Constant RIGHT indicates Right key. */
+    public static final int RIGHT = 1007;
+
+    /** The Constant F1 indicates F1 key. */
+    public static final int F1 = 1008;
+
+    /** The Constant F2 indicates F2 key. */
+    public static final int F2 = 1009;
+
+    /** The Constant F3 indicates F3 key. */
+    public static final int F3 = 1010;
+
+    /** The Constant F4 indicates F4 key. */
+    public static final int F4 = 1011;
+
+    /** The Constant F5 indicates F5 key. */
+    public static final int F5 = 1012;
+
+    /** The Constant F6 indicates F6 key. */
+    public static final int F6 = 1013;
+
+    /** The Constant F7 indicates F7 key. */
+    public static final int F7 = 1014;
+
+    /** The Constant F8 indicates F8 key. */
+    public static final int F8 = 1015;
+
+    /** The Constant F9 indicates F9 key. */
+    public static final int F9 = 1016;
+
+    /** The Constant F10 indicates F10 key. */
+    public static final int F10 = 1017;
+
+    /** The Constant F11 indicates F11 key. */
+    public static final int F11 = 1018;
+
+    /** The Constant F12 indicates F12 key. */
+    public static final int F12 = 1019;
+
+    /** The Constant PRINT_SCREEN  indicates Print Screen key. */
+    public static final int PRINT_SCREEN = 1020;
+
+    /** The Constant SCROLL_LOCK indicates Scroll Lock key. */
+    public static final int SCROLL_LOCK = 1021;
+
+    /** The Constant CAPS_LOCK indicates Caps Lock key. */
+    public static final int CAPS_LOCK = 1022;
+
+    /** The Constant NUM_LOCK indicates Num Lock key. */
+    public static final int NUM_LOCK = 1023;
+
+    /** The Constant PAUSE indicates Pause key. */
+    public static final int PAUSE = 1024;
+
+    /** The Constant INSERT indicates Insert key. */
+    public static final int INSERT = 1025;
+
+    /** The Constant ENTER indicates Enter key. */
+    public static final int ENTER = 10;
+
+    /** The Constant BACK_SPACE indicates Back Space key. */
+    public static final int BACK_SPACE = 8;
+
+    /** The Constant TAB indicates TAb key. */
+    public static final int TAB = 9;
+
+    /** The Constant ESCAPE indicates Escape key. */
+    public static final int ESCAPE = 27;
+
+    /** The Constant DELETE indicates Delete key. */
+    public static final int DELETE = 127;
+
+    /** 
+     * The Constant WINDOW_DESTROY indicates an event when the user has asked the
+     * window manager to kill the window.
+     */
+    public static final int WINDOW_DESTROY = 201;
+
+    /** 
+     * The Constant WINDOW_EXPOSE indicates an event when the user has asked the
+     * window manager to expose the window.
+     */
+    public static final int WINDOW_EXPOSE = 202;
+
+    /** 
+     * The Constant WINDOW_ICONIFY indicates an event when the user has asked the
+     * window manager to inconify the window.
+     */
+    public static final int WINDOW_ICONIFY = 203;
+
+    /** 
+     * The Constant WINDOW_DEICONIFY indicates an event when the user has asked the
+     * window manager to deinconify the window. 
+     */
+    public static final int WINDOW_DEICONIFY = 204;
+
+    /** 
+     * The Constant WINDOW_MOVED indicates an event when the user has asked the
+     * window manager to move the window. 
+     */
+    public static final int WINDOW_MOVED = 205;
+
+    /** 
+     * The Constant KEY_PRESS indicates an event when the user presses 
+     * a normal key. 
+     */
+    public static final int KEY_PRESS = 401;
+
+    /** 
+     * The Constant KEY_RELEASE indicates an event when the user releases 
+     * a normal key.
+     */
+    public static final int KEY_RELEASE = 402;
+
+    /** 
+     * The Constant KEY_ACTION indicates an event when the user pressed 
+     * a non-ASCII action key. 
+     */
+    public static final int KEY_ACTION = 403;
+
+    /**
+     * The Constant KEY_ACTION_RELEASE indicates an event when the user released 
+     * a non-ASCII action key. 
+     */
+    public static final int KEY_ACTION_RELEASE = 404;
+
+    /** 
+     * The Constant MOUSE_DOWN indicates an event when the user has pressed 
+     * the mouse button. 
+     */
+    public static final int MOUSE_DOWN = 501;
+
+    /** 
+     * The Constant MOUSE_UP indicates an event when the user has released 
+     * the mouse button. 
+     */
+    public static final int MOUSE_UP = 502;
+
+    /** 
+     * The Constant MOUSE_MOVE indicates an event when the user has moved
+     * the mouse with no button pressed.
+     */
+    public static final int MOUSE_MOVE = 503;
+
+    /** 
+     * The Constant MOUSE_ENTER indicates an event when the mouse
+     * has entered a component.
+     */
+    public static final int MOUSE_ENTER = 504;
+
+    /** 
+     * The Constant MOUSE_EXIT indicates an event when the mouse
+     * has exited a component. 
+     */
+    public static final int MOUSE_EXIT = 505;
+
+    /** The Constant MOUSE_DRAG indicates an event when the user
+     * has moved a mouse with the pressed button. 
+     */
+    public static final int MOUSE_DRAG = 506;
+
+    /** 
+     * The Constant SCROLL_LINE_UP indicates an event when the user has
+     * activated line-up area of scrollbar.
+     */
+    public static final int SCROLL_LINE_UP = 601;
+
+    /**
+     * The Constant SCROLL_LINE_DOWN indicates an event when the user has
+     * activated line-down area of scrollbar. 
+     */
+    public static final int SCROLL_LINE_DOWN = 602;
+
+    /**
+     * The Constant SCROLL_PAGE_UP indicates an event when the user has
+     * activated page up area of scrollbar. 
+     */
+    public static final int SCROLL_PAGE_UP = 603;
+
+    /**
+     * The Constant SCROLL_PAGE_DOWN indicates an event when the user has
+     * activated page down area of scrollbar. 
+     */
+    public static final int SCROLL_PAGE_DOWN = 604;
+
+    /**
+     * The Constant SCROLL_ABSOLUTE indicates an event when the user 
+     * has moved the bubble in a scroll bar. 
+     */
+    public static final int SCROLL_ABSOLUTE = 605;
+
+    /** The Constant SCROLL_BEGIN indicates a scroll begin event. */
+    public static final int SCROLL_BEGIN = 606;
+
+    /** The Constant SCROLL_END indicates a scroll end event. */
+    public static final int SCROLL_END = 607;
+
+    /** 
+     * The Constant LIST_SELECT indicates that an item in a list 
+     * has been selected.
+     */
+    public static final int LIST_SELECT = 701;
+
+    /** 
+     * The Constant LIST_DESELECT indicates that an item in a list 
+     * has been deselected. 
+     */
+    public static final int LIST_DESELECT = 702;
+
+    /** 
+     * The Constant ACTION_EVENT indicates that the user wants some 
+     * action to occur.
+     */
+    public static final int ACTION_EVENT = 1001;
+
+    /** The Constant LOAD_FILE indicates a file loading event. */
+    public static final int LOAD_FILE = 1002;
+
+    /** The Constant SAVE_FILE indicates a file saving event. */
+    public static final int SAVE_FILE = 1003;
+
+    /** The Constant GOT_FOCUS indicates that a component got the focus. */
+    public static final int GOT_FOCUS = 1004;
+
+    /** The Constant LOST_FOCUS indicates that the component lost the focus. */
+    public static final int LOST_FOCUS = 1005;
+
+    /** The target is the component with which the event is associated. */
+    public Object target;
+
+    /** The when is timestamp when event has occured. */
+    public long when;
+
+    /** The id indicates the type of the event. */
+    public int id;
+
+    /** The x coordinate of event. */
+    public int x;
+
+    /** The y coordinate of event. */
+    public int y;
+
+    /** The key code of key event. */
+    public int key;
+
+    /** The state of the modifier keys (given by a bitmask). */
+    public int modifiers;
+
+    /** The click count indicates the number of consecutive clicks. */
+    public int clickCount;
+
+    /** The argument of the event. */
+    public Object arg;
+
+    /** The next event. */
+    public Event evt;
+
+    /**
+     * Instantiates a new event with the specified target component, 
+     * event type, and argument.
+     * 
+     * @param target the target component.
+     * @param id the event type.
+     * @param arg the argument.
+     */
+    public Event(Object target, int id, Object arg) {
+        this(target, 0l, id, 0, 0, 0, 0, arg);
+    }
+
+    /**
+     * Instantiates a new event with the specified target component, time stamp,
+     * event type, x and y coordinates, keyboard key, state of the modifier
+     * keys, and an argument set to null.
+     * 
+     * @param target the target component.
+     * @param when the time stamp.
+     * @param id the event type.
+     * @param x the x coordinate.
+     * @param y the y coordinate.
+     * @param key the key.
+     * @param modifiers the modifier keys state.
+     */
+    public Event(Object target, long when, int id, int x, int y, int key, int modifiers) {
+        this(target, when, id, x, y, key, modifiers, null);
+    }
+
+    /**
+     * Instantiates a new event with the specified target component, time stamp,
+     * event type, x and y coordinates, keyboard key, state of the modifier
+     * keys, and an argument.
+     * 
+     * @param target the target component.
+     * @param when the time stamp.
+     * @param id the event type.
+     * @param x the x coordinate.
+     * @param y the y coordinate.
+     * @param key the key.
+     * @param modifiers the modifier keys state.
+     * @param arg the specified argument.
+     */
+    public Event(Object target, long when, int id, int x, int y, int key, int modifiers, Object arg) {
+        this.target = target;
+        this.when = when;
+        this.id = id;
+        this.x = x;
+        this.y = y;
+        this.key = key;
+        this.modifiers = modifiers;
+        this.arg = arg;
+    }
+
+    /**
+     * Returns a string representation of this Event.
+     * 
+     * @return a string representation of this Event.
+     */
+    @Override
+    public String toString() {
+        /* The format is based on 1.5 release behavior 
+         * which can be revealed by the following code:
+         * 
+         * Event e = new Event(new Button(), 0l, Event.KEY_PRESS, 
+         *                     0, 0, Event.TAB, Event.SHIFT_MASK, "arg");
+         * System.out.println(e);
+         */
+
+        return getClass().getName() + "[" + paramString() + "]"; //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Returns a string representing the state of this Event.
+     * 
+     * @return a string representing the state of this Event.
+     */
+    protected String paramString() {
+        return "id=" + id + ",x=" + x + ",y=" + y + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+        (key != 0 ? ",key=" + key  + getModifiersString() : "") + //$NON-NLS-1$ //$NON-NLS-2$
+        ",target=" + target + //$NON-NLS-1$
+        (arg != null ? ",arg=" + arg : ""); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Gets a string representation of the modifiers.
+     * 
+     * @return a string representation of the modifiers
+     */
+    private String getModifiersString() {
+        String strMod = ""; //$NON-NLS-1$
+        if (shiftDown()) {
+            strMod += ",shift"; //$NON-NLS-1$
+        }
+        if (controlDown()) {
+            strMod += ",control"; //$NON-NLS-1$
+        }
+        if (metaDown()) {
+            strMod += ",meta"; //$NON-NLS-1$
+        }
+        return strMod;
+    }
+
+    /**
+     * Translates x and y coordinates of his event to the x+dx and x+dy 
+     * coordinates.
+     * 
+     * @param dx the dx - the distance by which the event's x coordinate
+     * is increased 
+     * @param dy the dy - the distance by which the event's y coordinate
+     * is increased 
+     */
+    public void translate(int dx, int dy) {
+        x += dx;
+        y += dy;
+    }
+
+    /**
+     * Checks if Control key is down or not.
+     * 
+     * @return true, if Control key is down; false otherwise.
+     */
+    public boolean controlDown() {
+        return (modifiers & CTRL_MASK) != 0;
+    }
+
+    /**
+     * Checks if Meta key is down or not.
+     * 
+     * @return true, if Meta key is down; false otherwise.
+     */
+    public boolean metaDown() {
+        return (modifiers & META_MASK) != 0;
+    }
+
+    /**
+     * Checks if Shift key is down or not.
+     * 
+     * @return true, if Shift key is down; false otherwise.
+     */
+    public boolean shiftDown() {
+        return (modifiers & SHIFT_MASK) != 0;
+    }
+
+}
+
diff --git a/awt/java/awt/EventDispatchThread.java b/awt/java/awt/EventDispatchThread.java
new file mode 100644
index 0000000..442c8a2
--- /dev/null
+++ b/awt/java/awt/EventDispatchThread.java
@@ -0,0 +1,118 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov, Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt;
+
+import org.apache.harmony.awt.wtk.NativeEvent;
+import org.apache.harmony.awt.wtk.NativeEventQueue;
+
+class EventDispatchThread extends Thread  {
+    
+    private static final class MarkerEvent extends AWTEvent {
+        MarkerEvent(Object source, int id) {
+            super(source, id);
+        }
+    }
+
+    final Dispatcher dispatcher;
+    final Toolkit toolkit;
+    private NativeEventQueue nativeQueue;
+
+    protected volatile boolean shutdownPending = false;
+
+    /**
+     * Initialise and run the main event loop
+     */
+    @Override
+    public void run() {
+        nativeQueue = toolkit.getNativeEventQueue();
+
+        try {
+            runModalLoop(null);
+        } finally {
+            toolkit.shutdownWatchdog.forceShutdown();
+        }
+    }
+
+    void runModalLoop(ModalContext context) {
+        long lastPaintTime = System.currentTimeMillis();
+        while (!shutdownPending && (context == null || context.isModalLoopRunning())) {
+            try {
+            EventQueue eventQueue = toolkit.getSystemEventQueueImpl();
+
+            NativeEvent ne = nativeQueue.getNextEvent();
+            if (ne != null) {
+                dispatcher.onEvent(ne);
+                MarkerEvent marker = new MarkerEvent(this, 0);
+                eventQueue.postEvent(marker);
+                for (AWTEvent ae = eventQueue.getNextEventNoWait(); 
+                        (ae != null) && (ae != marker); 
+                        ae = eventQueue.getNextEventNoWait()) {
+                    eventQueue.dispatchEvent(ae);
+                }
+            } else {
+                toolkit.shutdownWatchdog.setNativeQueueEmpty(true);
+                AWTEvent ae = eventQueue.getNextEventNoWait();
+                if (ae != null) {
+                    eventQueue.dispatchEvent(ae);
+                    long curTime = System.currentTimeMillis();
+                    if (curTime - lastPaintTime > 10) {
+                        toolkit.onQueueEmpty();
+                        lastPaintTime = System.currentTimeMillis();
+                    }
+                } else {
+                    toolkit.shutdownWatchdog.setAwtQueueEmpty(true);
+                    toolkit.onQueueEmpty();
+                    lastPaintTime = System.currentTimeMillis();
+                    waitForAnyEvent();
+                }
+            }
+            } catch (Throwable t) {
+                // TODO: Exception handler should be implemented
+                // t.printStackTrace();
+            }
+        }
+    }
+    
+    private void waitForAnyEvent() {
+        EventQueue eventQueue = toolkit.getSystemEventQueueImpl();
+        if (!eventQueue.isEmpty() || !nativeQueue.isEmpty()) {
+            return;
+        }
+        Object eventMonitor = nativeQueue.getEventMonitor();
+        synchronized(eventMonitor) {
+            try {
+                eventMonitor.wait();
+            } catch (InterruptedException e) {}
+        }
+    }
+
+    void shutdown() {
+        shutdownPending = true;
+    }
+
+    EventDispatchThread(Toolkit toolkit, Dispatcher dispatcher ) {
+        this.toolkit = toolkit;
+        this.dispatcher = dispatcher;
+        setName("AWT-EventDispatchThread"); //$NON-NLS-1$
+        setDaemon(true);
+    }
+
+}
diff --git a/awt/java/awt/EventQueue.java b/awt/java/awt/EventQueue.java
new file mode 100644
index 0000000..3997546
--- /dev/null
+++ b/awt/java/awt/EventQueue.java
@@ -0,0 +1,310 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov, Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.awt.event.InvocationEvent;
+import java.lang.reflect.InvocationTargetException;
+import java.util.EmptyStackException;
+
+/**
+ * The EventQueue class manages events. It is a platform-independent class 
+ * that queues events both from the underlying peer classes and from trusted 
+ * application classes.
+ */
+public class EventQueue {
+    
+    /** The core ref. */
+    private final EventQueueCoreAtomicReference coreRef = 
+            new EventQueueCoreAtomicReference();
+    
+    /**
+     * The Class EventQueueCoreAtomicReference.
+     */
+    private static final class EventQueueCoreAtomicReference {
+        
+        /** The core. */
+        private EventQueueCore core;
+
+        /*synchronized*/ /**
+         * Gets the.
+         * 
+         * @return the event queue core
+         */
+        EventQueueCore get() { 
+            return core;
+        }
+
+        /*synchronized*/ /**
+         * Sets the.
+         * 
+         * @param newCore the new core
+         */
+        void set(EventQueueCore newCore) { 
+            core = newCore;
+        }
+    }
+
+    /**
+     * Returns true if the calling thread is the current 
+     * AWT EventQueue's dispatch thread. 
+     * 
+     * @return true, if the calling thread is the current 
+     * AWT EventQueue's dispatch thread; false otherwise.
+     */
+    public static boolean isDispatchThread() {
+        return Thread.currentThread() instanceof EventDispatchThread;
+    }
+
+    /**
+     * Posts an InvocationEvent which executes the run() method on a Runnable 
+     * when dispatched by the AWT event dispatcher thread.
+     * 
+     * @param runnable the Runnable whose run method should be executed 
+     * synchronously on the EventQueue.
+     */
+    public static void invokeLater(Runnable runnable) {
+        Toolkit toolkit = Toolkit.getDefaultToolkit();
+        InvocationEvent event = new InvocationEvent(toolkit, runnable);
+        toolkit.getSystemEventQueueImpl().postEvent(event);
+    }
+
+    /**
+     * Posts an InvocationEvent which executes the run() method on a Runnable 
+     * when dispatched by the AWT event dispatcher thread and the 
+     * notifyAll method is called on it immediately after run returns.
+     * 
+     * @param runnable the Runnable whose run method should be executed 
+     * synchronously on the EventQueue.
+     * 
+     * @throws InterruptedException if another thread has interrupted 
+     * this thread.
+     * @throws InvocationTargetException if a throwable is thrown 
+     * when running the runnable. 
+     */
+    public static void invokeAndWait(Runnable runnable)
+            throws InterruptedException, InvocationTargetException {
+
+        if (isDispatchThread()) {
+            throw new Error();
+        }
+
+        final Toolkit toolkit = Toolkit.getDefaultToolkit();
+        final Object notifier = new Object();  //$NON-LOCK-1$
+        InvocationEvent event = new InvocationEvent(
+                toolkit, runnable, notifier, true);
+
+        synchronized (notifier) {
+            toolkit.getSystemEventQueueImpl().postEvent(event);
+            notifier.wait();
+        }
+
+        Exception exception = event.getException();
+
+        if (exception != null) {
+            throw new InvocationTargetException(exception);
+        }
+    }
+
+    /**
+     * Gets the system event queue.
+     * 
+     * @return the system event queue
+     */
+    private static EventQueue getSystemEventQueue() {
+        Thread th = Thread.currentThread();
+        if (th instanceof EventDispatchThread) {
+            return ((EventDispatchThread)th).toolkit.getSystemEventQueueImpl();
+        }
+        return null;
+    }
+    
+    /**
+     * Gets the most recent event's timestamp.
+     * This event was dispatched from the EventQueue associated with the 
+     * calling thread.
+     * 
+     * @return the timestamp of the last Event to be dispatched, 
+     * or System.currentTimeMillis() if this method is invoked from 
+     * a thread other than an event-dispatching thread.
+     */
+    public static long getMostRecentEventTime() {
+        EventQueue eq = getSystemEventQueue();
+        return (eq != null) ? 
+                eq.getMostRecentEventTimeImpl() : System.currentTimeMillis();
+    }
+    
+    /**
+     * Gets the most recent event time impl.
+     * 
+     * @return the most recent event time impl
+     */
+    private long getMostRecentEventTimeImpl() {
+        return getCore().getMostRecentEventTime();
+    }
+
+    /**
+     * Returns the the currently dispatched event by the EventQueue 
+     * associated with the calling thread.
+     * 
+     * @return the currently dispatched event or null if this method 
+     * is invoked from a thread other than an event-dispatching thread.
+     */
+    public static AWTEvent getCurrentEvent() {
+        EventQueue eq = getSystemEventQueue();
+        return (eq != null) ? 
+                eq.getCurrentEventImpl() : null;
+    }
+
+    /**
+     * Gets the current event impl.
+     * 
+     * @return the current event impl
+     */
+    private AWTEvent getCurrentEventImpl() {
+        return getCore().getCurrentEvent();
+    }
+
+    /**
+     * Instantiates a new event queue.
+     */
+    public EventQueue() {
+        setCore(new EventQueueCore(this));
+    }
+
+    /**
+     * Instantiates a new event queue.
+     * 
+     * @param t the t
+     */
+    EventQueue(Toolkit t) {
+        setCore(new EventQueueCore(this, t));
+    }
+
+    /**
+     * Posts a event to the EventQueue.
+     * 
+     * @param event AWTEvent.
+     */
+    public void postEvent(AWTEvent event) {
+        event.isPosted = true;
+        getCore().postEvent(event);
+    }
+
+    /**
+     * Returns an event from the EventQueue and removes it from this queue. 
+     *  
+     * @return the next AWTEvent.
+     * 
+     * @throws InterruptedException is thrown if another thread 
+     * interrupts this thread.
+     */
+    public AWTEvent getNextEvent() throws InterruptedException {
+        return getCore().getNextEvent();
+    }
+    
+    /**
+     * Gets the next event no wait.
+     * 
+     * @return the next event no wait
+     */
+    AWTEvent getNextEventNoWait() {
+        return getCore().getNextEventNoWait();
+    }
+
+    /**
+     * Returns the first event of the EventQueue (without removing it 
+     * from the queue).
+     * 
+     * @return the the first AWT event of the EventQueue.
+     */
+    public AWTEvent peekEvent() {
+        return getCore().peekEvent();
+    }
+
+    /**
+     * Returns the first event of the EventQueue with the specified ID
+     * (without removing it from the queue).
+     * 
+     * @param id the type ID of event.
+     * 
+     * @return the first event of the EventQueue with the specified ID.
+     */
+    public AWTEvent peekEvent(int id) {
+        return getCore().peekEvent(id);
+    }
+
+    /**
+     * Replaces the existing EventQueue with the specified EventQueue. 
+     * Any pending events are transferred to the new EventQueue. 
+     * 
+     * @param newEventQueue the new event queue.
+     */
+    public void push(EventQueue newEventQueue) {
+        getCore().push(newEventQueue);
+    }
+    
+    /**
+     * Stops dispatching events using this EventQueue. 
+     * Any pending events are transferred to the previous EventQueue.
+     * 
+     * @throws EmptyStackException is thrown if no previous push 
+     * was made on this EventQueue.
+     */
+    protected void pop() throws EmptyStackException {
+        getCore().pop();
+    }
+
+    /**
+     * Dispatches the specified event.
+     * 
+     * @param event the AWTEvent.
+     */
+    protected void dispatchEvent(AWTEvent event) {
+        getCore().dispatchEventImpl(event);
+    }
+
+    /**
+     * Checks if the queue is empty.
+     * 
+     * @return true, if is empty
+     */
+    boolean isEmpty() {
+        return getCore().isEmpty();
+    }
+
+    /**
+     * Gets the core.
+     * 
+     * @return the core
+     */
+    EventQueueCore getCore() {
+        return coreRef.get();
+    }
+    
+    /**
+     * Sets the core.
+     * 
+     * @param newCore the new core
+     */
+    void setCore(EventQueueCore newCore) {
+        coreRef.set((newCore != null) ? newCore : new EventQueueCore(this));
+    }
+}
diff --git a/awt/java/awt/EventQueueCore.java b/awt/java/awt/EventQueueCore.java
new file mode 100644
index 0000000..ffc7c46
--- /dev/null
+++ b/awt/java/awt/EventQueueCore.java
@@ -0,0 +1,253 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/** 
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.InputEvent;
+import java.awt.event.InputMethodEvent;
+import java.awt.event.InvocationEvent;
+import java.awt.event.MouseEvent;
+import java.util.LinkedList;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The events storage for EventQueue
+ */
+final class EventQueueCore {
+    
+    private final LinkedList<EventQueue> queueStack = new LinkedList<EventQueue>();
+    private final LinkedList<AWTEvent> events = new LinkedList<AWTEvent>();
+    
+    private Toolkit toolkit;
+    private EventQueue activeQueue;
+    private Thread dispatchThread;
+    
+    AWTEvent currentEvent;
+    long mostRecentEventTime = System.currentTimeMillis();
+    
+    EventQueueCore(EventQueue eq) {
+        synchronized (this) {
+            queueStack.addLast(eq);
+            activeQueue = eq;
+        }
+    }
+
+    EventQueueCore(EventQueue eq, Toolkit t) {
+        synchronized (this) {
+            queueStack.addLast(eq);
+            activeQueue = eq;
+            setToolkit(t);
+        }
+    }
+
+    synchronized long getMostRecentEventTime() {
+        return mostRecentEventTime;
+    }
+    
+    synchronized AWTEvent getCurrentEvent() {
+        return currentEvent;
+    }
+    
+    synchronized boolean isSystemEventQueue() {
+        return toolkit != null;
+    }
+    
+    private void setToolkit(Toolkit t) {
+        toolkit = t;
+        if (toolkit != null) {
+            toolkit.setSystemEventQueueCore(this);
+            dispatchThread = toolkit.dispatchThread;
+        }
+    }
+
+    synchronized void postEvent(AWTEvent event) {
+        //???AWT
+        /*
+        events.addLast(event);
+        if ((toolkit == null) && (dispatchThread == null)) {
+            dispatchThread = new EventQueueThread(this);
+            dispatchThread.start();
+        }
+        // TODO: add event coalescing
+        if (toolkit != null) {
+            toolkit.shutdownWatchdog.setAwtQueueEmpty(false);
+            if (!GraphicsEnvironment.getLocalGraphicsEnvironment().isHeadlessInstance()) {
+                notifyEventMonitor(toolkit);
+            }
+        }
+        notifyAll();
+        */
+    }
+    
+    void notifyEventMonitor(Toolkit t) {
+        Object em = t.getNativeEventQueue().getEventMonitor();
+        synchronized (em) {
+            em.notifyAll();
+        }
+    }
+    
+    synchronized AWTEvent getNextEvent() throws InterruptedException {
+        while (events.isEmpty()) {
+            wait();
+        }
+        AWTEvent event = events.removeFirst();
+        // TODO: add event coalescing
+        return event;
+    }    
+    
+    synchronized AWTEvent peekEvent() {
+        return events.isEmpty() ? null : events.getFirst();
+    }
+    
+    synchronized AWTEvent peekEvent(int id) {
+        for (AWTEvent event : events) {
+            if (event.getID() == id) {
+                return event;
+            }
+        }
+        return null;
+    }
+    
+    synchronized void dispatchEvent(AWTEvent event) {
+        updateCurrentEventAndTime(event);
+        try {
+            activeQueue.dispatchEvent(event);
+        } finally {
+            currentEvent = null;
+        }
+    }
+    
+    void dispatchEventImpl(AWTEvent event) {
+        if (event instanceof ActiveEvent) {
+            updateCurrentEventAndTime(event);
+            try {
+                ((ActiveEvent) event).dispatch();
+            } finally {
+                currentEvent = null;
+            }
+            return;
+        }
+
+        Object src = event.getSource();
+
+        if (src instanceof Component) {
+            if (preprocessComponentEvent(event)) {
+                ((Component) src).dispatchEvent(event);
+            }
+        } else {
+            if (toolkit != null) {
+                toolkit.dispatchAWTEvent(event);
+            }
+            if (src instanceof MenuComponent) {
+                ((MenuComponent) src).dispatchEvent(event);
+            }
+        }
+    }
+
+    private final boolean preprocessComponentEvent(AWTEvent event) {
+      if (event instanceof MouseEvent) {
+          return preprocessMouseEvent((MouseEvent)event);
+      }
+      return true;
+    }
+
+    private final boolean preprocessMouseEvent(MouseEvent event) {
+        //???AWT
+        /*
+      if (toolkit != null && toolkit.mouseEventPreprocessor != null) {
+          toolkit.lockAWT();
+          try {
+              return toolkit.mouseEventPreprocessor.preprocess(event);
+          } finally {
+              toolkit.unlockAWT();
+          }
+      }
+      return true;
+        */
+        return true;
+    }
+    
+    private void updateCurrentEventAndTime(AWTEvent event) {
+        currentEvent = event;
+        long when = 0;
+        if (event instanceof ActionEvent) {
+            when = ((ActionEvent) event).getWhen();
+        } else if (event instanceof InputEvent) {
+            when = ((InputEvent) event).getWhen();
+        } else if (event instanceof InputMethodEvent) {
+            when = ((InputMethodEvent) event).getWhen();
+        } else if (event instanceof InvocationEvent) {
+            when = ((InvocationEvent) event).getWhen();
+        }
+        if (when != 0) {
+            mostRecentEventTime = when;
+        }
+    }
+    
+    synchronized void push(EventQueue newEventQueue) {
+        // TODO: handle incorrect situations
+        if (queueStack.isEmpty()) {
+            // awt.6B=Queue stack is empty
+            throw new IllegalStateException(Messages.getString("awt.6B")); //$NON-NLS-1$
+        }
+        
+        queueStack.addLast(newEventQueue);
+        activeQueue = newEventQueue;
+        activeQueue.setCore(this);
+    }
+    
+    synchronized void pop() {
+        EventQueue removed = queueStack.removeLast();
+        if (removed != activeQueue) {
+            // awt.6C=Event queue stack is broken
+            throw new IllegalStateException(Messages.getString("awt.6C")); //$NON-NLS-1$
+        }
+        activeQueue = queueStack.getLast();
+        removed.setCore(null);
+    }
+
+    synchronized AWTEvent getNextEventNoWait() {
+        try {
+            return events.isEmpty() ? null : activeQueue.getNextEvent();
+        } catch (InterruptedException e) {
+            return null;
+        }
+    }
+
+    synchronized boolean isEmpty() {
+        return (currentEvent == null) && events.isEmpty();
+    }
+    
+    synchronized boolean isEmpty(long timeout) {
+        if (!isEmpty()) {
+            return false;
+        }
+        try {
+            wait(timeout);
+        } catch (InterruptedException e) {}
+        return isEmpty();
+    }
+    
+    synchronized EventQueue getActiveEventQueue() {
+        return activeQueue;
+    }
+}
diff --git a/awt/java/awt/Font.java b/awt/java/awt/Font.java
new file mode 100644
index 0000000..139ae68
--- /dev/null
+++ b/awt/java/awt/Font.java
@@ -0,0 +1,1500 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package java.awt;
+
+import com.android.internal.awt.AndroidGraphics2D;
+
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.font.LineMetrics;
+import java.awt.font.TextAttribute;
+import java.awt.font.TransformAttribute;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.BufferedInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.text.CharacterIterator;
+import java.text.AttributedCharacterIterator.Attribute;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import org.apache.harmony.awt.gl.font.AndroidGlyphVector;
+import org.apache.harmony.awt.gl.font.CommonGlyphVector;
+import org.apache.harmony.awt.gl.font.FontPeerImpl;
+import org.apache.harmony.awt.gl.font.FontMetricsImpl;
+import org.apache.harmony.awt.gl.font.LineMetricsImpl;
+import org.apache.harmony.awt.internal.nls.Messages;
+import org.apache.harmony.misc.HashCode;
+
+
+/**
+ * The Font class represents fonts for rendering text. 
+ * This class allow to map characters to glyphs.
+ * <p> 
+ * A glyph is a shape used to render a character or a sequence of 
+ * characters. For example one character of Latin writing system 
+ * represented by one glyth, but in complex writing system such as 
+ * South and South-East Asian there is more complicated correspondence 
+ * between characters and glyphs.
+ * <p>
+ * The Font object is identified by two types of names. The logical font name 
+ * is the name that is used to construct the font. The font name
+ * is the name of a particular font face (for example, Arial Bold). 
+ * The family name is the font's family name that specifies 
+ * the typographic design across several faces (for example, Arial). In 
+ * all the Font is identified by three attributes: the family name, 
+ * the style (such as bold or italic), and the size.
+ */
+public class Font implements Serializable {
+
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = -4206021311591459213L;
+
+    // Identity Transform attribute
+    /** The Constant IDENTITY_TRANSFORM. */
+    private static final TransformAttribute IDENTITY_TRANSFORM = new TransformAttribute(
+            new AffineTransform());
+
+    /** The Constant PLAIN indicates font's plain style. */
+    public static final int PLAIN = 0;
+
+    /** The Constant BOLD indicates font's bold style. */
+    public static final int BOLD = 1;
+
+    /** The Constant ITALIC indicates font's italic style. */
+    public static final int ITALIC = 2;
+
+    /** The Constant ROMAN_BASELINE indicated roman baseline. */
+    public static final int ROMAN_BASELINE = 0;
+
+    /** The Constant CENTER_BASELINE indicates center baseline. */
+    public static final int CENTER_BASELINE = 1;
+
+    /** The Constant HANGING_BASELINE indicates hanging baseline. */
+    public static final int HANGING_BASELINE = 2;
+
+    /** 
+     * The Constant TRUETYPE_FONT indicates a font resource of 
+     * type TRUETYPE. 
+     */
+    public static final int TRUETYPE_FONT = 0;
+
+    /** 
+     * The Constant TYPE1_FONT indicates a font resource of
+     * type TYPE1. 
+     */
+    public static final int TYPE1_FONT = 1;
+
+    /** 
+     * The Constant LAYOUT_LEFT_TO_RIGHT indicates that text is
+     * left to right. 
+     */
+    public static final int LAYOUT_LEFT_TO_RIGHT = 0;
+
+    /** 
+     * The Constant LAYOUT_RIGHT_TO_LEFT indicates that text is
+     * right to left. 
+     */
+    public static final int LAYOUT_RIGHT_TO_LEFT = 1;
+
+    /** 
+     * The Constant LAYOUT_NO_START_CONTEXT indicates that the text
+     * in the char array before the indicated start should not be examined. 
+     */
+    public static final int LAYOUT_NO_START_CONTEXT = 2;
+
+    /** The Constant LAYOUT_NO_LIMIT_CONTEXT indicates that text in 
+     * the char array after the indicated limit should not be examined. */
+    public static final int LAYOUT_NO_LIMIT_CONTEXT = 4;
+
+    /** The Constant DEFAULT_FONT. */
+    static final Font DEFAULT_FONT = new Font("Dialog", Font.PLAIN, 12); //$NON-NLS-1$
+
+    /** The name of the Font. */
+    protected String name;
+
+    /** The style of the Font. */
+    protected int style;
+
+    /** The size of the Font. */
+    protected int size;
+
+    /** The point size of the Font. */
+    protected float pointSize;
+
+    // Flag if the Font object transformed
+    /** The transformed. */
+    private boolean transformed;
+
+    // Set of font attributes
+    /** The requested attributes. */
+    private Hashtable<Attribute, Object> fRequestedAttributes;
+
+    // font peer object corresponding to this Font
+    /** The font peer. */
+    private transient FontPeerImpl fontPeer;
+
+    // number of glyphs in this Font
+    /** The num glyphs. */
+    private transient int numGlyphs = -1;
+
+    // code for missing glyph for this Font
+    /** The missing glyph code. */
+    private transient int missingGlyphCode = -1;
+
+    /**
+     * Writes object to ObjectOutputStream.
+     * 
+     * @param out ObjectOutputStream
+     * 
+     * @throws IOException Signals that an I/O exception has occurred.
+     */
+    private void writeObject(java.io.ObjectOutputStream out) throws IOException {
+        out.defaultWriteObject();
+    }
+
+    /**
+     * Reads object from ObjectInputStream object and set native platform
+     * dependent fields to default values.
+     * 
+     * @param in ObjectInputStream object
+     * 
+     * @throws IOException Signals that an I/O exception has occurred.
+     * @throws ClassNotFoundException the class not found exception
+     */
+    private void readObject(java.io.ObjectInputStream in) throws IOException,
+            ClassNotFoundException {
+        in.defaultReadObject();
+
+        numGlyphs = -1;
+        missingGlyphCode = -1;
+
+    }
+
+    /**
+     * Instantiates a new Font with the specified attributes. 
+     * The Font will be created with default attributes 
+     * if the attribute's parameter is null. 
+     * 
+     * @param attributes the attributes to be assigned to the new Font, or null.
+     */
+    public Font(Map<? extends Attribute, ?> attributes) {
+        Object currAttr;
+
+        // Default values are taken from the documentation of the Font class.
+        // See Font constructor, decode and getFont sections.
+
+        this.name = "default"; //$NON-NLS-1$
+        this.size = 12;
+        this.pointSize = 12;
+        this.style = Font.PLAIN;
+
+        if (attributes != null) {
+
+            fRequestedAttributes = new Hashtable<Attribute, Object>(attributes);
+
+            currAttr = attributes.get(TextAttribute.SIZE);
+            if (currAttr != null) {
+                this.pointSize = ((Float) currAttr).floatValue();
+                this.size = (int) Math.ceil(this.pointSize);
+            }
+
+            currAttr = attributes.get(TextAttribute.POSTURE);
+            if (currAttr != null
+                    && currAttr.equals(TextAttribute.POSTURE_OBLIQUE)) {
+                this.style |= Font.ITALIC;
+            }
+
+            currAttr = attributes.get(TextAttribute.WEIGHT);
+            if ((currAttr != null)
+                    && (((Float) currAttr).floatValue() >= (TextAttribute.WEIGHT_BOLD)
+                            .floatValue())) {
+                this.style |= Font.BOLD;
+            }
+
+            currAttr = attributes.get(TextAttribute.FAMILY);
+            if (currAttr != null) {
+                this.name = (String) currAttr;
+            }
+
+            currAttr = attributes.get(TextAttribute.TRANSFORM);
+            if (currAttr != null) {
+                if (currAttr instanceof TransformAttribute) {
+                    this.transformed = !((TransformAttribute) currAttr)
+                            .getTransform().isIdentity();
+                } else if (currAttr instanceof AffineTransform) {
+                    this.transformed = !((AffineTransform) currAttr)
+                            .isIdentity();
+                }
+            }
+
+        } else {
+            fRequestedAttributes = new Hashtable<Attribute, Object>(5);
+            fRequestedAttributes.put(TextAttribute.TRANSFORM,
+                    IDENTITY_TRANSFORM);
+
+            this.transformed = false;
+
+            fRequestedAttributes.put(TextAttribute.FAMILY, name);
+
+            fRequestedAttributes.put(TextAttribute.SIZE, new Float(this.size));
+
+            if ((this.style & Font.BOLD) != 0) {
+                fRequestedAttributes.put(TextAttribute.WEIGHT,
+                        TextAttribute.WEIGHT_BOLD);
+            } else {
+                fRequestedAttributes.put(TextAttribute.WEIGHT,
+                        TextAttribute.WEIGHT_REGULAR);
+            }
+            if ((this.style & Font.ITALIC) != 0) {
+                fRequestedAttributes.put(TextAttribute.POSTURE,
+                        TextAttribute.POSTURE_OBLIQUE);
+            } else {
+                fRequestedAttributes.put(TextAttribute.POSTURE,
+                        TextAttribute.POSTURE_REGULAR);
+            }
+
+        }
+    }
+
+    /**
+     * Instantiates a new Font with the specified name, style and size.
+     * 
+     * @param name the name of font.
+     * @param style the style of font.
+     * @param size the size of font.
+     */
+    public Font(String name, int style, int size) {
+
+        this.name = (name != null) ? name : "Default"; //$NON-NLS-1$
+        this.size = (size >= 0) ? size : 0;
+        this.style = (style & ~0x03) == 0 ? style : Font.PLAIN;
+        this.pointSize = this.size;
+
+        fRequestedAttributes = new Hashtable<Attribute, Object>(5);
+
+        fRequestedAttributes.put(TextAttribute.TRANSFORM, IDENTITY_TRANSFORM);
+
+        this.transformed = false;
+
+        fRequestedAttributes.put(TextAttribute.FAMILY, this.name);
+        fRequestedAttributes.put(TextAttribute.SIZE, new Float(this.size));
+
+        if ((this.style & Font.BOLD) != 0) {
+            fRequestedAttributes.put(TextAttribute.WEIGHT,
+                    TextAttribute.WEIGHT_BOLD);
+        } else {
+            fRequestedAttributes.put(TextAttribute.WEIGHT,
+                    TextAttribute.WEIGHT_REGULAR);
+        }
+        if ((this.style & Font.ITALIC) != 0) {
+            fRequestedAttributes.put(TextAttribute.POSTURE,
+                    TextAttribute.POSTURE_OBLIQUE);
+        } else {
+            fRequestedAttributes.put(TextAttribute.POSTURE,
+                    TextAttribute.POSTURE_REGULAR);
+        }
+    }
+
+    /**
+     * Returns true if this Font has a glyph for the specified character.
+     * 
+     * @param c the character.
+     * 
+     * @return true if this Font has a glyph for the specified character,
+     * false otherwise.
+     */
+    public boolean canDisplay(char c) {
+        FontPeerImpl peer = (FontPeerImpl) this.getPeer();
+        return peer.canDisplay(c);
+    }
+
+    /**
+     * Returns true if the Font can display the characters of the 
+     * the specified text from the specified start position 
+     * to the specified limit position. 
+     * 
+     * @param text the text.
+     * @param start the start offset (in the character array).
+     * @param limit the limit offset (in the character array).
+     * 
+     * @return the a character's position in the text that this Font 
+     * can not display, or -1 if this Font can display all characters 
+     * in this text.
+     */
+    public int canDisplayUpTo(char[] text, int start, int limit) {
+        int st = start;
+        int result;
+        while ((st < limit) && canDisplay(text[st])) {
+            st++;
+        }
+
+        if (st == limit) {
+            result = -1;
+        } else {
+            result = st;
+        }
+
+        return result;
+    }
+
+    /**
+     * Returns true if the Font can display the characters of the 
+     * the specified CharacterIterator from the specified start position 
+     * and the specified limit position. 
+     * 
+     * @param iter the CharacterIterator.
+     * @param start the start offset.
+     * @param limit the limit offset.
+     * 
+     * @return the a character's position in the CharacterIterator
+     * that this Font can not display, or -1 if this Font can display 
+     * all characters in this text.
+     */
+    public int canDisplayUpTo(CharacterIterator iter, int start, int limit) {
+        int st = start;
+        char c = iter.setIndex(start);
+        int result;
+
+        while ((st < limit) && (canDisplay(c))) {
+            st++;
+            c = iter.next();
+        }
+        if (st == limit) {
+            result = -1;
+        } else {
+            result = st;
+        }
+
+        return result;
+    }
+
+    /**
+     * Returns true if this Font can display a specified String.
+     * 
+     * @param str the String.
+     * 
+     * @return the a character's position in the String that 
+     * this Font can not display, or -1 if this Font can display 
+     * all characters in this text.
+     */
+    public int canDisplayUpTo(String str) {
+        char[] chars = str.toCharArray();
+        return canDisplayUpTo(chars, 0, chars.length);
+    }
+
+    /**
+     * Creates a GlyphVector of associating characters to glyphs 
+     * based on the unicode map of this Font. 
+     * 
+     * @param frc the FontRenderContext.
+     * @param chars the characters array.
+     * 
+     * @return the GlyphVector of associating characters to glyphs 
+     * based on the unicode map of this Font.
+     */
+    public GlyphVector createGlyphVector(FontRenderContext frc, char[] chars) {
+        return new AndroidGlyphVector(chars, frc, this, 0);
+    }
+
+    /**
+     * Creates a GlyphVector of associating characters contained
+     * in the specified CharacterIterator to glyphs based on 
+     * the unicode map of this Font. 
+     * 
+     * @param frc the FontRenderContext.
+     * @param iter the CharacterIterator.
+     * 
+     * @return the GlyphVector of associating characters contained
+     * in the specified CharacterIterator to glyphs 
+     * based on the unicode map of this Font.
+     */
+    public GlyphVector createGlyphVector(FontRenderContext frc,
+            CharacterIterator iter) {
+    	throw new RuntimeException("Not implemented!"); //$NON-NLS-1$    
+    }
+
+    /**
+     * Creates a GlyphVector of associating characters to glyphs based on 
+     * the unicode map of this Font. 
+     * 
+     * @param frc the FontRenderContext.
+     * @param glyphCodes the specified integer array of glyph codes.
+     * 
+     * @return the GlyphVector of associating characters to glyphs 
+     * based on the unicode map of this Font.
+     */
+    public GlyphVector createGlyphVector(FontRenderContext frc, int[] glyphCodes)
+            throws org.apache.harmony.luni.util.NotImplementedException {
+        throw new RuntimeException("Not implemented!"); //$NON-NLS-1$
+    }
+
+    /**
+     * Creates a GlyphVector of associating characters to glyphs based on 
+     * the unicode map of this Font. 
+     * 
+     * @param frc the FontRenderContext.
+     * @param str the specified String.
+     * 
+     * @return the GlyphVector of associating characters to glyphs 
+     * based on the unicode map of this Font.
+     */
+    public GlyphVector createGlyphVector(FontRenderContext frc, String str) {
+        return new AndroidGlyphVector(str.toCharArray(), frc, this, 0);
+
+    }
+
+    /**
+     * Returns the font style constant value corresponding to one of the font style
+     * names ("BOLD", "ITALIC", "BOLDITALIC"). This method returns Font.PLAIN if
+     * the argument is not one of the predefined style names.
+     * 
+     * @param fontStyleName font style name
+     * 
+     * @return font style constant value corresponding to the font style name
+     * specified.
+     */
+    private static int getFontStyle(String fontStyleName) {
+        int result = Font.PLAIN;
+
+        if (fontStyleName.toUpperCase().equals("BOLDITALIC")) { //$NON-NLS-1$
+            result = Font.BOLD | Font.ITALIC;
+        } else if (fontStyleName.toUpperCase().equals("BOLD")) { //$NON-NLS-1$
+            result = Font.BOLD;
+        } else if (fontStyleName.toUpperCase().equals("ITALIC")) { //$NON-NLS-1$
+            result = Font.ITALIC;
+        }
+
+        return result;
+    }
+
+    /**
+     * Decodes the specified string which described the Font. The string 
+     * should have the following format: fontname-style-pointsize. 
+     * The style can be PLAIN, BOLD, BOLDITALIC, or ITALIC.
+     * 
+     * @param str the string which describes the font.
+     * 
+     * @return the Font from the specified string.
+     */
+    public static Font decode(String str) {
+        // XXX: Documentation doesn't describe all cases, e.g. fonts face names
+        // with
+        // symbols that are suggested as delimiters in the documentation.
+        // In this decode implementation only ***-***-*** format is used with
+        // '-'
+        // as the delimiter to avoid unexpected parse results of font face names
+        // with spaces.
+
+        if (str == null) {
+            return DEFAULT_FONT;
+        }
+
+        StringTokenizer strTokens;
+        String delim = "-"; //$NON-NLS-1$
+        String substr;
+
+        int fontSize = DEFAULT_FONT.size;
+        int fontStyle = DEFAULT_FONT.style;
+        String fontName = DEFAULT_FONT.name;
+
+        strTokens = new StringTokenizer(str.trim(), delim);
+
+        // Font Name
+        if (strTokens.hasMoreTokens()) {
+            fontName = strTokens.nextToken(); // first token is the font name
+        }
+
+        // Font Style or Size (if the style is undefined)
+        if (strTokens.hasMoreTokens()) {
+            substr = strTokens.nextToken();
+
+            try {
+                // if second token is the font size
+                fontSize = Integer.parseInt(substr);
+            } catch (NumberFormatException e) {
+                // then second token is the font style
+                fontStyle = getFontStyle(substr);
+            }
+
+        }
+
+        // Font Size
+        if (strTokens.hasMoreTokens()) {
+            try {
+                fontSize = Integer.parseInt(strTokens.nextToken());
+            } catch (NumberFormatException e) {
+            }
+        }
+
+        return new Font(fontName, fontStyle, fontSize);
+    }
+
+    /**
+     * Perfoms the specified affine transform to the Font and returns 
+     * a new Font.
+     * 
+     * @param trans the AffineTransform.
+     * 
+     * @return the Font object.
+     * 
+     * @throws IllegalArgumentException if affine transform parameter
+     * is null.
+     */
+    @SuppressWarnings("unchecked")
+    public Font deriveFont(AffineTransform trans) {
+
+        if (trans == null) {
+            // awt.94=transform can not be null
+            throw new IllegalArgumentException(Messages.getString("awt.94")); //$NON-NLS-1$
+        }
+
+        Hashtable<Attribute, Object> derivefRequestedAttributes = (Hashtable<Attribute, Object>) fRequestedAttributes
+                .clone();
+
+        derivefRequestedAttributes.put(TextAttribute.TRANSFORM,
+                new TransformAttribute(trans));
+
+        return new Font(derivefRequestedAttributes);
+
+    }
+
+    /**
+     * Returns a new Font that is a copy of the current Font 
+     * modified so that the size is the specified size.
+     * 
+     * @param size the size of font.
+     * 
+     * @return the Font object.
+     */
+    @SuppressWarnings("unchecked")
+    public Font deriveFont(float size) {
+        Hashtable<Attribute, Object> derivefRequestedAttributes = (Hashtable<Attribute, Object>) fRequestedAttributes
+                .clone();
+        derivefRequestedAttributes.put(TextAttribute.SIZE, new Float(size));
+        return new Font(derivefRequestedAttributes);
+    }
+
+    /**
+     * Returns a new Font that is a copy of the current Font 
+     * modified so that the style is the specified style.
+     * 
+     * @param style the style of font.
+     * 
+     * @return the Font object.
+     */
+    @SuppressWarnings("unchecked")
+    public Font deriveFont(int style) {
+        Hashtable<Attribute, Object> derivefRequestedAttributes = (Hashtable<Attribute, Object>) fRequestedAttributes
+                .clone();
+
+        if ((style & Font.BOLD) != 0) {
+            derivefRequestedAttributes.put(TextAttribute.WEIGHT,
+                    TextAttribute.WEIGHT_BOLD);
+        } else if (derivefRequestedAttributes.get(TextAttribute.WEIGHT) != null) {
+            derivefRequestedAttributes.remove(TextAttribute.WEIGHT);
+        }
+
+        if ((style & Font.ITALIC) != 0) {
+            derivefRequestedAttributes.put(TextAttribute.POSTURE,
+                    TextAttribute.POSTURE_OBLIQUE);
+        } else if (derivefRequestedAttributes.get(TextAttribute.POSTURE) != null) {
+            derivefRequestedAttributes.remove(TextAttribute.POSTURE);
+        }
+
+        return new Font(derivefRequestedAttributes);
+    }
+
+    /**
+     * Returns a new Font that is a copy of the current Font
+     * modified to match the specified style and with the specified
+     * affine transform applied to its glyphs.
+     * 
+     * @param style the style of font.
+     * @param trans the AffineTransform.
+     * 
+     * @return the Font object.
+     */
+    @SuppressWarnings("unchecked")
+    public Font deriveFont(int style, AffineTransform trans) {
+
+        if (trans == null) {
+            // awt.94=transform can not be null
+            throw new IllegalArgumentException(Messages.getString("awt.94")); //$NON-NLS-1$
+        }
+        Hashtable<Attribute, Object> derivefRequestedAttributes = (Hashtable<Attribute, Object>) fRequestedAttributes
+                .clone();
+
+        if ((style & BOLD) != 0) {
+            derivefRequestedAttributes.put(TextAttribute.WEIGHT,
+                    TextAttribute.WEIGHT_BOLD);
+        } else if (derivefRequestedAttributes.get(TextAttribute.WEIGHT) != null) {
+            derivefRequestedAttributes.remove(TextAttribute.WEIGHT);
+        }
+
+        if ((style & ITALIC) != 0) {
+            derivefRequestedAttributes.put(TextAttribute.POSTURE,
+                    TextAttribute.POSTURE_OBLIQUE);
+        } else if (derivefRequestedAttributes.get(TextAttribute.POSTURE) != null) {
+            derivefRequestedAttributes.remove(TextAttribute.POSTURE);
+        }
+        derivefRequestedAttributes.put(TextAttribute.TRANSFORM,
+                new TransformAttribute(trans));
+
+        return new Font(derivefRequestedAttributes);
+    }
+
+    /**
+     * Returns a new Font that is a copy of the current Font 
+     * modified so that the size and style are the specified 
+     * size and style.
+     * 
+     * @param style the style of font.
+     * @param size the size of font.
+     * 
+     * @return the Font object.
+     */
+    @SuppressWarnings("unchecked")
+    public Font deriveFont(int style, float size) {
+        Hashtable<Attribute, Object> derivefRequestedAttributes = (Hashtable<Attribute, Object>) fRequestedAttributes
+                .clone();
+
+        if ((style & BOLD) != 0) {
+            derivefRequestedAttributes.put(TextAttribute.WEIGHT,
+                    TextAttribute.WEIGHT_BOLD);
+        } else if (derivefRequestedAttributes.get(TextAttribute.WEIGHT) != null) {
+            derivefRequestedAttributes.remove(TextAttribute.WEIGHT);
+        }
+
+        if ((style & ITALIC) != 0) {
+            derivefRequestedAttributes.put(TextAttribute.POSTURE,
+                    TextAttribute.POSTURE_OBLIQUE);
+        } else if (derivefRequestedAttributes.get(TextAttribute.POSTURE) != null) {
+            derivefRequestedAttributes.remove(TextAttribute.POSTURE);
+        }
+
+        derivefRequestedAttributes.put(TextAttribute.SIZE, new Float(size));
+        return new Font(derivefRequestedAttributes);
+
+    }
+
+    /**
+     * Returns a new Font object with a new set of font attributes.
+     * 
+     * @param attributes the map of attributes.
+     * 
+     * @return the Font.
+     */
+    @SuppressWarnings("unchecked")
+    public Font deriveFont(Map<? extends Attribute, ?> attributes) {
+        Attribute[] avalAttributes = this.getAvailableAttributes();
+
+        Hashtable<Attribute, Object> derivefRequestedAttributes = (Hashtable<Attribute, Object>) fRequestedAttributes
+                .clone();
+        Object currAttribute;
+        for (Attribute element : avalAttributes) {
+            currAttribute = attributes.get(element);
+            if (currAttribute != null) {
+                derivefRequestedAttributes.put(element, currAttribute);
+            }
+        }
+        return new Font(derivefRequestedAttributes);
+    }
+
+    /**
+     * Compares the specified Object with the current Font.
+     * 
+     * @param obj the Object to be compared.
+     * 
+     * @return true, if the specified Object is an instance of Font
+     * with the same family, size, and style as this Font, false otherwise. 
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+
+        if (obj != null) {
+            try {
+                Font font = (Font) obj;
+
+                return ((this.style == font.style) && (this.size == font.size)
+                        && this.name.equals(font.name)
+                        && (this.pointSize == font.pointSize) && (this
+                        .getTransform()).equals(font.getTransform()));
+            } catch (ClassCastException e) {
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Gets the map of font's attributes.
+     * 
+     * @return the map of font's attributes.
+     */
+    @SuppressWarnings("unchecked")
+    public Map<TextAttribute, ?> getAttributes() {
+        return (Map<TextAttribute, ?>) fRequestedAttributes.clone();
+    }
+
+    /**
+     * Gets the keys of all available attributes.
+     * 
+     * @return the keys array of all available attributes.
+     */
+    public Attribute[] getAvailableAttributes() {
+        Attribute[] attrs = { TextAttribute.FAMILY, TextAttribute.POSTURE,
+                TextAttribute.SIZE, TextAttribute.TRANSFORM,
+                TextAttribute.WEIGHT, TextAttribute.SUPERSCRIPT,
+                TextAttribute.WIDTH };
+        return attrs;
+    }
+
+    /**
+     * Gets the baseline for this character.
+     * 
+     * @param c the character.
+     * 
+     * @return the baseline for this character.
+     */
+    public byte getBaselineFor(char c) {
+        // TODO: implement using TT BASE table data
+        return 0;
+    }
+
+    /**
+     * Gets the family name of the Font.
+     * 
+     * @return the family name of the Font.
+     */
+    public String getFamily() {
+        if (fRequestedAttributes != null) {
+            fRequestedAttributes.get(TextAttribute.FAMILY);
+        }
+        return null;
+    }
+
+    /**
+     * Returns the family name of this Font associated with 
+     * the specified locale.
+     * 
+     * @param l the locale.
+     * 
+     * @return the family name of this Font associated with 
+     * the specified locale.
+     */
+    public String getFamily(Locale l) {
+        if (l == null) {
+            // awt.01='{0}' parameter is null
+            throw new NullPointerException(Messages.getString(
+                    "awt.01", "Locale")); //$NON-NLS-1$ //$NON-NLS-2$ 
+        }
+        return getFamily();
+    }
+
+    /**
+     * Gets a Font with the specified attribute set.
+     * 
+     * @param attributes the attributes to be assigned to the new Font.
+     * 
+     * @return the Font.
+     */
+    public static Font getFont(Map<? extends Attribute, ?> attributes) {
+        Font fnt = (Font) attributes.get(TextAttribute.FONT);
+        if (fnt != null) {
+            return fnt;
+        }
+        return new Font(attributes);
+    }
+
+    /**
+     * Gets a Font object from the system properties list with the specified name
+     * or returns the specified Font if there is no such property.
+     * 
+     * @param sp the specified property name.
+     * @param f the Font.
+     * 
+     * @return the Font object from the system properties list  with the specified name
+     * or the specified Font if there is no such property.
+     */
+    public static Font getFont(String sp, Font f) {
+        String pr = System.getProperty(sp);
+        if (pr == null) {
+            return f;
+        }
+        return decode(pr);
+    }
+
+    /**
+     * Gets a Font object from the system properties list with the specified name.
+     * 
+     * @param sp the system property name.
+     * 
+     * @return the Font, or null if there is no shuch property
+     * with the specified name. 
+     */
+    public static Font getFont(String sp) {
+        return getFont(sp, null);
+    }
+
+    /**
+     * Gets the font name.
+     * 
+     * @return the font name.
+     */
+    public String getFontName() {
+        if (fRequestedAttributes != null) {
+            fRequestedAttributes.get(TextAttribute.FAMILY);
+        }
+        return null;
+    }
+
+    /**
+     * Returns the font name associated with the specified locale.
+     * 
+     * @param l the locale.
+     * 
+     * @return the font name associated with the specified locale.
+     */
+    public String getFontName(Locale l) {
+        return getFamily();
+    }
+
+    /**
+     * Returns a LineMetrics object created with the specified parameters.
+     * 
+     * @param chars the chars array.
+     * @param start the start offset.
+     * @param end the end offset.
+     * @param frc the FontRenderContext.
+     * 
+     * @return the LineMetrics for the specified parameters.
+     */
+    public LineMetrics getLineMetrics(char[] chars, int start, int end,
+            FontRenderContext frc) {
+        if (frc == null) {
+            // awt.00=FontRenderContext is null
+            throw new NullPointerException(Messages.getString("awt.00")); //$NON-NLS-1$
+        }
+
+        //FontMetrics fm = AndroidGraphics2D.getInstance().getFontMetrics();
+        FontMetrics fm = new FontMetricsImpl(this);
+        float[] fmet = {fm.getAscent(), fm.getDescent(), fm.getLeading()}; 
+        return new LineMetricsImpl(chars.length, fmet, null);
+    }
+
+    /**
+     * Returns a LineMetrics object created with the specified parameters.
+     * 
+     * @param iter the CharacterIterator.
+     * @param start the start offset.
+     * @param end the end offset.
+     * @param frc the FontRenderContext.
+     * 
+     * @return the LineMetrics for the specified parameters.
+     */
+    public LineMetrics getLineMetrics(CharacterIterator iter, int start,
+            int end, FontRenderContext frc) {
+
+        if (frc == null) {
+            // awt.00=FontRenderContext is null
+            throw new NullPointerException(Messages.getString("awt.00")); //$NON-NLS-1$
+        }
+
+        String resultString;
+        int iterCount;
+
+        iterCount = end - start;
+        if (iterCount < 0) {
+            resultString = ""; //$NON-NLS-1$
+        } else {
+            char[] chars = new char[iterCount];
+            int i = 0;
+            for (char c = iter.setIndex(start); c != CharacterIterator.DONE
+                    && (i < iterCount); c = iter.next()) {
+                chars[i] = c;
+                i++;
+            }
+            resultString = new String(chars);
+        }
+        return this.getLineMetrics(resultString, frc);
+    }
+
+    /**
+     * Returns a LineMetrics object created with the specified parameters.
+     * 
+     * @param str the String.
+     * @param frc the FontRenderContext.
+     * 
+     * @return the LineMetrics for the specified parameters.
+     */
+    public LineMetrics getLineMetrics(String str, FontRenderContext frc) {
+        //FontMetrics fm = AndroidGraphics2D.getInstance().getFontMetrics();
+        FontMetrics fm = new FontMetricsImpl(this);
+        float[] fmet = {fm.getAscent(), fm.getDescent(), fm.getLeading()};
+        //Log.i("FONT FMET", fmet.toString());
+        return new LineMetricsImpl(str.length(), fmet, null);
+
+    }
+
+    /**
+     * Returns a LineMetrics object created with the specified parameters.
+     * 
+     * @param str the String.
+     * @param start the start offset.
+     * @param end the end offset.
+     * @param frc the FontRenderContext.
+     * 
+     * @return the LineMetrics for the specified parameters.
+     */
+    public LineMetrics getLineMetrics(String str, int start, int end,
+            FontRenderContext frc) {
+        return this.getLineMetrics(str.substring(start, end), frc);
+    }
+
+    /**
+     * Gets the logical bounds of the specified String in 
+     * the specified FontRenderContext. The logical bounds contains 
+     * the origin, ascent, advance, and height.
+     * 
+     * @param ci the specified CharacterIterator.
+     * @param start the start offset.
+     * @param end the end offset.
+     * @param frc the FontRenderContext.
+     * 
+     * @return a Rectangle2D object.
+     */
+    public Rectangle2D getStringBounds(CharacterIterator ci, int start,
+            int end, FontRenderContext frc) {
+        int first = ci.getBeginIndex();
+        int finish = ci.getEndIndex();
+        char[] chars;
+
+        if (start < first) {
+            // awt.95=Wrong start index: {0}
+            throw new IndexOutOfBoundsException(Messages.getString(
+                    "awt.95", start)); //$NON-NLS-1$
+        }
+        if (end > finish) {
+            // awt.96=Wrong finish index: {0}
+            throw new IndexOutOfBoundsException(Messages.getString(
+                    "awt.96", end)); //$NON-NLS-1$
+        }
+        if (start > end) {
+            // awt.97=Wrong range length: {0}
+            throw new IndexOutOfBoundsException(Messages.getString("awt.97", //$NON-NLS-1$
+                    (end - start)));
+        }
+
+        if (frc == null) {
+            throw new NullPointerException(Messages.getString("awt.00")); //$NON-NLS-1$
+        }
+
+        chars = new char[end - start];
+
+        ci.setIndex(start);
+        for (int i = 0; i < chars.length; i++) {
+            chars[i] = ci.current();
+            ci.next();
+        }
+
+        return this.getStringBounds(chars, 0, chars.length, frc);
+
+    }
+
+    /**
+     * Gets the logical bounds of the specified String in 
+     * the specified FontRenderContext. The logical bounds contains 
+     * the origin, ascent, advance, and height.
+     * 
+     * @param str the specified String.
+     * @param frc the FontRenderContext.
+     * 
+     * @return a Rectangle2D object.
+     */
+    public Rectangle2D getStringBounds(String str, FontRenderContext frc) {
+        char[] chars = str.toCharArray();
+        return this.getStringBounds(chars, 0, chars.length, frc);
+
+    }
+
+    /**
+     * Gets the logical bounds of the specified String in 
+     * the specified FontRenderContext. The logical bounds contains 
+     * the origin, ascent, advance, and height.
+     * 
+     * @param str the specified String.
+     * @param start the start offset.
+     * @param end the end offset.
+     * @param frc the FontRenderContext.
+     * 
+     * @return a Rectangle2D object.
+     */
+    public Rectangle2D getStringBounds(String str, int start, int end,
+            FontRenderContext frc) {
+
+        return this.getStringBounds((str.substring(start, end)), frc);
+    }
+
+    /**
+     * Gets the logical bounds of the specified String in 
+     * the specified FontRenderContext. The logical bounds contains 
+     * the origin, ascent, advance, and height.
+     * 
+     * @param chars the specified character array.
+     * @param start the start offset.
+     * @param end the end offset.
+     * @param frc the FontRenderContext.
+     * 
+     * @return a Rectangle2D object.
+     */
+    public Rectangle2D getStringBounds(char[] chars, int start, int end,
+            FontRenderContext frc) {
+        if (start < 0) {
+            // awt.95=Wrong start index: {0}
+            throw new IndexOutOfBoundsException(Messages.getString(
+                    "awt.95", start)); //$NON-NLS-1$
+        }
+        if (end > chars.length) {
+            // awt.96=Wrong finish index: {0}
+            throw new IndexOutOfBoundsException(Messages.getString(
+                    "awt.96", end)); //$NON-NLS-1$
+        }
+        if (start > end) {
+            // awt.97=Wrong range length: {0}
+            throw new IndexOutOfBoundsException(Messages.getString("awt.97", //$NON-NLS-1$
+                    (end - start)));
+        }
+
+        if (frc == null) {
+            throw new NullPointerException(Messages.getString("awt.00")); //$NON-NLS-1$
+        }
+
+        FontPeerImpl peer = (FontPeerImpl) this.getPeer();
+
+        final int TRANSFORM_MASK = AffineTransform.TYPE_GENERAL_ROTATION
+                | AffineTransform.TYPE_GENERAL_TRANSFORM;
+        Rectangle2D bounds;
+
+        AffineTransform transform = getTransform();
+
+        // XXX: for transforms where an angle between basis vectors is not 90
+        // degrees Rectanlge2D class doesn't fit as Logical bounds.
+        if ((transform.getType() & TRANSFORM_MASK) == 0) {
+            int width = 0;
+            for (int i = start; i < end; i++) {
+                width += peer.charWidth(chars[i]);
+            }
+            //LineMetrics nlm = peer.getLineMetrics();
+            
+            LineMetrics nlm = getLineMetrics(chars, start, end, frc);
+            
+            bounds = transform.createTransformedShape(
+                    new Rectangle2D.Float(0, -nlm.getAscent(), width, nlm
+                            .getHeight())).getBounds2D();
+        } else {
+            int len = end - start;
+            char[] subChars = new char[len];
+            System.arraycopy(chars, start, subChars, 0, len);
+            bounds = createGlyphVector(frc, subChars).getLogicalBounds();
+        }
+        return bounds;
+    }
+
+    /**
+     * Gets the character's maximum bounds as defined in 
+     * the specified FontRenderContext.
+     * 
+     * @param frc the FontRenderContext.
+     * 
+     * @return the character's maximum bounds.
+     */
+    public Rectangle2D getMaxCharBounds(FontRenderContext frc) {
+        if (frc == null) {
+            // awt.00=FontRenderContext is null
+            throw new NullPointerException(Messages.getString("awt.00")); //$NON-NLS-1$ 
+        }
+
+        FontPeerImpl peer = (FontPeerImpl) this.getPeer();
+
+        Rectangle2D bounds = peer.getMaxCharBounds(frc);
+        AffineTransform transform = getTransform();
+        // !! Documentation doesn't describe meaning of max char bounds
+        // for the fonts that have rotate transforms. For all transforms
+        // returned bounds are the bounds of transformed maxCharBounds
+        // Rectangle2D that corresponds to the font with identity transform.
+        // TODO: resolve this issue to return correct bounds
+        bounds = transform.createTransformedShape(bounds).getBounds2D();
+
+        return bounds;
+    }
+
+    /**
+     * Returns a new GlyphVector object performing full layout of
+     * the text.
+     * 
+     * @param frc the FontRenderContext.
+     * @param chars the character array to be layout.
+     * @param start the start offset of the text to use for 
+     * the GlyphVector.
+     * @param count the count of characters to use for 
+     * the GlyphVector.
+     * @param flags the flag indicating text direction: 
+     * LAYOUT_RIGHT_TO_LEFT, LAYOUT_LEFT_TO_RIGHT.
+     * 
+     * @return the GlyphVector.
+     */
+    public GlyphVector layoutGlyphVector(FontRenderContext frc, char[] chars,
+            int start, int count, int flags) {
+        // TODO: implement method for bidirectional text.
+        // At the moment only LTR and RTL texts supported.
+        if (start < 0) {
+            // awt.95=Wrong start index: {0}
+            throw new ArrayIndexOutOfBoundsException(Messages.getString(
+                    "awt.95", //$NON-NLS-1$
+                    start));
+        }
+
+        if (count < 0) {
+            // awt.98=Wrong count value, can not be negative: {0}
+            throw new ArrayIndexOutOfBoundsException(Messages.getString(
+                    "awt.98", //$NON-NLS-1$
+                    count));
+        }
+
+        if (start + count > chars.length) {
+            // awt.99=Wrong [start + count] is out of range: {0}
+            throw new ArrayIndexOutOfBoundsException(Messages.getString(
+                    "awt.99", //$NON-NLS-1$
+                    (start + count)));
+        }
+
+        char[] out = new char[count];
+        System.arraycopy(chars, start, out, 0, count);
+
+        return new CommonGlyphVector(out, frc, this, flags);
+    }
+
+    /**
+     * Returns the String representation of this Font.
+     * 
+     * @return the String representation of this Font.
+     */
+    @Override
+    public String toString() {
+        String stl = "plain"; //$NON-NLS-1$
+        String result;
+
+        if (this.isBold() && this.isItalic()) {
+            stl = "bolditalic"; //$NON-NLS-1$
+        }
+        if (this.isBold() && !this.isItalic()) {
+            stl = "bold"; //$NON-NLS-1$
+        }
+
+        if (!this.isBold() && this.isItalic()) {
+            stl = "italic"; //$NON-NLS-1$
+        }
+
+        result = this.getClass().getName() + "[family=" + this.getFamily() + //$NON-NLS-1$
+                ",name=" + this.name + //$NON-NLS-1$
+                ",style=" + stl + //$NON-NLS-1$
+                ",size=" + this.size + "]"; //$NON-NLS-1$ //$NON-NLS-2$
+        return result;
+    }
+
+    /**
+     * Gets the postscript name of this Font.
+     * 
+     * @return the postscript name of this Font.
+     */
+    public String getPSName() {
+        FontPeerImpl peer = (FontPeerImpl) this.getPeer();
+        return peer.getPSName();
+    }
+
+    /**
+     * Gets the logical name of this Font.
+     * 
+     * @return the logical name of this Font.
+     */
+    public String getName() {
+        return (this.name);
+    }
+
+    /**
+     * Gets the peer of this Font.
+     * 
+     * @return the peer of this Font.
+     * 
+     * @deprecated Font rendering is platform independent now.
+     */
+    @Deprecated
+    public java.awt.peer.FontPeer getPeer() {
+        if (fontPeer == null) {
+            fontPeer = (FontPeerImpl) Toolkit.getDefaultToolkit()
+                    .getGraphicsFactory().getFontPeer(this);
+        }
+        return fontPeer;
+
+    }
+
+    /**
+     * Gets the transform acting on this Font (from the Font's 
+     * attributes).
+     * 
+     * @return the transformation of this Font. 
+     */
+    public AffineTransform getTransform() {
+        Object transform = fRequestedAttributes.get(TextAttribute.TRANSFORM);
+
+        if (transform != null) {
+            if (transform instanceof TransformAttribute) {
+                return ((TransformAttribute) transform).getTransform();
+            }
+            if (transform instanceof AffineTransform) {
+                return new AffineTransform((AffineTransform) transform);
+            }
+        } else {
+            transform = new AffineTransform();
+        }
+        return (AffineTransform) transform;
+
+    }
+
+    /**
+     * Checks if this font is transformed or not.
+     * 
+     * @return true, if this font is transformed, false otherwise.
+     */
+    public boolean isTransformed() {
+        return this.transformed;
+    }
+
+    /**
+     * Checks if this font has plain style or not.
+     * 
+     * @return true, if this font has plain style, false otherwise.
+     */
+    public boolean isPlain() {
+        return (this.style == PLAIN);
+    }
+
+    /**
+     * Checks if this font has italic style or not.
+     * 
+     * @return true, if this font has italic style, false otherwise.
+     */
+    public boolean isItalic() {
+        return (this.style & ITALIC) != 0;
+    }
+
+    /**
+     * Checks if this font has bold style or not.
+     * 
+     * @return true, if this font has bold style, false otherwise.
+     */
+    public boolean isBold() {
+        return (this.style & BOLD) != 0;
+    }
+
+    /**
+     * Returns true if this Font has uniform line metrics. 
+     * 
+     * @return true if this Font has uniform line metrics, 
+     * false otherwise.
+     */
+    public boolean hasUniformLineMetrics() {
+        FontPeerImpl peer = (FontPeerImpl) this.getPeer();
+        return peer.hasUniformLineMetrics();
+    }
+
+    /**
+     * Returns hash code of this Font object.
+     * 
+     * @return the hash code of this Font object.
+
+     */
+    @Override
+    public int hashCode() {
+        HashCode hash = new HashCode();
+
+        hash.append(this.name);
+        hash.append(this.style);
+        hash.append(this.size);
+
+        return hash.hashCode();
+    }
+
+    /**
+     * Gets the style of this Font.
+     * 
+     * @return the style of this Font.
+     */
+    public int getStyle() {
+        return this.style;
+    }
+
+    /**
+     * Gets the size of this Font.
+     * 
+     * @return the size of this Font.
+     */
+    public int getSize() {
+        return this.size;
+    }
+
+    /**
+     * Gets the number of glyphs for this Font.
+     * 
+     * @return the number of glyphs for this Font.
+     */
+    public int getNumGlyphs() {
+        if (numGlyphs == -1) {
+            FontPeerImpl peer = (FontPeerImpl) this.getPeer();
+            this.numGlyphs = peer.getNumGlyphs();
+        }
+        return this.numGlyphs;
+    }
+
+    /**
+     * Gets the glyphCode which is used as default glyph when this Font
+     * does not have a glyph for a specified unicode.
+     * 
+     * @return the missing glyph code.
+     */
+    public int getMissingGlyphCode() {
+        if (missingGlyphCode == -1) {
+            FontPeerImpl peer = (FontPeerImpl) this.getPeer();
+            this.missingGlyphCode = peer.getMissingGlyphCode();
+        }
+        return this.missingGlyphCode;
+    }
+
+    /**
+     * Gets the float value of font's size.
+     * 
+     * @return the float value of font's size.
+     */
+    public float getSize2D() {
+        return this.pointSize;
+    }
+
+    /**
+     * Gets the italic angle of this Font.
+      * 
+     * @return the italic angle of this Font.
+     */
+    public float getItalicAngle() {
+        FontPeerImpl peer = (FontPeerImpl) this.getPeer();
+        return peer.getItalicAngle();
+    }
+
+    /**
+     * Creates the font with the specified font format and font file.
+     * 
+     * @param fontFormat the font format.
+     * @param fontFile the file object represented the input data 
+     * for the font.
+     * 
+     * @return the Font.
+     * 
+     * @throws FontFormatException is thrown if fontFile does not contain 
+     * the required font tables for the specified format.
+     * @throws IOException signals that an I/O exception has occurred.
+     */
+    public static Font createFont(int fontFormat, File fontFile)
+            throws FontFormatException, IOException {
+        // ???AWT not supported
+        InputStream is = new FileInputStream(fontFile);
+        try {
+            return createFont(fontFormat, is);
+        } finally {
+            is.close();
+        }
+    }
+
+    /**
+     * Creates the font with the specified font format and input stream.
+     * 
+     * @param fontFormat the font format.
+     * @param fontStream the input stream represented input data for 
+     * the font.
+     * 
+     * @return the Font.
+     * 
+     * @throws FontFormatException is thrown if fontFile does not contain 
+     * the required font tables for the specified format.
+     * @throws IOException signals that an I/O exception has occurred.
+     */
+    public static Font createFont(int fontFormat, InputStream fontStream)
+            throws FontFormatException, IOException {
+
+        // ???AWT not supported
+
+        BufferedInputStream buffStream;
+        int bRead = 0;
+        int size = 8192;
+        // memory page size, for the faster reading
+        byte buf[] = new byte[size];
+
+        if (fontFormat != TRUETYPE_FONT) { // awt.9A=Unsupported font format
+            throw new IllegalArgumentException(Messages.getString("awt.9A")); //$NON-NLS-1$ 
+        }
+        
+        /* Get font file in system-specific directory */
+
+        File fontFile = Toolkit.getDefaultToolkit().getGraphicsFactory()
+                .getFontManager().getTempFontFile();
+
+                // BEGIN android-modified
+        buffStream = new BufferedInputStream(fontStream, 8192);
+                // END android-modified
+        FileOutputStream fOutStream = new FileOutputStream(fontFile);
+
+        bRead = buffStream.read(buf, 0, size);
+
+        while (bRead != -1) {
+            fOutStream.write(buf, 0, bRead);
+            bRead = buffStream.read(buf, 0, size);
+        }
+
+        buffStream.close();
+        fOutStream.close();
+
+        Font font = null;
+
+        font = Toolkit.getDefaultToolkit().getGraphicsFactory().embedFont(
+                fontFile.getAbsolutePath());
+        if (font == null) { // awt.9B=Can't create font - bad font data
+            throw new FontFormatException(Messages.getString("awt.9B")); //$NON-NLS-1$
+        }
+        return font;
+    }
+
+}
diff --git a/awt/java/awt/FontFormatException.java b/awt/java/awt/FontFormatException.java
new file mode 100644
index 0000000..c017fd2
--- /dev/null
+++ b/awt/java/awt/FontFormatException.java
@@ -0,0 +1,41 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Ilya S. Okomin
+ * @version $Revision$
+ */
+package java.awt;
+
+/**
+ * The FontFormatException class is used to provide notification
+ * and information that font can't be created.
+ */
+public class FontFormatException extends Exception {
+    
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = -4481290147811361272L;
+
+    /**
+     * Instantiates a new font format exception with detailed message.
+     * 
+     * @param reason the detailed message.
+     */
+    public FontFormatException(String reason) {
+        super(reason);
+    }
+
+}
diff --git a/awt/java/awt/FontMetrics.java b/awt/java/awt/FontMetrics.java
new file mode 100644
index 0000000..3948d73
--- /dev/null
+++ b/awt/java/awt/FontMetrics.java
@@ -0,0 +1,456 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Ilya S. Okomin
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.awt.font.FontRenderContext;
+import java.awt.font.LineMetrics;
+import java.awt.geom.Rectangle2D;
+import java.io.Serializable;
+import java.text.CharacterIterator;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The FontMetrics class contains information about the rendering 
+ * of a particular font on a particular screen.
+ * <p>
+ * Each character in the Font has three values that help define where 
+ * to place it: an ascent, a descent, and an advance. The ascent is the 
+ * distance the character extends above the baseline. The descent is
+ * the distance the character extends below the baseline. 
+ * The advance width defines the position at which the next character
+ * should be placed.
+ * <p>
+ * An array of characters or a string has an ascent, a descent,
+ *  and an advance width too. The ascent or descent of the array 
+ *  is specified by the maximum ascent or descent of the characters 
+ *  in the array. The advance width is the sum of the advance widths 
+ *  of each of the characters in the character array.
+ */
+public abstract class FontMetrics implements Serializable {
+    
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = 1681126225205050147L;
+
+    /** The font from which the FontMetrics is created. */
+    protected Font font;
+
+    /**
+     * Instantiates a new font metrics from the specified Font.
+     * 
+     * @param fnt the Font.
+     */
+    protected FontMetrics(Font fnt) {
+        this.font = fnt;
+    }
+
+    /**
+     * Returns the String representation of this FontMetrics.
+     * 
+     * @return the string
+     */
+    @Override
+    public String toString() {
+        return this.getClass().getName() +
+                "[font=" + this.getFont() + //$NON-NLS-1$
+                "ascent=" + this.getAscent() + //$NON-NLS-1$
+                ", descent=" + this.getDescent() + //$NON-NLS-1$
+                ", height=" + this.getHeight() + "]"; //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Gets the font associated with this FontMetrics.
+     * 
+     * @return the font associated with this FontMetrics.
+     */
+    public Font getFont() {
+        return font;
+    }
+
+    /**
+     * Gets the height of the text line in this Font.
+     * 
+     * @return the height of the text line in this Font.
+     */
+    public int getHeight() {
+        return this.getAscent() + this.getDescent() + this.getLeading();
+    }
+
+    /**
+     * Gets the font ascent of the Font associated with this FontMetrics.
+     * The font ascent is the distance from the font's baseline to 
+     * the top of most alphanumeric characters.
+     * 
+     * @return the ascent of the Font associated with this FontMetrics.
+     */
+    public int getAscent() {
+        return 0;
+    }
+
+    /**
+     * Gets the font descent of the Font associated with this FontMetrics.
+     * The font descent is the distance from the font's baseline to 
+     * the bottom of most alphanumeric characters with descenders.
+     * 
+     * @return the descent of the Font associated with this FontMetrics.
+     */
+    public int getDescent() {
+        return 0;
+    }
+
+    /**
+     * Gets the leading of the Font associated with this FontMetrics.
+     * 
+     * @return the leading of the Font associated with this FontMetrics.
+     */
+    public int getLeading() {
+        return 0;
+    }
+
+    /**
+     * Gets the LineMetrics object for the specified CharacterIterator
+     * in the specified Graphics.
+     * 
+     * @param ci the CharacterIterator.
+     * @param beginIndex the offset.
+     * @param limit the number of characters to be used.
+     * @param context the Graphics.
+     * 
+     * @return the LineMetrics object for the specified CharacterIterator
+     * in the specified Graphics.
+     */
+    public LineMetrics getLineMetrics(CharacterIterator ci, int beginIndex,
+                                        int limit, Graphics context) {
+        return font.getLineMetrics(ci, beginIndex, limit, 
+                this.getFRCFromGraphics(context));
+    }
+
+    /**
+     * Gets the LineMetrics object for the specified String
+     * in the specified Graphics.
+     * 
+     * @param str the String.
+     * @param context the Graphics.
+     * 
+     * @return the LineMetrics object for the specified String
+     * in the specified Graphics.
+     */
+    public LineMetrics getLineMetrics(String str, Graphics context) {
+        return font.getLineMetrics(str, this.getFRCFromGraphics(context));
+    }
+
+    /**
+     * Gets the LineMetrics object for the specified character 
+     * array in the specified Graphics.
+     * 
+     * @param chars the character array.
+     * @param beginIndex the offset of array.
+     * @param limit the number of characters to be used.
+     * @param context the Graphics.
+     * 
+     * @return the LineMetrics object for the specified character 
+     * array in the specified Graphics.
+     */
+    public LineMetrics getLineMetrics(char[] chars, int beginIndex, int limit,
+                                        Graphics context) {
+        return font.getLineMetrics(chars, beginIndex, limit, 
+                this.getFRCFromGraphics(context));
+    }
+
+    /**
+     * Gets the LineMetrics object for the specified String
+     * in the specified Graphics.
+     * 
+     * @param str the String.
+     * @param beginIndex the offset.
+     * @param limit the number of characters to be used.
+     * @param context the Graphics.
+     * 
+     * @return the LineMetrics object for the specified String
+     * in the specified Graphics.
+     */
+    public LineMetrics getLineMetrics(String str, int beginIndex, int limit,
+                                        Graphics context) {
+        return font.getLineMetrics(str, beginIndex, limit, 
+                this.getFRCFromGraphics(context));
+    }
+
+    /**
+     * Returns the character's maximum bounds in the specified 
+     * Graphics context.
+     * 
+     * @param context the Graphics context.
+     * 
+     * @return the character's maximum bounds in the specified 
+     * Graphics context.
+     */
+    public Rectangle2D getMaxCharBounds(Graphics context) {
+        return this.font.getMaxCharBounds(this.getFRCFromGraphics(context));
+    }
+    
+    /**
+     * Gets the bounds of the specified CharacterIterator 
+     * in the specified Graphics context.
+     * 
+     * @param ci the CharacterIterator.
+     * @param beginIndex the begin offset of the array.
+     * @param limit the number of characters.
+     * @param context the Graphics.
+     * 
+     * @return the bounds of the specified CharacterIterator 
+     * in the specified Graphics context.
+     */
+    public Rectangle2D getStringBounds(CharacterIterator ci, int beginIndex,
+            int limit, Graphics context) {
+        return font.getStringBounds(ci, beginIndex, limit, 
+                this.getFRCFromGraphics(context));
+    }
+
+    /**
+     * Gets the bounds of the specified String 
+     * in the specified Graphics context.
+     * 
+     * @param str the String.
+     * @param beginIndex the begin offset of the array.
+     * @param limit the number of characters.
+     * @param context the Graphics.
+     * 
+     * @return the bounds of the specified String 
+     * in the specified Graphics context.
+     */
+    public Rectangle2D getStringBounds(String str, int beginIndex, int limit,
+            Graphics context) {
+        return font.getStringBounds(str, beginIndex, limit, 
+                this.getFRCFromGraphics(context));
+    }
+
+
+    /**
+     * Gets the bounds of the specified characters array 
+     * in the specified Graphics context.
+     * 
+     * @param chars the characters array.
+     * @param beginIndex the begin offset of the array.
+     * @param limit the number of characters.
+     * @param context the Graphics.
+     * 
+     * @return the bounds of the specified characters array 
+     * in the specified Graphics context.
+     */
+    public Rectangle2D getStringBounds(char[] chars, int beginIndex, int limit,
+            Graphics context) {
+        return font.getStringBounds(chars, beginIndex, limit, 
+                this.getFRCFromGraphics(context));
+    }
+
+    /**
+     * Gets the bounds of the specified String 
+     * in the specified Graphics context.
+     * 
+     * @param str the String.
+     * @param context the Graphics.
+     * 
+     * @return the bounds of the specified String 
+     * in the specified Graphics context.
+     */
+    public Rectangle2D getStringBounds(String str, Graphics context) {
+        return font.getStringBounds(str, this.getFRCFromGraphics(context));
+    }
+
+    /**
+     * Checks if the Font has uniform line metrics or not. 
+     * The Font can contain characters of other fonts for 
+     * covering character set. In this case the Font isn't
+     * uniform. 
+     *  
+     * @return true, if the Font has uniform line metrics, 
+     * false otherwise.
+     */
+    public boolean hasUniformLineMetrics() {
+        return this.font.hasUniformLineMetrics();
+    }
+
+    /**
+     * Returns the distance from the leftmost point to the rightmost 
+     * point on the string's baseline showing the specified array 
+     * of bytes in this Font.   
+     * 
+     * @param data the array of bytes to be measured.
+     * @param off the start offset.
+     * @param len the number of bytes to be measured.
+     * 
+     * @return the advance width of the array.
+     */
+    public int bytesWidth(byte[] data, int off, int len) {
+        int width = 0;
+        if ((off >= data.length) || (off < 0)){
+            // awt.13B=offset off is out of range
+            throw new IllegalArgumentException(Messages.getString("awt.13B")); //$NON-NLS-1$
+        }
+
+        if ((off+len > data.length)){
+            // awt.13C=number of elemets len is out of range
+            throw new IllegalArgumentException(Messages.getString("awt.13C")); //$NON-NLS-1$
+        }
+
+        for (int i = off; i < off+len; i++){
+            width += charWidth(data[i]);
+        }
+
+        return width;
+    }
+
+    /**
+     * Returns the distance from the leftmost point to the rightmost 
+     * point on the string's baseline showing the specified array 
+     * of characters in this Font.   
+     * 
+     * @param data the array of characters to be measured.
+     * @param off the start offset.
+     * @param len the number of bytes to be measured.
+     * 
+     * @return the advance width of the array.
+     */
+    public int charsWidth(char[] data, int off , int len){
+        int width = 0;
+        if ((off >= data.length) || (off < 0)){
+            // awt.13B=offset off is out of range
+            throw new IllegalArgumentException(Messages.getString("awt.13B")); //$NON-NLS-1$
+        }
+
+        if ((off+len > data.length)){
+            // awt.13C=number of elemets len is out of range
+            throw new IllegalArgumentException(Messages.getString("awt.13C")); //$NON-NLS-1$
+        }
+
+        for (int i = off; i < off+len; i++){
+            width += charWidth(data[i]);
+        }
+
+        return width;
+    }
+
+    /**
+     * Returns the distance from the leftmost point to the rightmost 
+     * point of the specified character in this Font.   
+     * 
+     * @param ch the specified unicode point code of 
+     * character to be measured.
+     * 
+     * @return the advance width of the character.
+     */
+    public int charWidth(int ch) {
+        return 0;
+    }
+
+    /**
+     * Returns the distance from the leftmost point to the rightmost 
+     * point of the specified character in this Font.   
+     * 
+     * @param ch the specified character to be measured.
+     * 
+     * @return the advance width of the character.
+     */
+    public int charWidth(char ch) {
+        return 0;
+    }
+
+    /**
+     * Gets the maximum advance width of character in this Font.
+     * 
+     * @return the maximum advance width of character in this Font.
+     */
+    public int getMaxAdvance() {
+        return 0;
+    }
+
+    /**
+     * Gets the maximum font ascent of the Font associated with 
+     * this FontMetrics.
+     * 
+     * @return the maximum font ascent of the Font associated with 
+     * this FontMetrics.
+     */
+    public int getMaxAscent() {
+        return 0;
+    }
+
+    /**
+     * Gets the maximum font descent of character in this Font.
+     * 
+     * @return the maximum font descent of character in this Font.
+     * 
+     * @deprecated Replaced by getMaxDescent() method.
+     */
+    @Deprecated
+    public int getMaxDecent() {
+        return 0;
+    }
+
+    /**
+     * Gets the maximum font descent of character in this Font.
+     * 
+     * @return the maximum font descent of character in this Font.
+     */
+    public int getMaxDescent() {
+        return 0;
+    }
+
+    /**
+     * Gets the advance widths of the characters in the Font.
+     * 
+     * @return the advance widths of the characters in the Font.
+     */
+    public int[] getWidths() {
+        return null;
+    }
+
+    /**
+     * Returns the advance width for the specified String in this Font.
+     * 
+     * @param str String to be measured. 
+     * 
+     * @return the the advance width for the specified String 
+     * in this Font.
+     */
+    public int stringWidth(String str) {
+        return 0;
+    }
+    
+    /**
+     * Returns FontRenderContext instanse of the Graphics context specified.
+     * 
+     * @param context the specified Graphics context
+     * 
+     * @return a FontRenderContext of the specified Graphics context.
+     */
+    private FontRenderContext getFRCFromGraphics(Graphics context){
+        FontRenderContext frc;
+        if (context instanceof Graphics2D) {
+            frc = ((Graphics2D)context).getFontRenderContext();
+        } else {
+            frc = new FontRenderContext(null, false, false);
+        }
+
+        return frc;
+    }
+}
+
diff --git a/awt/java/awt/GradientPaint.java b/awt/java/awt/GradientPaint.java
new file mode 100644
index 0000000..0e06528
--- /dev/null
+++ b/awt/java/awt/GradientPaint.java
@@ -0,0 +1,219 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package java.awt;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.ColorModel;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The GradientPaint class defines a way to fill a Shape with a linear color
+ * gradient pattern. 
+ * <p>
+ * The GradientPaint's fill pattern is determined by two points and two colors, 
+ * plus the cyclic mode option.
+ * Each of the two points is painted with its corresponding color, and on 
+ * the line segment connecting the two points, the color is proportionally
+ * changed between the two colors. For points on the same line which are not 
+ * between the two specified points (outside of the connecting segment) their
+ * color is determined by the cyclic mode option. If the mode is cyclic, then
+ * the rest of the line repeats the color pattern of the connecting segment, 
+ * cycling back and forth between the two colors. If not, the mode is acyclic 
+ * which means that all points 
+ * on the line outside the connecting line segment are given the same 
+ * color as the closest of the two specified points.
+ * <p>
+ * The color of points that are not on the line connecting the two 
+ * specified points are given by perpendicular projection: by taking 
+ * the set of lines perpendicular to the connecting line and for each 
+ * one, the whole line is colored with the same color.
+ */
+public class GradientPaint implements Paint {
+    
+    /** The start point color. */
+    Color color1;
+
+    /** The end color point. */
+    Color color2;
+
+    /** The location of the start point. */
+    Point2D point1;
+
+    /** The location of the end point. */
+    Point2D point2;
+
+    /** The indicator of cycle filling. If TRUE filling 
+     * repeated outside points stripe, if FALSE solid color filling outside. */
+    boolean cyclic;
+
+    /**
+     * Instantiates a new GradientPaint with cyclic or acyclic mode.
+     * 
+     * @param point1 the first specified point.
+     * @param color1 the Color of the first specified point. 
+     * @param point2 the second specified point.
+     * @param color2 the Color of the second specified point.
+     * @param cyclic the cyclic mode - true if the gradient pattern should cycle 
+     * repeatedly between the two colors; false otherwise.
+     */
+    public GradientPaint(Point2D point1, Color color1, Point2D point2,
+            Color color2, boolean cyclic) {
+        if (point1 == null || point2 == null) {
+            // awt.6D=Point is null
+            throw new NullPointerException(Messages.getString("awt.6D")); //$NON-NLS-1$
+        }
+        if (color1 == null || color2 == null) {
+            // awt.6E=Color is null
+            throw new NullPointerException(Messages.getString("awt.6E")); //$NON-NLS-1$
+        }
+
+        this.point1 = point1;
+        this.point2 = point2;
+        this.color1 = color1;
+        this.color2 = color2;
+        this.cyclic = cyclic;
+    }
+
+    /**
+     * Instantiates a new GradientPaint with cyclic or acyclic mode;
+     * points are specified by coordinates.
+     * 
+     * @param x1 the X coordinate of the first point.
+     * @param y1 the Y coordinate of the first point.
+     * @param color1 the color of the first point.
+     * @param x2 the X coordinate of the second point.
+     * @param y2 the Y coordinate of the second point.
+     * @param color2 the color of the second point.
+     * @param cyclic the cyclic mode - true if the gradient pattern should cycle 
+     * repeatedly between the two colors; false otherwise.
+     */
+    public GradientPaint(float x1, float y1, Color color1, float x2, float y2, Color color2,
+            boolean cyclic) {
+        this(new Point2D.Float(x1, y1), color1, new Point2D.Float(x2, y2), color2, cyclic);
+    }
+
+    /**
+     * Instantiates a new acyclic GradientPaint;
+     * points are specified by coordinates.
+     * 
+     * @param x1 the X coordinate of the first point.
+     * @param y1 the Y coordinate of the first point.
+     * @param color1 the color of the first point.
+     * @param x2 the X coordinate of the second point.
+     * @param y2 the Y coordinate of the second point.
+     * @param color2 the color of the second point.
+     */
+    public GradientPaint(float x1, float y1, Color color1, float x2, float y2, Color color2) {
+        this(x1, y1, color1, x2, y2, color2, false);
+    }
+
+    /**
+     * Instantiates a new acyclic GradientPaint.
+     * 
+     * @param point1 the first specified point.
+     * @param color1 the Color of the first specified point. 
+     * @param point2 the second specified point.
+     * @param color2 the Color of the second specified point.
+     */
+    public GradientPaint(Point2D point1, Color color1, Point2D point2, Color color2) {
+        this(point1, color1, point2, color2, false);
+    }
+
+    /**
+     * Creates PaintContext for a color pattern generating. 
+     * 
+     * @param cm the ColorModel of the Paint data.
+     * @param deviceBounds the bounding Rectangle of graphics primitives
+     * being rendered in the device space. 
+     * @param userBounds tthe bounding Rectangle of graphics primitives
+     * being rendered in the user space. 
+     * @param t the AffineTransform from user space into device space.
+     * @param hints the RrenderingHints object.
+     * 
+     * @return the PaintContext for color pattern generating.
+     * 
+     * @see java.awt.Paint#createContext(java.awt.image.ColorModel, java.awt.Rectangle, java.awt.geom.Rectangle2D, java.awt.geom.AffineTransform, java.awt.RenderingHints)
+     */
+    public PaintContext createContext(ColorModel cm, Rectangle deviceBounds,
+            Rectangle2D userBounds, AffineTransform t, RenderingHints hints) {
+        return new GradientPaintContext(cm, t, point1, color1, point2, color2, cyclic);
+    }
+
+    /**
+     * Gets the color of the first point.
+     * 
+     * @return the color of the first point.
+     */
+    public Color getColor1() {
+        return color1;
+    }
+
+    /**
+     * Gets the color of the second point.
+     * 
+     * @return the color of the second point.
+     */
+    public Color getColor2() {
+        return color2;
+    }
+
+    /**
+     * Gets the first point.
+     * 
+     * @return the Point object - the first point. 
+     */
+    public Point2D getPoint1() {
+        return point1;
+    }
+
+    /**
+     * Gets the second point.
+     * 
+     * @return the Point object - the second point.
+     */
+    public Point2D getPoint2() {
+        return point2;
+    }
+
+    /**
+     * Gets the transparency mode for the GradientPaint.
+     * 
+     * @return the transparency mode for the GradientPaint.
+     * 
+     * @see java.awt.Transparency#getTransparency()
+     */
+    public int getTransparency() {
+        int a1 = color1.getAlpha();
+        int a2 = color2.getAlpha();
+        return (a1 == 0xFF && a2 == 0xFF) ? OPAQUE : TRANSLUCENT;
+    }
+
+    /**
+     * Returns the GradientPaint mode: true for cyclic mode, false for
+     * acyclic mode.
+     * 
+     * @return true if the gradient cycles repeatedly between the two colors; 
+     * false otherwise.
+     */
+    public boolean isCyclic() {
+        return cyclic;
+    }
+}
diff --git a/awt/java/awt/GradientPaintContext.java b/awt/java/awt/GradientPaintContext.java
new file mode 100644
index 0000000..74575f5
--- /dev/null
+++ b/awt/java/awt/GradientPaintContext.java
@@ -0,0 +1,204 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Denis M. Kishenko
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.awt.image.ColorModel;
+import java.awt.image.DataBufferInt;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+
+class GradientPaintContext implements PaintContext {
+
+    /**
+     * The size of noncyclic part of color lookup table
+     */
+    static int LOOKUP_SIZE = 256;
+    
+    /**
+     * The index mask to lookup color in the table
+     */
+    static int LOOKUP_MASK = 0x1FF;
+    
+    /**
+     * The min value equivalent to zero. If absolute value less then ZERO it considered as zero.  
+     */
+    static double ZERO = 1E-10;
+
+    /**
+     * The ColorModel user defined for PaintContext
+     */
+    ColorModel cm;
+    
+    /**
+     * The indicator of cycle filling.
+     */
+    boolean cyclic;
+    
+    /**
+     * The integer color value of the start point
+     */
+    int c1;
+    
+    /**
+     * The integer color value of the end point
+     */
+    int c2;
+    
+    /**
+     * The lookup gradient color table 
+     */
+    int[] table;
+
+    /**
+     * The tempopary pre-calculated value to evalutae color index 
+     */
+    int dx;
+    
+    /**
+     * The tempopary pre-calculated value to evalutae color index 
+     */
+    int dy;
+    
+    /**
+     * The tempopary pre-calculated value to evalutae color index 
+     */
+    int delta;
+    
+    /**
+     * Constructs a new GradientPaintcontext
+     * @param cm - not used
+     * @param t - the fill transformation
+     * @param point1 - the start fill point
+     * @param color1 - color of the start point 
+     * @param point2 - the end fill point
+     * @param color2 - color of the end point
+     * @param cyclic - the indicator of cycle filling
+     */
+    GradientPaintContext(ColorModel cm, AffineTransform t, Point2D point1, Color color1, Point2D point2, Color color2, boolean cyclic) {
+        this.cyclic = cyclic;
+        this.cm = ColorModel.getRGBdefault();
+
+        c1 = color1.getRGB();
+        c2 = color2.getRGB();
+
+        double px = point2.getX() - point1.getX();
+        double py = point2.getY() - point1.getY();
+
+        Point2D p = t.transform(point1, null);
+        Point2D bx = new Point2D.Double(px, py);
+        Point2D by = new Point2D.Double(py, -px);
+
+        t.deltaTransform(bx, bx);
+        t.deltaTransform(by, by);
+
+        double vec = bx.getX() * by.getY() - bx.getY() * by.getX();
+
+        if (Math.abs(vec) < ZERO) {
+            dx = dy = delta = 0;
+            table = new int[1];
+            table[0] = c1;
+        } else {
+            double mult = LOOKUP_SIZE * 256 / vec;
+            dx = (int)(by.getX() * mult);
+            dy = (int)(by.getY() * mult);
+            delta = (int)((p.getX() * by.getY() - p.getY() * by.getX()) * mult);
+            createTable();
+        }
+    }
+
+    /**
+     * Create color index lookup table. Calculate 256 step trasformation from 
+     * the start point color to the end point color. Colors multiplied by 256 to do integer calculations. 
+     */
+    void createTable() {
+        double ca = (c1 >> 24) & 0xFF;
+        double cr = (c1 >> 16) & 0xFF;
+        double cg = (c1 >> 8) & 0xFF;
+        double cb = c1 & 0xFF;
+
+        double k = 1.0 / LOOKUP_SIZE;
+        double da = (((c2 >> 24) & 0xFF) - ca) * k;
+        double dr = (((c2 >> 16) & 0xFF) - cr) * k;
+        double dg = (((c2 >> 8) & 0xFF) - cg) * k;
+        double db = ((c2 & 0xFF) - cb) * k;
+
+        table = new int[cyclic ? LOOKUP_SIZE + LOOKUP_SIZE : LOOKUP_SIZE];
+        for(int i = 0; i < LOOKUP_SIZE; i++) {
+            table[i] =
+                (int)ca << 24 |
+                (int)cr << 16 |
+                (int)cg << 8 |
+                (int)cb;
+            ca += da;
+            cr += dr;
+            cg += dg;
+            cb += db;
+        }
+        if (cyclic) {
+            for(int i = 0; i < LOOKUP_SIZE; i++) {
+                table[LOOKUP_SIZE + LOOKUP_SIZE - 1 - i] = table[i];
+            }
+        }
+    }
+
+    public ColorModel getColorModel() {
+        return cm;
+    }
+
+    public void dispose() {
+    }
+
+    public Raster getRaster(int x, int y, int w, int h) {
+        WritableRaster rast = cm.createCompatibleWritableRaster(w, h);
+
+        int[] buf = ((DataBufferInt)rast.getDataBuffer()).getData();
+
+        int c = x * dy - y * dx - delta;
+        int cx = dy;
+        int cy = - w * dy - dx;
+        int k = 0;
+
+        if (cyclic) {
+            for(int j = 0; j < h; j++) {
+                for(int i = 0; i < w; i++) {
+                    buf[k++] = table[(c >> 8) & LOOKUP_MASK];
+                    c += cx;
+                }
+                c += cy;
+            }
+        } else {
+            for(int j = 0; j < h; j++) {
+                for(int i = 0; i < w; i++) {
+                    int index = c >> 8;
+                    buf[k++] = index < 0 ? c1 : index >= LOOKUP_SIZE ? c2 : table[index];
+                    c += cx;
+                }
+                c += cy;
+            }
+        }
+
+        return rast;
+    }
+
+}
+
diff --git a/awt/java/awt/Graphics.java b/awt/java/awt/Graphics.java
new file mode 100644
index 0000000..c20f6bc
--- /dev/null
+++ b/awt/java/awt/Graphics.java
@@ -0,0 +1,737 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Alexey A. Petrenko
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.awt.image.ImageObserver;
+import java.text.AttributedCharacterIterator;
+
+/**
+ * The abstract Graphics class allows applications to draw on a screen
+ * or other rendering target. There are several properties which 
+ * define rendering options: origin point, clipping area, color, font.
+ * <br><br>
+ * The origin point specifies the beggining of the clipping area coordinate 
+ * system. All coordinates used in rendering operations are computed with 
+ * respect to this point. The clipping area defines the boundaries where 
+ * rendering operations can be performed. Rendering operations can't modify 
+ * pixels outside of the clipping area.
+ * <br><br>
+ * The draw and fill methods allow applications to drawing shapes, text, 
+ * images with specified font and color options in the specified part 
+ * of the screen.
+ *    
+ */
+public abstract class Graphics {
+
+    // Constructors
+
+    /**
+     * Instantiates a new Graphics. This constructor is default for Graphics and
+     * can not be called directly. 
+     */
+    protected Graphics() {
+    }
+
+    // Public methods
+
+    /**
+     * Creates a copy of the Graphics object with a new origin and a new 
+     * specified clip area. The new clip area is the rectangle defined by 
+     * the origin point with coordinates X,Y and the given width and height. 
+     * The coordinates of all subsequent rendering operations will be computed
+     * with respect to the new origin and can be performed only within the 
+     * range of the clipping area dimentions. 
+     *  
+     * @param x the X coordinate of the original point
+     * @param y the Y coordinate of the original point
+     * @param width the width of clipping area
+     * @param height the height of clipping area
+     * 
+     * @return the Graphics object with new origin point and clipping area. 
+     */
+    public Graphics create(int x, int y, int width, int height) {
+        Graphics res = create();
+        res.translate(x, y);
+        res.clipRect(0, 0, width, height);
+        return res;
+    }
+
+    /**
+     * Draws the higlighted outline of a rectangle.
+     * 
+     * @param x the X coordinate of the rectangle's top left corner.
+     * @param y the Y coordinate of the rectangle's top left corner.
+     * @param width the width of rectangle.
+     * @param height the height of rectangle.
+     * @param raised a boolean value that determines whether the rectangle 
+     * is drawn as raised or indented.
+     */
+    public void draw3DRect(int x, int y, int width, int height, boolean raised) {
+        // Note: lighter/darker colors should be used to draw 3d rect.
+        // The resulting rect is (width+1)x(height+1). Stroke and paint attributes of
+        // the Graphics2D should be reset to the default values.
+        // fillRect is used instead of drawLine to bypass stroke
+        // reset/set and rasterization.
+
+        Color color = getColor();
+        Color colorUp, colorDown;
+        if (raised) {
+            colorUp = color.brighter();
+            colorDown = color.darker();
+        } else {
+            colorUp = color.darker();
+            colorDown = color.brighter();
+        }
+
+        setColor(colorUp);
+        fillRect(x, y, width, 1);
+        fillRect(x, y+1, 1, height);
+
+        setColor(colorDown);
+        fillRect(x+width, y, 1, height);
+        fillRect(x+1, y+height, width, 1);
+    }
+
+    /**
+     * Draws the text represented by byte array. This method uses the current 
+     * font and color for rendering.
+     * 
+     * @param bytes the byte array which contains the text to be drawn. 
+     * @param off the offset within the byte array of the text to be drawn.
+     * @param len the number of bytes of text to draw. 
+     * @param x the X coordinate where the text is to be drawn.
+     * @param y the Y coordinate where the text is to be drawn.
+     */
+    public void drawBytes(byte[] bytes, int off, int len, int x, int y) {
+        drawString(new String(bytes, off, len), x, y);
+    }
+
+    /**
+     * Draws the text represented by character array. This method uses the 
+     * current font and color for rendering.
+     * 
+     * @param chars the character array. 
+     * @param off the offset within the character array of the text to be drawn.
+     * @param len the number of characters which will be drawn. 
+     * @param x the X coordinate where the text is to be drawn.
+     * @param y the Y coordinate where the text is to be drawn.
+     */
+    public void drawChars(char[] chars, int off, int len, int x, int y) {
+        drawString(new String(chars, off, len), x, y);
+    }
+
+    /**
+     * Draws the outline of a polygon which is defined by Polygon object.
+     * 
+     * @param p the Polygon object.
+     */
+    public void drawPolygon(Polygon p) {
+        drawPolygon(p.xpoints, p.ypoints, p.npoints);
+    }
+
+    /**
+     * Draws the rectangle with the specified width and length and top left 
+     * corner coordinates.
+     * 
+     * @param x the X coordinate of the rectangle's top left corner.
+     * @param y the Y coordinate of the rectangle's top left corner.
+     * @param width the width of the rectangle.
+     * @param height the height of the rectangle.
+     */
+    public void drawRect(int x, int y, int width, int height) {
+        int []xpoints = {x, x, x+width, x+width};
+        int []ypoints = {y, y+height, y+height, y};
+
+        drawPolygon(xpoints, ypoints, 4);
+    }
+
+    /**
+     * Fills the higlighted outline of a rectangle.
+     * 
+     * @param x the X coordinate of the rectangle's top left corner.
+     * @param y the Y coordinate of the rectangle's top left corner.
+     * @param width the width of the rectangle.
+     * @param height the height of the rectangle.
+     * @param raised a boolean value that determines whether the rectangle 
+     * is drawn as raised or indented.
+     */
+    public void fill3DRect(int x, int y, int width, int height, boolean raised) {
+        // Note: lighter/darker colors should be used to draw 3d rect.
+        // The resulting rect is (width)x(height), same as fillRect.
+        // Stroke and paint attributes of the Graphics2D should be reset
+        // to the default values. fillRect is used instead of drawLine to
+        // bypass stroke reset/set and line rasterization.
+        
+        Color color = getColor();
+        Color colorUp, colorDown;
+        if (raised) {
+            colorUp = color.brighter();
+            colorDown = color.darker();
+            setColor(color);
+        } else {
+            colorUp = color.darker();
+            colorDown = color.brighter();
+            setColor(colorUp);
+        }
+
+        width--;
+        height--;
+        fillRect(x+1, y+1, width-1, height-1);
+
+        setColor(colorUp);
+        fillRect(x, y, width, 1);
+        fillRect(x, y+1, 1, height);
+
+        setColor(colorDown);
+        fillRect(x+width, y, 1, height);
+        fillRect(x+1, y+height, width, 1);
+    }
+
+    /**
+     * Fills the polygon with the current color.
+     * 
+     * @param p the Polygon object.
+     */
+    public void fillPolygon(Polygon p) {
+        fillPolygon(p.xpoints, p.ypoints, p.npoints);
+    }
+
+    /**
+     * Disposes of the Graphics.
+     */
+    @Override
+    public void finalize() {
+    }
+
+    /**
+     * Gets the bounds of the current clipping area as a rectangle 
+     * and copies it to an existing rectangle.
+     *  
+     * @param r a Rectangle object where the current clipping area 
+     * bounds are to be copied.
+     * 
+     * @return the bounds of the current clipping area.
+     */
+    public Rectangle getClipBounds(Rectangle r) {
+        Shape clip = getClip();
+
+        if (clip != null) {
+            // TODO: Can we get shape bounds without creating Rectangle object?
+            Rectangle b = clip.getBounds();
+            r.x = b.x;
+            r.y = b.y;
+            r.width = b.width;
+            r.height = b.height;
+        }
+
+        return r;
+    }
+
+    /**
+     * Gets the bounds of the current clipping area as a rectangle.
+     * 
+     * @return a Rectangle object 
+     * 
+     * @deprecated Use {@link #getClipBounds()}
+     */
+    @Deprecated
+    public Rectangle getClipRect() {
+        return getClipBounds();
+    }
+
+    /**
+     * Gets the font metrics of the current font. 
+     * The font metrics object contains information about the rendering 
+     * of a particular font.
+     * 
+     * @return the font metrics of current font.
+     */
+    public FontMetrics getFontMetrics() {
+        return getFontMetrics(getFont());
+    }
+
+    /**
+     * Determines whether or not the specified rectangle intersects the 
+     * current clipping area.
+     *  
+     * @param x the X coordinate of the rectangle.
+     * @param y the Y coordinate of the rectangle.
+     * @param width the width of the rectangle.
+     * @param height the height of the rectangle.
+     * 
+     * @return true, if the specified rectangle intersects the current clipping area, 
+     * overwise false. 
+     */
+    public boolean hitClip(int x, int y, int width, int height) {
+        // TODO: Create package private method Rectangle.intersects(int, int, int, int);
+        return getClipBounds().intersects(new Rectangle(x, y, width, height));
+    }
+
+    /**
+     * Returns string which represents this Graphics object.
+     * 
+     * @return the string which represents this Graphics object.
+     */
+    @Override
+    public String toString() {
+        // TODO: Think about string representation of Graphics.
+        return "Graphics"; //$NON-NLS-1$
+    }
+
+    // Abstract methods
+
+    /**
+     * Clears the specified rectangle. This method fills specified rectangle 
+     * with background color.  
+     * 
+     * @param x the X coordinate of the rectangle.
+     * @param y the Y coordinate of the rectangle.
+     * @param width the width of the rectangle.
+     * @param height the height of the rectangle.
+     */
+    public abstract void clearRect(int x, int y, int width, int height);
+
+    /**
+     * Intersects the current clipping area with a new rectangle. 
+     * If the current clipping area is not defined, the rectangle 
+     * becomes a new clipping area. Rendering operations are only allowed 
+     * within the new the clipping area.    
+     *          
+     * @param x the X coordinate of the rectangle for intersection. 
+     * @param y the Y coordinate of the rectangle for intersection.
+     * @param width the width of the rectangle for intersection.
+     * @param height the height of the rectangle for intersection.
+     */
+    public abstract void clipRect(int x, int y, int width, int height);
+
+    /**
+     * Copies the rectangle area to another area specified by 
+     * a distance (dx, dy) from the original rectangle's location. 
+     * Positive dx and dy values give a new location defined by 
+     * translation to the right and down from the original location, 
+     * negative dx and dy values - to the left and up.
+     * <br><br>
+     * 
+     * @param sx the X coordinate of the rectangle which will be copied. 
+     * @param sy the Y coordinate of the rectangle which will be copied.
+     * @param width the width of the rectangle which will be copied.
+     * @param height the height of the rectangle which will be copied.
+     * @param dx the horizontal distance from the source rectangle's 
+     * location to the copy's location. 
+     * @param dy the vertical distance from the source rectangle's 
+     * location to the copy's location. 
+     */
+    public abstract void copyArea(int sx, int sy, int width, int height, int dx, int dy);
+
+    /**
+     * Creates a new copy of this Graphics.
+     * 
+     * @return a new Graphics context which is a copy of this Graphics.
+     */
+    public abstract Graphics create();
+
+    /**
+     * Disposes of the Graphics. This Graphics object can not be used after 
+     * calling this method.  
+     */
+    public abstract void dispose();
+
+    /**
+     * Draws the arc covering the specified rectangle and using the current color. 
+     * The rectangle is defined by the origin point (X, Y) and dimentions 
+     * (width and height). The arc center is the the center of specified rectangle. 
+     * The angle origin is 3 o'clock position, the positive angle is counted as a 
+     * counter-clockwise rotation, the negotive angle is counted as clockwise rotation.   
+     * 
+     * @param x the X origin coordinate of the rectangle which scales the arc. 
+     * @param y the Y origin coordinate of the rectangle which scales the arc.
+     * @param width the width of the rectangle which scales the arc.
+     * @param height the height of the rectangle which scales the arc.
+     * @param sa start angle - the origin angle of arc.
+     * @param ea arc angle - the angular arc value relative to the start angle. 
+     */
+    public abstract void drawArc(int x, int y, int width, int height, int sa, int ea);
+
+    /**
+     * Draws the specified image with the defined background color. 
+     * The top left corner of image will be drawn at point (x, y) 
+     * in current coordinate system. The image loading process notifies the
+     * specified Image Observer. This method returns true if the image
+     * has loaded, overwise it returns false.       
+     * 
+     * @param img the image which will be drawn. 
+     * @param x the X coordinate of the image top left corner. 
+     * @param y the Y coordinate of the image top left corner. 
+     * @param bgcolor the background color.
+     * @param observer the ImageObserver object which should be notified about image loading process.
+     * 
+     * @return true, if loading image is successful or image is null, overwise false.
+     */
+    public abstract boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer);
+
+    /**
+     * Draws the specified image. 
+     * The top left corner of image will be drawn at point (x, y) 
+     * in current coordinate system. The image loading process notifies the
+     * specified Image Observer. This method returns true if the image
+     * has loaded, overwise it returns false. 
+     * 
+     * @param img the image which will be drawn. 
+     * @param x the X coordinate of the image top left corner. 
+     * @param y the Y coordinate of the image top left corner. 
+     * @param observer the ImageObserver object which should be notified about image loading process.
+     * 
+     * @return true, if loading image is successful or image is null, overwise false.
+     */
+    public abstract boolean drawImage(Image img, int x, int y, ImageObserver observer);
+
+    /**
+     * Scales the specified image to fit in the specified rectangle and 
+     * draws it with the defined background color. The top left corner 
+     * of the image will be drawn at the point (x, y) in current coordinate 
+     * system. The non-opaque pixels will be drawn in the background color. 
+     * The image loading process notifies the specified Image Observer. 
+     * This method returns true if the image has loaded, overwise it returns false. 
+     * 
+     * @param img the image which will be drawn.
+     * @param x the X coordinate of the image's top left corner.
+     * @param y the Y coordinate of the image's top left corner. 
+     * @param width the width of rectangle which scales the image.
+     * @param height the height of rectangle which scales the image.
+     * @param bgcolor the background color.
+     * @param observer the ImageObserver object which should be notified about image loading process.
+     * 
+     * @return true, if loading image is successful or image is null, overwise false.
+     */
+    public abstract boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver observer);
+
+    /**
+     * Scales the specified image to fit in the specified rectangle and 
+     * draws it. The top left corner of the image will be drawn at the 
+     * point (x, y) in current coordinate system. The image loading process 
+     * notifies the specified Image Observer. 
+     * This method returns true if the image has loaded, overwise it returns false. 
+     * 
+     * @param img the image which will be drawn.
+     * @param x the X coordinate of the image top left corner.
+     * @param y the Y coordinate of the image top left corner. 
+     * @param width the width of rectangle which scales the image.
+     * @param height the height of rectangle which scales the image.
+     * @param observer the ImageObserver object which should be notified about image loading process.
+     * 
+     * @return true, if loading image is successful or image is null, overwise false.
+     */
+    public abstract boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer);
+
+    /**
+     * Scales the specified area of the specified image to fit in the rectangle area 
+     * defined by its corners coordinates and draws the sub-image with the specified 
+     * background color. The sub-image to be drawn is defined by its top left 
+     * corner coordinates (sx1, sy1) and bottom right corner coordinates (sx2, sy2)
+     * computed with respect to the origin (top left corner) of the source image.
+     * The non opaque pixels will be drawn in the background color. The 
+     * image loading process notifies specified Image Observer. 
+     * This method returns true if the image
+     * has loaded, overwise it returns false. 
+     * 
+     * @param img the image which will be drawn.
+     * @param dx1 the X top left corner coordinate of the destination rectangle area. 
+     * @param dy1 the Y top left corner coordinate of the destination rectangle area.
+     * @param dx2 the X bottom right corner coordinate of the destination rectangle area.
+     * @param dy2 the Y bottom right corner coordinate of the destination rectangle area.
+     * @param sx1 the X top left corner coordinate of the area to be drawn within the source image.
+     * @param sy1 the Y top left corner coordinate of the area to be drawn within the source image.
+     * @param sx2 the X bottom right corner coordinate of the area to be drawn within the source image.
+     * @param sy2 the Y bottom right corner coordinate of the area to be drawn within the source image.
+     * @param bgcolor the background color.
+     * @param observer the ImageObserver object which should be notified about image loading process.
+     * 
+     * @return true, if loading image is successful or image is null, overwise false.
+     */
+    public abstract boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, Color bgcolor, ImageObserver observer);
+
+    /**
+     * Scales the specified area of the specified image to fit in the rectangle area 
+     * defined by its corners coordinates and draws the sub-image. The sub-image 
+     * to be drawn is defined by its top left 
+     * corner coordinates (sx1, sy1) and bottom right corner coordinates (sx2, sy2)
+     * computed with respect to the origin (top left corner) of the source image.
+     * The image loading process notifies specified Image Observer. 
+     * This method returns true if the image
+     * has loaded, overwise it returns false. 
+     * 
+     * @param img the image which will be drawn.
+     * @param dx1 the X top left corner coordinate of the destination rectangle area. 
+     * @param dy1 the Y top left corner coordinate of the destination rectangle area.
+     * @param dx2 the X bottom right corner coordinate of the destination rectangle area.
+     * @param dy2 the Y bottom right corner coordinate of the destination rectangle area.
+     * @param sx1 the X top left corner coordinate of the area to be drawn within the source image.
+     * @param sy1 the Y top left corner coordinate of the area to be drawn within the source image.
+     * @param sx2 the X bottom right corner coordinate of the area to be drawn within the source image.
+     * @param sy2 the Y bottom right corner coordinate of the area to be drawn within the source image.
+     * @param observer the ImageObserver object which should be notified about image loading process.
+     * 
+     * @return true, if loading image is successful or image is null, overwise false.
+     */
+    public abstract boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer);
+    
+    /**
+     * Draws a line from the point (x1, y1) to the point (x2, y2). 
+     * This method draws the line with current color 
+     * which can be changed by setColor(Color c) method.
+     * 
+     * @param x1 the X coordinate of the first point.
+     * @param y1 the Y coordinate of the first point.
+     * @param x2 the X coordinate of the second point.
+     * @param y2 the Y coordinate of the second point.
+     */
+    public abstract void drawLine(int x1, int y1, int x2, int y2);
+
+    /**
+     * Draws the ouline of an oval to fit in the rectangle defined
+     * by the given width, height, and top left corner.
+     * 
+     * @param x the X top left corner oval coordinate
+     * @param y the Y top left corner oval coordinate
+     * @param width the oval width
+     * @param height the oval height
+     */
+    public abstract void drawOval(int x, int y, int width, int height);
+
+    /**
+     * Draws the outline of a polygon. The polygon vertices are defined by points 
+     * with xpoints[i], ypoints[i]  as coordinates. The polygon edges are the
+     * lines from the points with (xpoints[i-1], ypoints[i-1]) coordinates to   
+     * the points with (xpoints[i], ypoints[i]) coordinates, for 0 < i < npoints +1.
+     * 
+     * @param xpoints the array of X coordinates of the polygon vertices.
+     * @param ypoints the array of Y coordinates of the polygon vertices.
+     * @param npoints the number of polygon vertices/points.
+     */
+    public abstract void drawPolygon(int[] xpoints, int[] ypoints, int npoints);
+
+    /**
+     * Draws a set of connected lines which are defined by the x and y coordinate arrays.  
+     * The polyline is closed if coordinates of the first point are the same as 
+     * coordinates of the last point.
+     * 
+     * @param xpoints the array of X point coordinates.
+     * @param ypoints the array of Y point coordinates.
+     * @param npoints the number of points.
+     */
+    public abstract void drawPolyline(int[] xpoints, int[] ypoints, int npoints);
+
+    /**
+     * Draws the outline of a rectangle with round corners.
+     * 
+     * @param x the X coordinate of the rectangle's top left corner.
+     * @param y the Y coordinate of the rectangle's top left corner.
+     * @param width the width of the rectangle.
+     * @param height the height of the rectangle.
+     * @param arcWidth the arc width for the corners.
+     * @param arcHeight the arc height for the corners.
+     */
+    public abstract void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight);
+
+    /**
+     * Draws a text defined by an iterator. The iterator should specify the font 
+     * for every character. 
+     *  
+     * @param iterator the iterator.
+     * @param x the X coordinate of the firt character.
+     * @param y the Y coordinate of the first character.
+     */
+    public abstract void drawString(AttributedCharacterIterator iterator, int x, int y);
+
+    /**
+     * Draws a text defined by a string. This method draws the text with current
+     * font and color.
+     * 
+     * @param str the string. 
+     * @param x the X coordinate of the firt character.
+     * @param y the Y coordinate of the first character.
+     */
+    public abstract void drawString(String str, int x, int y);
+
+    /**
+     * Fills the arc covering the rectangle and using the current color. 
+     * The rectangle is defined by the origin point (X, Y) and dimentions (width and height). 
+     * The arc center is the the center of specified rectangle. 
+     * The angle origin is at the 3 o'clock position, and a positive angle gives  
+     * counter-clockwise rotation, a negative angle gives clockwise rotation.
+     *  
+     * @param x the X origin coordinate of the rectangle which scales the arc. 
+     * @param y the Y origin coordinate of the rectangle which scales the arc.
+     * @param width the width of the rectangle which scales the arc.
+     * @param height the height of the rectangle which scales the arc.
+     * @param sa start angle - the origin angle of arc.
+     * @param ea arc angle - the angular arc value relative to the start angle. 
+     */
+    public abstract void fillArc(int x, int y, int width, int height, int sa, int ea);
+
+    /**
+     * Fills an oval with the current color where the oval is defined by the 
+     * bounding rectangle with the given width, height, and top left corner.
+     * 
+     * @param x the X top left corner oval coordinate.
+     * @param y the Y top left corner oval coordinate.
+     * @param width the oval width.
+     * @param height the oval height.
+     */
+    public abstract void fillOval(int x, int y, int width, int height);
+
+    /**
+     * Fills a polygon with the current color. The polygon vertices are defined by the points 
+     * with xpoints[i], ypoints[i] as coordinates. The polygon edges are the
+     * lines from the points with (xpoints[i-1], ypoints[i-1]) coordinates to   
+     * the points with (xpoints[i], ypoints[i]) coordinates, for 0 < i < npoints +1.
+     * 
+     * @param xpoints the array of X coordinates of the polygon vertices.
+     * @param ypoints the array of Y coordinates of the polygon vertices.
+     * @param npoints the number of polygon vertices/points.
+     */
+    public abstract void fillPolygon(int[] xpoints, int[] ypoints, int npoints);
+
+    /**
+     * Fills a rectangle with the current color. 
+     * The rectangle is defined by its width and length and top left corner coordinates.
+     * 
+     * @param x the X coordinate of the rectangle's top left corner.
+     * @param y the Y coordinate of the rectangle's top left corner.
+     * @param width the width of rectangle.
+     * @param height the height of rectangle.
+     */
+    public abstract void fillRect(int x, int y, int width, int height);
+
+    /**
+     * Fills a round cornered rectangle with the current color.
+     * 
+     * @param x the X coordinate of the top left corner of the bounding rectangle.
+     * @param y the Y coordinate of the top left corner of the bounding rectangle.
+     * @param width the width of the bounding rectangle.
+     * @param height the height of the bounding rectangle.
+     * @param arcWidth the arc width at the corners.
+     * @param arcHeight the arc height at the corners.
+     */
+    public abstract void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight);
+
+    /**
+     * Gets the clipping area.
+     * <br> <br>
+     *  
+     * @return a Shape object of the clipping area or null if it is not set.
+     */
+    public abstract Shape getClip();
+
+    /**
+     * Gets the bounds of the current clipping area as a rectangle.
+     *  
+     * @return a Rectangle object which represents the bounds of the current clipping area. 
+     */
+    public abstract Rectangle getClipBounds();
+
+    /**
+     * Gets the current color of Graphics.
+     * 
+     * @return the current color.
+     */
+    public abstract Color getColor();
+
+    /**
+     * Gets the current font of Graphics.
+     * 
+     * @return the current font.
+     */
+    public abstract Font getFont();
+
+    /**
+     * Gets the font metrics of the specified font. 
+     * The font metrics object contains information about the rendering of a particular font.
+     * 
+     * @param font the specified font
+     * 
+     * @return the font metrics for the specified font.
+     */
+    public abstract FontMetrics getFontMetrics(Font font);
+
+    /**
+     * Sets the new clipping area specified by rectangle. The new clipping area 
+     * doesn't depend on the window's visibility. Rendering operations can't be performed 
+     * outside new clipping area.
+     * 
+     * @param x the X coordinate of the new clipping rectangle.
+     * @param y the Y coordinate of the new clipping rectangle.
+     * @param width the width of the new clipping rectangle.
+     * @param height the height of the new clipping rectangle.
+     */
+    public abstract void setClip(int x, int y, int width, int height);
+
+    /**
+     * Sets the new clipping area to be the area specified by Shape object. 
+     * The new clipping area doesn't depend on the window's visibility. 
+     * Rendering operations can't be performed outside new clipping area.
+     * 
+     * @param clip a Shape object which representes new clipping area.
+     */
+    public abstract void setClip(Shape clip);
+
+    /**
+     * Sets the current Graphics color. All rendering operations with this Graphics
+     * will use this color.
+     * 
+     * @param c the new color.
+     */
+    public abstract void setColor(Color c);
+
+    /**
+     * Sets the current Graphics font. All rendering operations with this Graphics
+     * will use this font.
+     * 
+     * @param font the new font.
+     */
+    public abstract void setFont(Font font);
+
+    /**
+     * Sets the paint mode for the Graphics which overwrites all rendering 
+     * operations with the current color.
+     *  
+     */
+    public abstract void setPaintMode();
+
+    /**
+     * Sets the XOR mode for the Graphics which changes a pixel from
+     * the current color to the specified XOR color.
+     * <br> <br>
+     * 
+     * @param color the new XOR mode
+     */
+    public abstract void setXORMode(Color color);
+
+    /**
+     * Translates the origin of Graphics current coordinate system 
+     * to the point with X, Y coordinates in the current coordinate system.
+     * All rendering operation in this Graphics will be related to the new origin.
+     * 
+     * @param x the X coordinate of the origin
+     * @param y the Y coordinate of the origin
+     */
+    public abstract void translate(int x, int y);
+}
diff --git a/awt/java/awt/Graphics2D.java b/awt/java/awt/Graphics2D.java
new file mode 100644
index 0000000..2ff5e0c
--- /dev/null
+++ b/awt/java/awt/Graphics2D.java
@@ -0,0 +1,456 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package java.awt;
+
+import java.awt.font.GlyphVector;
+import java.awt.font.FontRenderContext;
+import java.awt.geom.AffineTransform;
+import java.awt.image.BufferedImage;
+import java.awt.image.BufferedImageOp;
+import java.awt.image.ImageObserver;
+import java.awt.image.RenderedImage;
+import java.awt.image.renderable.RenderableImage;
+import java.text.AttributedCharacterIterator;
+import java.util.Map;
+
+/**
+ * The Graphics2D class extends Graphics class and provides more capabilities
+ * for rendering text, images, shapes. This provides methods to peform 
+ * transformation of coordinate system, color management, and text layout. 
+ * The following attributes exist for rendering:
+ * <ul>
+ * <li>Color - current Graphics2D color;</li>
+ * <li>Font - current Graphics2D font;</li>
+ * <li>Stroke - pen with a width of 1 pixel;</li>  
+ * <li>Transform - current Graphics2D Transformation;</li>
+ * <li>Composite - alpha compositing rules for combining source and destination colors.</li>
+ * </ul> 
+ */
+public abstract class Graphics2D extends Graphics {
+    
+    /**
+     * Instantiates a new Graphics2D object. This constructor should never be
+     * called directly.
+     */
+    protected Graphics2D() {
+        super();
+    }
+
+    /**
+     * Adds preferences for the rendering algorithms. The preferences
+     * are arbitrary and specified by Map objects. All specified by Map object
+     * preferencies can be modified. 
+     * 
+     * @param hints the rendering hints.
+     */
+    public abstract void addRenderingHints(Map<?, ?> hints);
+
+    /**
+     * Intersects the current clipping area with the specified Shape 
+     * and the result becomes a new clipping area. 
+     * If current clipping area is not defined, the Shape 
+     * becomes the new clipping area. No rendering operations 
+     * are allowed outside the clipping area.  
+     * 
+     * @param s the specified Shape object which will be intersected 
+     * with current clipping area.
+     */
+    public abstract void clip(Shape s);
+
+    /**
+     * Draws the outline of the specified Shape.
+     * 
+     * @param s the Shape which ouline is drawn.
+     */
+    public abstract void draw(Shape s);
+
+    /**
+     * Draws the specified GlyphVector object's text at the point x, y. 
+     * 
+     * @param g the GlyphVector object to be drawn.
+     * @param x the X position where the GlyphVector's text should 
+     * be rendered.  
+     * @param y the Y position where the GlyphVector's text should 
+     * be rendered.
+     */
+    public abstract void drawGlyphVector(GlyphVector g, float x, float y);
+
+    /**
+     * Draws the BufferedImage -- modified according to the operation
+     * BufferedImageOp -- at the point x, y.
+     * 
+     * @param img the BufferedImage to be rendered.
+     * @param op the filter to be applied to the image before rendering. 
+     * @param x the X coordinate of the point where the image's upper left corner
+     * will be placed.
+     * @param y the Y coordinate of the point where the image's upper left corner
+     * will be placed.
+     */
+    public abstract void drawImage(BufferedImage img, BufferedImageOp op, int x, int y);
+
+    /**
+     * Draws BufferedImage transformed from image space into user space 
+     * according to the AffineTransform xform and notifies the ImageObserver.
+     *  
+     * @param img the BufferedImage to be rendered.
+     * @param xform the affine transformation from the image to the user space.
+     * @param obs the ImageObserver to be notified about the image conversion.
+     * 
+     * @return true, if the image is successfully loaded and rendered, 
+     * or it's null, otherwise false.
+     */
+    public abstract boolean drawImage(Image img, AffineTransform xform, ImageObserver obs);
+
+    /**
+     * Draws a RenderableImage which is transformed from image space into user 
+     * according to the AffineTransform xform.
+     *  
+     * @param img the RenderableImage to be rendered.
+     * @param xform the affine transformation from image to user space.
+     */
+    public abstract void drawRenderableImage(RenderableImage img, AffineTransform xform);
+
+    /**
+     * Draws a RenderedImage which is transformed from image space into user 
+     * according to the AffineTransform xform.
+     *  
+     * @param img the RenderedImage to be rendered.
+     * @param xform the affine transformation from image to user space.
+     */
+    public abstract void drawRenderedImage(RenderedImage img, AffineTransform xform);
+
+    /**
+     * Draws the string specified by the AttributedCharacterIterator. 
+     * The first character's position is specified by the X, Y parameters.   
+     * 
+     * @param iterator whose text is drawn.
+     * @param x the X position where the first character is drawn. 
+     * @param y the Y position where the first character is drawn.
+     */
+    public abstract void drawString(AttributedCharacterIterator iterator, float x, float y);
+
+    /**
+     * Draws the string specified by the AttributedCharacterIterator. 
+     * The first character's position is specified by the X, Y parameters.   
+     * 
+     * @param iterator whose text is drawn.
+     * @param x the X position where the first character is drawn. 
+     * @param y the Y position where the first character is drawn.
+     * 
+     * @see java.awt.Graphics#drawString(AttributedCharacterIterator, int, int)
+     */
+    @Override
+    public abstract void drawString(AttributedCharacterIterator iterator, int x, int y);
+
+    /**
+     * Draws the String whose the first character position is specified 
+     * by the parameters X, Y.   
+     * 
+     * @param s the String to be drawn.
+     * @param x the X position of the first character. 
+     * @param y the Y position of the first character.
+     */
+    public abstract void drawString(String s, float x, float y);
+
+    /**
+     * Draws the String whose the first character coordinates are specified 
+     * by the parameters X, Y.   
+     * 
+     * @param str the String to be drawn.
+     * @param x the X coordinate of the first character. 
+     * @param y the Y coordinate of the first character.
+     * 
+     * @see java.awt.Graphics#drawString(String, int, int)
+     */
+    @Override
+    public abstract void drawString(String str, int x, int y);
+
+    /**
+     * Fills the interior of the specified Shape.
+     * 
+     * @param s the Shape to be filled.
+     */
+    public abstract void fill(Shape s);
+
+    /**
+     * Gets the background color.
+     * 
+     * @return the current background color.
+     */
+    public abstract Color getBackground();
+
+    /**
+     * Gets the current composite of the Graphics2D.
+     * 
+     * @return the current composite which specifies the compositing style.
+     */
+    public abstract Composite getComposite();
+
+    /**
+     * Gets the device configuration.
+     * 
+     * @return the device configuration
+     */
+    public abstract GraphicsConfiguration getDeviceConfiguration();
+
+    /**
+     * Gets the rendering context of the Font.
+     * 
+     * @return the FontRenderContext.
+     */
+    public abstract FontRenderContext getFontRenderContext();
+
+    /**
+     * Gets the current Paint of Graphics2D.
+     * 
+     * @return the current Paint of Graphics2D.
+     */
+    public abstract Paint getPaint();
+
+    /**
+     * Gets the value of single preference for specified key. 
+     * 
+     * @param key the specified key of the rendering hint.
+     * 
+     * @return the value of rendering hint for specified key.
+     */
+    public abstract Object getRenderingHint(RenderingHints.Key key);
+
+    /**
+     * Gets the set of the rendering preferences as a collection of 
+     * key/value pairs.
+     * 
+     * @return the RenderingHints which contains the rendering preferences.
+     */
+    public abstract RenderingHints getRenderingHints();
+
+    /**
+     * Gets current stroke of the Graphics2D.
+     * 
+     * @return current stroke of the Graphics2D.
+     */
+    public abstract Stroke getStroke();
+
+    /**
+     * Gets current affine transform of the Graphics2D.
+     * 
+     * @return current AffineTransform of the Graphics2D.
+     */
+    public abstract AffineTransform getTransform();
+
+    /**
+     * Determines wether or not the specified Shape intersects the specified 
+     * Rectangle. If the onStroke parameter is true, this method 
+     * checks whether or not the specified Shape outline intersects the specified 
+     * Rectangle, otherwise this method checks whether or not the specified 
+     * Shape's interior intersects the specified Rectangle.   
+     * 
+     * @param rect the specified Rectangle.
+     * @param s the Shape to check for intersection.
+     * @param onStroke the parameter determines whether or not this method checks
+     * for intersection of the Shape outline or of the Shape interior with 
+     * the Rectangle. 
+     * 
+     * @return true, if there is a hit, otherwise false.
+     */
+    public abstract boolean hit(Rectangle rect, Shape s, boolean onStroke);
+
+    /**
+     * Performs a rotation transform relative to current Graphics2D Transform.
+     * The coordinate system is rotated by the specified angle in radians relative to 
+     * current origin.
+     * 
+     * @param theta the angle of rotation in radians.
+     */
+    public abstract void rotate(double theta);
+
+    /**
+     * Performs a translated rotation transform relative to current Graphics2D 
+     * Transform. The coordinate system is rotated by the specified angle in radians 
+     * relative to current origin and then moved to point (x, y).
+     * 
+     * Is this right?
+     * 
+     * @param theta the angle of rotation in radians.
+     * @param x the X coordinate.
+     * @param y the Y coordinate. 
+     */
+    public abstract void rotate(double theta, double x, double y);
+
+    /**
+     * Performs a linear scale transform relative to current Graphics2D Transform.
+     * The coordinate system is rescaled vertically and horizontally 
+     * by the specified parameters.
+     * 
+     * @param sx the scaling factor by which the X coordinate is multiplied.   
+     * @param sy the scaling factor by which the Y coordinate is multiplied.   
+     */
+    public abstract void scale(double sx, double sy);
+
+    /**
+     * Sets a new background color for clearing rectangular areas. 
+     * The clearRect method uses the current background color. 
+     * 
+     * @param color the new background color.
+     */
+    public abstract void setBackground(Color color);
+
+    /**
+     * Sets the current composite for Graphics2D. 
+     * 
+     * @param comp the Composite object.
+     */
+    public abstract void setComposite(Composite comp);
+
+    /**
+     * Sets the paint for Graphics2D.
+     * 
+     * @param paint the Paint object.
+     */
+    public abstract void setPaint(Paint paint);
+
+    /**
+     * Sets a key-value pair in the current RenderingHints map.
+     * 
+     * @param key the key of the rendering hint to set.
+     * @param value the value to set for the rendering hint.
+     */
+    public abstract void setRenderingHint(RenderingHints.Key key, Object value);
+
+    /**
+     * Replaces the current rendering hints with the specified rendering preferences.
+     * 
+     * @param hints the new Map of rendering hints.
+     */
+    public abstract void setRenderingHints(Map<?, ?> hints);
+
+    /**
+     * Sets the stroke for the Graphics2D.
+     * 
+     * @param s the Stroke object.
+     */
+    public abstract void setStroke(Stroke s);
+
+    /**
+     * Overwrite the current Transform of the Graphics2D. The specified Transform 
+     * should be received from the getTransform() method and should be used 
+     * only for restoring the original Graphics2D transform after calling
+     * draw or fill methods. 
+     * 
+     * @param Tx the specified Transform.
+     */
+    public abstract void setTransform(AffineTransform Tx);
+
+    /**
+     * Performs a shear transform relative to current Graphics2D Transform.
+     * The coordinate system is shifted by the specified multipliers relative to 
+     * current position.
+     * 
+     * @param shx the multiplier by which the X coordinates shift position
+     * along X axis as a function of Y coordinates.   
+     * @param shy the multiplier by which the Y coordinates shift position
+     * along Y axis as a function of X coordinates.   
+     */
+    public abstract void shear(double shx, double shy);
+
+    /**
+     * Concatenates the AffineTransform object with current Transform 
+     * of this Graphics2D. The transforms are applied in reverse order
+     * with the last specified transform applied first and the next
+     * transformation applied to the result of previous transformation. 
+     * More precisely, if Cx is the current Graphics2D transform, the 
+     * transform method's result with Tx as the parameter
+     * is the transformation Rx, where Rx(p) = Cx(Tx(p)), for p - a point
+     * in current coordinate system. Rx becomes the current Transform   
+     * for this Graphics2D.
+     * 
+     * @param Tx the AffineTransform object to be concatenated with 
+     * current Transform.
+     */
+    public abstract void transform(AffineTransform Tx);
+
+    /**
+     * Performs a translate transform relative to current Graphics2D Transform.
+     * The coordinate system is moved by the specified distance relative 
+     * to current position.
+     * 
+     * @param tx the translation distance along the X axis.
+     * @param ty the translation distance along the Y axis.
+     */
+    public abstract void translate(double tx, double ty);
+
+    /**
+     * Moves the origin Graphics2D Transform to the point with x, y
+     * coordinates in current coordinate system. The new origin of coordinate 
+     * system is moved to the (x, y) point accordingly. All rendering and 
+     * transform operations are performed relative to this new origin.
+     * 
+     * @param x the X coordinate.
+     * @param y the Y coordinate. 
+     * 
+     * @see java.awt.Graphics#translate(int, int)
+     */
+    @Override
+    public abstract void translate(int x, int y);
+
+    /**
+     * Fills a 3D rectangle with the current color. 
+     * The rectangle is specified by its width, height, and top left corner 
+     * coordinates.
+     * 
+     * @param x the X coordinate of the rectangle's top left corner.
+     * @param y the Y coordinate of the rectangle's top left corner.
+     * @param width the width of rectangle.
+     * @param height the height of rectangle.
+     * @param raised a boolean value that determines whether the rectangle 
+     * is drawn as raised or indented.
+     * 
+     * @see java.awt.Graphics#fill3DRect(int, int, int, int, boolean)
+     */
+    @Override
+    public void fill3DRect(int x, int y, int width, int height, boolean raised) {
+        // According to the spec, color should be used instead of paint,
+        // so Graphics.fill3DRect resets paint and
+        // it should be restored after the call
+        Paint savedPaint = getPaint();
+        super.fill3DRect(x, y, width, height, raised);
+        setPaint(savedPaint);
+    }
+
+    /**
+     * Draws the higlighted outline of a rectangle.
+     * 
+     * @param x the X coordinate of the rectangle's top left corner.
+     * @param y the Y coordinate of the rectangle's top left corner.
+     * @param width the width of rectangle.
+     * @param height the height of rectangle.
+     * @param raised a boolean value that determines whether the rectangle 
+     * is drawn as raised or indented.
+     *       
+     * @see java.awt.Graphics#draw3DRect(int, int, int, int, boolean)
+     */
+    @Override
+    public void draw3DRect(int x, int y, int width, int height, boolean raised) {
+        // According to the spec, color should be used instead of paint,
+        // so Graphics.draw3DRect resets paint and
+        // it should be restored after the call
+        Paint savedPaint = getPaint();
+        super.draw3DRect(x, y, width, height, raised);
+        setPaint(savedPaint);
+    }
+}
\ No newline at end of file
diff --git a/awt/java/awt/GraphicsConfiguration.java b/awt/java/awt/GraphicsConfiguration.java
new file mode 100644
index 0000000..8bec253
--- /dev/null
+++ b/awt/java/awt/GraphicsConfiguration.java
@@ -0,0 +1,217 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Alexey A. Petrenko
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.awt.geom.AffineTransform;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.VolatileImage;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The GraphicsConfiguration class contains the characteristics of graphics
+ * devices such as a printer or monitor, and represents device's capabilities
+ * and modes. Many GraphicsConfiguration objects can be associated with
+ * single graphics device.
+ */
+public abstract class GraphicsConfiguration {
+   
+   /**
+     * Constructor could not be used directly and should be obtained in 
+     * extended classes. 
+    */
+
+    protected GraphicsConfiguration() {
+    }
+
+
+   /**
+    * Creates BufferedImage image object with a data layout and color model 
+    * compatible with this GraphicsConfiguration with specified width 
+    * and height parameters.
+    * 
+    * @param width the width of BufferedImage.
+    * @param height the height of BufferedImage.
+    * 
+    * @return the BufferedImage object with specified width and height 
+    * parameters.
+    */
+    public abstract BufferedImage createCompatibleImage(int width, int height);
+
+    /**
+     * Creates a BufferedImage that has the specified width, height,
+     * transparency and has a data layout and color model compatible with this 
+     * GraphicsConfiguration. 
+     * 
+     * @param width the width of image.
+     * @param height the height  of image.
+     * @param transparency the transparency mode.
+     * 
+     * @return the BufferedImage object.
+     */
+    public abstract BufferedImage createCompatibleImage(int width, int height, int transparency);
+
+    /**
+     * Creates a VolatileImage that has the specified width and height 
+     * and has a data layout and color model compatible with this 
+     * GraphicsConfiguration. 
+     * 
+     * @param width the width of image.
+     * @param height the height of image.
+     * 
+     * @return the VolatileImage object.
+     */
+    public abstract VolatileImage createCompatibleVolatileImage(int width, int height);
+
+    /**
+     * Creates a VolatileImage that supports the specified width, height,
+     * transparency and has a data layout and color model compatible with this 
+     * GraphicsConfiguration. 
+     * 
+     * @param width the width of image.
+     * @param height the height of image.
+     * @param transparency the transparency mode.
+     * 
+     * @return the VolatileImage object.
+     */
+    public abstract VolatileImage createCompatibleVolatileImage(int width, int height, int transparency);
+
+    /**
+     * Gets the bounds of area covered by the GraphicsConfiguration in the
+     * device coordinates space.
+     * 
+     * @return the Rectangle of GraphicsConfiguration's bounds.
+     */
+    public abstract Rectangle getBounds();
+
+    /**
+     * Gets the ColorModel of the GraphicsConfiguration.
+     * 
+     * @return the ColorModel object of the GraphicsConfiguration.
+     */
+    public abstract ColorModel getColorModel();
+
+    /**
+     * Gets the ColorModel of the GraphicsConfiguration which 
+     * supports specified Transparency.
+     * 
+     * @param transparency the Transparency mode: OPAQUE, BITMASK, or
+     * TRANSLUCENT.
+     * 
+     * @return the ColorModel of the GraphicsConfiguration which 
+     * supports specified Transparency.
+     */
+    public abstract ColorModel getColorModel(int transparency);
+
+    /**
+     * Gets the default AffineTransform of the GraphicsConfiguration.
+     * This method translates user coordinates to device coordinates.
+     * 
+     * @return the default AffineTransform of the GraphicsConfiguration.
+     */
+    public abstract AffineTransform getDefaultTransform();
+
+    /**
+     * Gets the GraphicsDevice of the GraphicsConfiguration.
+     * 
+     * @return the GraphicsDevice of the GraphicsConfiguration.
+     */
+    public abstract GraphicsDevice getDevice();
+
+    /**
+     * Gets the normalizing AffineTransform of the GraphicsConfiguration.
+     * 
+     * @return the normalizing AffineTransform of the GraphicsConfiguration.
+     */
+    public abstract AffineTransform getNormalizingTransform();
+
+
+    /**
+     * Creates VolatileImage with specified width, height, ImageCapabilities;
+     * a data layout and color model compatible with this GraphicsConfiguration. 
+     *  
+     * @param width the width of image.
+     * @param height the height of image.
+     * @param caps the ImageCapabilities object.
+     * 
+     * @return the VolatileImage which data layout and color model compatible 
+     * with this GraphicsConfiguration. 
+     * 
+     * @throws AWTException if ImageCapabilities is not supported by the
+     * GraphicsConfiguration.
+     */
+    public VolatileImage createCompatibleVolatileImage(int width, int height,
+            ImageCapabilities caps) throws AWTException {
+        VolatileImage res = createCompatibleVolatileImage(width, height);
+        if (!res.getCapabilities().equals(caps)) {
+            // awt.14A=Can not create VolatileImage with specified capabilities
+            throw new AWTException(Messages.getString("awt.14A")); //$NON-NLS-1$
+        }
+        return res;
+    }
+
+    /**
+     * Creates a VolatileImage with specified width, height, transparency 
+     * and ImageCapabilities; a data layout and color model compatible with 
+     * this GraphicsConfiguration.
+     * 
+     * @param width the width of image.
+     * @param height the height of image.
+     * @param caps the ImageCapabilities object.
+     * @param transparency the Transparency mode: OPAQUE, BITMASK, or
+     * TRANSLUCENT.
+     * 
+     * @return the VolatileImage which data layout and color model compatible 
+     * with this GraphicsConfiguration. 
+     * 
+     * @throws AWTException if ImageCapabilities is not supported by the
+     * GraphicsConfiguration.
+     */
+    public VolatileImage createCompatibleVolatileImage(int width, int height,
+            ImageCapabilities caps, int transparency) throws AWTException {
+        VolatileImage res = createCompatibleVolatileImage(width, height, transparency);
+        if (!res.getCapabilities().equals(caps)) {
+            // awt.14A=Can not create VolatileImage with specified capabilities
+            throw new AWTException(Messages.getString("awt.14A")); //$NON-NLS-1$
+        }
+        return res;
+    }
+
+    /**
+     * Gets the buffering capabilities of the GraphicsConfiguration.
+     * 
+     * @return the BufferCapabilities object. 
+     */
+    public BufferCapabilities getBufferCapabilities() {
+        return new BufferCapabilities(new ImageCapabilities(false), new ImageCapabilities(false),
+                BufferCapabilities.FlipContents.UNDEFINED);
+    }
+
+    /**
+     * Gets the image capabilities of the GraphicsConfiguration.
+     * 
+     * @return the ImageCapabilities object.
+     */
+    public ImageCapabilities getImageCapabilities() {
+        return new ImageCapabilities(false);
+    }
+}
diff --git a/awt/java/awt/GraphicsDevice.java b/awt/java/awt/GraphicsDevice.java
new file mode 100644
index 0000000..8cf700a
--- /dev/null
+++ b/awt/java/awt/GraphicsDevice.java
@@ -0,0 +1,199 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Alexey A. Petrenko
+ * @version $Revision$
+ */
+package java.awt;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The GraphicsDevice class describes the graphics devices (such as screens 
+ * or printers) which are available in a particular graphics environment. 
+ * Many GraphicsDevice instances can be associated with a single
+ * GraphicsEnvironment. Each GraphicsDevice has one or more GraphicsConfiguration
+ * objects which specify the different configurations and modes of GraphicsDevice.
+ */
+public abstract class GraphicsDevice {
+    
+    /** The display mode. */
+    private DisplayMode displayMode;
+
+    //???AWT
+//    private Window fullScreenWindow = null;
+
+   /** The Constant TYPE_IMAGE_BUFFER indicates a image buffer device. */
+
+    public static final int TYPE_IMAGE_BUFFER = 2;
+
+    /** The Constant TYPE_PRINTER indicates a printer device. */
+    public static final int TYPE_PRINTER = 1;
+
+    /** The Constant TYPE_RASTER_SCREEN indicates a raster screen device. */
+    public static final int TYPE_RASTER_SCREEN = 0;
+
+   /**
+    * Constructor is not to be used directly as this class is abstract. 
+    */
+    protected GraphicsDevice() {
+        displayMode = new DisplayMode(0, 0, DisplayMode.BIT_DEPTH_MULTI, DisplayMode.REFRESH_RATE_UNKNOWN);
+    }
+
+
+   /**
+    * Returns an array of GraphicsConfiguration objects associated
+    * with the GraphicsDevice.  
+    * 
+    * @return an array of GraphicsConfiguration objects associated
+    * with the GraphicsDevice.
+    */
+    public abstract GraphicsConfiguration[] getConfigurations();
+
+    /**
+     * Gets the default configuration for the GraphicsDevice.
+     * 
+     * @return the default GraphicsConfiguration object for the GraphicsDevice.
+     */
+    public abstract GraphicsConfiguration getDefaultConfiguration();
+
+    /**
+     * Gets the String identifier which associated with the GraphicsDevice in 
+     * the GraphicsEnvironment.
+     * 
+     * @return the String identifier of the GraphicsDevice in 
+     * the GraphicsEnvironment.
+     */
+    public abstract String getIDstring();
+
+    /**
+     * Gets the type of this GraphicsDevice: 
+     * TYPE_IMAGE_BUFFER, TYPE_PRINTER or TYPE_RASTER_SCREEN.
+     * 
+     * @return the type of this GraphicsDevice: TYPE_IMAGE_BUFFER, 
+     * TYPE_PRINTER or TYPE_RASTER_SCREEN.
+     */
+    public abstract int getType();
+
+
+
+   /**
+	* Returns the number of bytes available in accelerated 
+	* memory on this device. 
+    * 
+    * @return the number of bytes available accelerated memory.
+    */
+    public int getAvailableAcceleratedMemory() {
+        return 0;
+    }
+
+    /* ???AWT
+    public GraphicsConfiguration getBestConfiguration(GraphicsConfigTemplate gct) {
+        return gct.getBestConfiguration(getConfigurations());
+    }
+    */
+    
+    /**
+     * Gets the current display mode of the GraphicsDevice.
+     * 
+     * @return the current display mode of the GraphicsDevice.
+     */
+    public DisplayMode getDisplayMode() {
+        return displayMode;
+    }
+
+    /**
+     * Gets an array of display modes available in this GraphicsDevice.
+     * 
+     * @return an array of display modes available in this GraphicsDevice.
+     */
+    public DisplayMode[] getDisplayModes() {
+        DisplayMode []dms = {displayMode};
+        return  dms;
+    }
+
+    /* ???AWT
+    public Window getFullScreenWindow() {
+        return fullScreenWindow;
+    }
+    */
+    
+    /**
+     * Returns true if this GraphicsDevice supports low-level 
+     * display changes.
+     * 
+     * @return true, if this GraphicsDevice supports low-level 
+     * display changes; false otherwise.
+     */
+    public boolean isDisplayChangeSupported() {
+        return false;
+    }
+
+    /**
+     * Returns true if this GraphicsDevice supports full screen
+     * mode.
+     * 
+     * @return true, if this GraphicsDevice supports full screen
+     * mode; otherwise false.
+     */
+    public boolean isFullScreenSupported() {
+        return false;
+    }
+    //an array of display modes available in this GraphicsDevice.
+    
+    /**
+     * Sets the display mode of this GraphicsDevice.
+     * 
+     * @param dm the new display mode of this GraphicsDevice. 
+     */
+    public void setDisplayMode(DisplayMode dm) {
+        if (!isDisplayChangeSupported()) {
+            // awt.122=Does not support display mode changes
+            throw new UnsupportedOperationException(Messages.getString("awt.122")); //$NON-NLS-1$
+        }
+
+        DisplayMode []dms = getDisplayModes();
+        for (DisplayMode element : dms) {
+            if (element.equals(dm)) {
+                displayMode = dm;
+                return;
+            }
+        }
+        // awt.123=Unsupported display mode: {0}
+        throw new IllegalArgumentException(Messages.getString("awt.123", dm)); //$NON-NLS-1$
+    }
+
+    /* ???AWT
+    public void setFullScreenWindow(Window w) {
+        if (w == null) {
+            fullScreenWindow = null;
+            return;
+        }
+
+        fullScreenWindow = w;
+
+        if (isFullScreenSupported()) {
+            w.enableInputMethods(false);
+        } else {
+            w.setSize(displayMode.getWidth(), displayMode.getHeight());
+            w.setLocation(0, 0);
+        }
+        w.setVisible(true);
+        w.setAlwaysOnTop(true);
+    }
+    */
+}
diff --git a/awt/java/awt/GraphicsEnvironment.java b/awt/java/awt/GraphicsEnvironment.java
new file mode 100644
index 0000000..3b14f55
--- /dev/null
+++ b/awt/java/awt/GraphicsEnvironment.java
@@ -0,0 +1,209 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ */
+
+package java.awt;
+
+import java.awt.image.BufferedImage;
+import java.util.Locale;
+
+import org.apache.harmony.awt.ContextStorage;
+import org.apache.harmony.awt.gl.CommonGraphics2DFactory;
+
+/**
+ * The GraphicsEnvironment class defines a collection of GraphicsDevice 
+ * objects and Font objects which are available for Java application on
+ * current platform.
+ */
+public abstract class GraphicsEnvironment {
+    
+    /**
+     * Constructor could not be used directly and should be obtained in 
+     * extended classes. 
+     */
+    protected GraphicsEnvironment() {}
+
+    /**
+     * Gets the local GraphicsEnvironment.
+     * 
+     * @return the local GraphicsEnvironment.
+     */
+    public static GraphicsEnvironment getLocalGraphicsEnvironment() {
+        synchronized(ContextStorage.getContextLock()) {
+            if (ContextStorage.getGraphicsEnvironment() == null) {
+                if (isHeadless()) {                    
+                    ContextStorage.setGraphicsEnvironment(new HeadlessGraphicsEnvironment());                    
+                } else {
+                    CommonGraphics2DFactory g2df =
+                            (CommonGraphics2DFactory) Toolkit.getDefaultToolkit().getGraphicsFactory();
+                    
+                    ContextStorage.setGraphicsEnvironment( 
+                            g2df.createGraphicsEnvironment(ContextStorage.getWindowFactory())
+                    );
+                }
+            }
+
+            return ContextStorage.getGraphicsEnvironment();
+        }
+    }
+
+    /**
+     * Returns whether or not a display, keyboard, and mouse are supported 
+     * in this graphics environment.
+     * 
+     * @return true, if HeadlessException will be thrown from areas of 
+     * the graphics environment that are dependent on a display, keyboard, 
+     * or mouse; false otherwise.
+     */
+    public boolean isHeadlessInstance() {
+        return false;
+    }
+
+    /**
+     * Checks whether or not a display, keyboard, and mouse are supported 
+     * in this environment. 
+     * 
+     * @return true, if a HeadlessException is thrown from areas of 
+     * the Toolkit and GraphicsEnvironment that are dependent on 
+     * a display, keyboard, or mouse; false otherwise.
+     */
+    public static boolean isHeadless() {
+        return "true".equals(System.getProperty("java.awt.headless"));
+    }
+
+    /**
+     * Gets the maximum bounds of system centered windows.
+     * 
+     * @return the maximum bounds of system centered windows.
+     * 
+     * @throws HeadlessException if isHeadless() method returns true.
+     */
+    public Rectangle getMaximumWindowBounds() throws HeadlessException {
+        return getDefaultScreenDevice().getDefaultConfiguration().getBounds();
+    }
+
+    /**
+     * Gets the Point which should defines the center of system window.
+     * 
+     * @return the Point where the system window should be centered.
+     * 
+     * @throws HeadlessException if isHeadless() method returns true.
+     */
+    public Point getCenterPoint() throws HeadlessException {
+        Rectangle mwb = getMaximumWindowBounds();
+        return new Point(mwb.width >> 1, mwb.height >> 1);
+    }
+
+    /**
+     * Indicates that the primary font should be used. 
+     * Primary font is specified by initial system locale or default encoding).
+     * 
+     */
+    public void preferLocaleFonts() {
+        // Note: API specification says following:
+        // "The actual change in font rendering behavior resulting
+        // from a call to this method is implementation dependent;
+        // it may have no effect at all." So, doing nothing is an
+        // acceptable behavior for this method.
+
+        // For now FontManager uses 1.4 font.properties scheme for font mapping, so
+        // this method doesn't make any sense. The implementation of this method
+        // which will influence font mapping is postponed until
+        // 1.5 mapping scheme not implemented.
+
+        // todo - Implement non-default behavior with 1.5 font mapping scheme
+    }
+
+    /**
+     * Indicates that a proportional preference of the font should be used.
+     */
+    public void preferProportionalFonts() {
+        // Note: API specification says following:
+        // "The actual change in font rendering behavior resulting
+        // from a call to this method is implementation dependent;
+        // it may have no effect at all." So, doing nothing is an
+        // acceptable behavior for this method.
+
+        // For now FontManager uses 1.4 font.properties scheme for font mapping, so
+        // this method doesn't make any sense. The implementation of this method
+        // which will influence font mapping is postponed until
+        // 1.5 mapping scheme not implemented.
+
+        // todo - Implement non-default behavior with 1.5 font mapping scheme
+    }
+
+    /**
+     * Creates the Graphics2D object for rendering to the specified
+     * BufferedImage.
+     * 
+     * @param bufferedImage the BufferedImage object.
+     * 
+     * @return the Graphics2D object which allows to render to the specified 
+     * BufferedImage.
+     */
+    public abstract Graphics2D createGraphics(BufferedImage bufferedImage);
+
+    /**
+     * Gets the array of all available fonts instances in this 
+     * GraphicsEnviroments.
+     * 
+     * @return the array of all available fonts instances in this 
+     * GraphicsEnviroments.
+     */
+    public abstract Font[] getAllFonts();
+
+    /**
+     * Gets the array of all available font family names.
+     * 
+     * @return the array of all available font family names.
+     */
+    public abstract String[] getAvailableFontFamilyNames();
+
+    /**
+     * Gets the array of all available font family names for the specified
+     * locale.
+     * 
+     * @param locale the Locale object which represents geographical
+     * region. The default locale is used if locale is null.
+     * 
+     * @return the array of available font family names for the specified 
+     * locale.
+     */
+    public abstract String[] getAvailableFontFamilyNames(Locale locale);
+
+    /**
+     * Gets the default screen device as GraphicDevice object.
+     * 
+     * @return the GraphicDevice object which represents default screen device.
+     * 
+     * @throws HeadlessException if isHeadless() returns true.
+     */
+    public abstract GraphicsDevice getDefaultScreenDevice() throws HeadlessException;
+
+    /**
+     * Gets an array of all available screen devices.
+     * 
+     * @return the array of GraphicsDevice obgects which represents 
+     * all available screen devices.
+     * 
+     * @throws HeadlessException if isHeadless() returns true.
+     */
+    public abstract GraphicsDevice[] getScreenDevices() throws HeadlessException;
+}
diff --git a/awt/java/awt/HeadlessException.java b/awt/java/awt/HeadlessException.java
new file mode 100644
index 0000000..28e463b
--- /dev/null
+++ b/awt/java/awt/HeadlessException.java
@@ -0,0 +1,48 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Alexey A. Petrenko
+ * @version $Revision$
+ */
+package java.awt;
+
+/**
+ * The HeadlessException class provides notifications and error messages 
+ * when code that is dependent on a keyboard, display, or mouse is called 
+ * in an environment that does not support a keyboard, display, or mouse.
+ */
+public class HeadlessException extends UnsupportedOperationException {
+    
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = 167183644944358563L;
+
+    /**
+     * Instantiates a new headless exception.
+     */
+    public HeadlessException() {
+        super();
+    }
+
+    /**
+     * Instantiates a new headless exception with the specified message.
+     * 
+     * @param msg the String which represents error message. 
+     */
+    public HeadlessException(String msg) {
+        super(msg);
+    }
+}
diff --git a/awt/java/awt/HeadlessGraphicsEnvironment.java b/awt/java/awt/HeadlessGraphicsEnvironment.java
new file mode 100644
index 0000000..97f88d1
--- /dev/null
+++ b/awt/java/awt/HeadlessGraphicsEnvironment.java
@@ -0,0 +1,69 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package java.awt;
+
+import java.awt.GraphicsDevice;
+import java.awt.HeadlessException;
+
+import org.apache.harmony.awt.gl.CommonGraphicsEnvironment;
+
+/**
+ * The HeadlessGraphicsEnvironment class is the CommonGraphicsEnvironment
+ * implementation to use in the case where the environment lacks display, 
+ * keyboard, and mouse support.
+ */
+public class HeadlessGraphicsEnvironment extends CommonGraphicsEnvironment {
+    
+    /**
+     * Returns whether or not a display, keyboard, and mouse are supported 
+     * in this graphics environment.
+     * 
+     * @return true, if HeadlessException will be thrown from areas of 
+     * the graphics environment that are dependent on a display, keyboard, 
+     * or mouse; false otherwise.
+     */
+    @Override
+    public boolean isHeadlessInstance() {
+        return true;
+    }
+    
+    /**
+     * Gets the default screen device as GraphicDevice object.
+     * 
+     * @return the GraphicDevice object which represents default screen device.
+     * 
+     * @throws HeadlessException if isHeadless() returns true.
+     */
+    @Override
+    public GraphicsDevice getDefaultScreenDevice() throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+    /**
+     * Gets an array of all available screen devices.
+     * 
+     * @return the array of GraphicsDevice objects which represents 
+     * all available screen devices.
+     * 
+     * @throws HeadlessException if isHeadless() returns true.
+     */
+    @Override
+    public GraphicsDevice[] getScreenDevices() throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+}
diff --git a/awt/java/awt/HeadlessToolkit.java b/awt/java/awt/HeadlessToolkit.java
new file mode 100644
index 0000000..a7dd557
--- /dev/null
+++ b/awt/java/awt/HeadlessToolkit.java
@@ -0,0 +1,301 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package java.awt;
+
+//???AWT
+//import java.awt.datatransfer.Clipboard;
+//import java.awt.dnd.DragGestureEvent;
+//import java.awt.dnd.DragGestureListener;
+//import java.awt.dnd.DragGestureRecognizer;
+//import java.awt.dnd.DragSource;
+//import java.awt.dnd.InvalidDnDOperationException;
+//import java.awt.dnd.peer.DragSourceContextPeer;
+import java.awt.im.InputMethodHighlight;
+import java.awt.image.ColorModel;
+//import java.awt.peer.*;
+//import java.beans.PropertyChangeSupport;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.harmony.awt.ComponentInternals;
+//import org.apache.harmony.awt.datatransfer.DTK;
+import org.apache.harmony.awt.wtk.GraphicsFactory;
+import org.apache.harmony.awt.wtk.NativeEventQueue;
+import org.apache.harmony.awt.wtk.WindowFactory;
+
+/**
+ * The HeadlessToolkit class is a subclass of ToolkitImpl to 
+ * be used for graphical environments that lack keyboard and 
+ * mouse capabilities.
+ */
+public final class HeadlessToolkit extends ToolkitImpl {
+    
+    //???AWT
+    /*
+    @Override
+    protected ButtonPeer createButton(Button a0) throws HeadlessException {
+        throw new HeadlessException();
+    }
+    
+    @Override
+    protected CheckboxPeer createCheckbox(Checkbox a0) throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+    @Override
+    protected CheckboxMenuItemPeer createCheckboxMenuItem(CheckboxMenuItem a0) throws HeadlessException {
+        throw new HeadlessException();
+    }
+    
+    @Override
+    protected ChoicePeer createChoice(Choice a0) throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+    public Cursor createCustomCursor(Image img, Point hotSpot, String name)
+    throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+    @Override
+    protected DialogPeer createDialog(Dialog a0) throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+    @Override
+    public <T extends DragGestureRecognizer> T createDragGestureRecognizer(
+            Class<T> recognizerAbstractClass, DragSource ds, Component c, int srcActions,
+            DragGestureListener dgl) {
+        return null;
+    }
+
+    @Override
+    public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge)
+    throws InvalidDnDOperationException {
+        throw new InvalidDnDOperationException();
+    }
+
+    @Override
+    protected FileDialogPeer createFileDialog(FileDialog a0) throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+    @Override
+    protected FramePeer createFrame(Frame a0) throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+    @Override
+    protected LabelPeer createLabel(Label a0) throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+    @Override
+    protected ListPeer createList(List a0) throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+    @Override
+    protected MenuPeer createMenu(Menu a0) throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+    @Override
+    protected MenuBarPeer createMenuBar(MenuBar a0) throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+    @Override
+    protected MenuItemPeer createMenuItem(MenuItem a0) throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+    @Override
+    protected PopupMenuPeer createPopupMenu(PopupMenu a0) throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+    @Override
+    protected ScrollbarPeer createScrollbar(Scrollbar a0) throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+    @Override
+    protected ScrollPanePeer createScrollPane(ScrollPane a0) throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+    @Override
+    protected TextAreaPeer createTextArea(TextArea a0) throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+    @Override
+    protected TextFieldPeer createTextField(TextField a0) throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+    @Override
+    protected WindowPeer createWindow(Window a0) throws HeadlessException {
+        throw new HeadlessException();
+    }
+    */
+
+    @Override
+    public Dimension getBestCursorSize(int prefWidth, int prefHeight) throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+    @Override
+    public ColorModel getColorModel() throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+    @Override
+    public GraphicsFactory getGraphicsFactory() throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+    @Override
+    public boolean getLockingKeyState(int keyCode) throws UnsupportedOperationException {
+        throw new HeadlessException();
+    }
+
+    @Override
+    public int getMaximumCursorColors() throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+    @Override
+    public int getMenuShortcutKeyMask() throws HeadlessException {
+        throw new HeadlessException();
+    }
+    
+    //???AWT
+    /*
+    @Override
+    NativeEventQueue getNativeEventQueue() throws HeadlessException {
+        throw new HeadlessException();
+    }
+    
+    @Override
+    public PrintJob getPrintJob(Frame frame, String jobtitle, JobAttributes jobAttributes, 
+            PageAttributes pageAttributes) throws IllegalArgumentException {
+        throw new IllegalArgumentException();        
+    }
+    
+    @Override
+    public PrintJob getPrintJob(Frame frame, String jobtitle, Properties props) throws NullPointerException  {
+        throw new NullPointerException();
+    }
+    */
+
+    @Override
+    public Insets getScreenInsets(GraphicsConfiguration gc) throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+    @Override
+    public int getScreenResolution() throws HeadlessException {
+        throw new HeadlessException();
+    }    
+
+    @Override
+    public Dimension getScreenSize() throws HeadlessException {
+        throw new HeadlessException();
+    }
+    
+    //???AWT
+    /*
+    @Override
+    public Clipboard getSystemClipboard() throws HeadlessException {
+        throw new HeadlessException();
+    }    
+    
+    @Override
+    public Clipboard getSystemSelection() throws HeadlessException {
+        throw new HeadlessException();
+    }
+    
+    @Override
+    WindowFactory getWindowFactory() throws HeadlessException {
+        throw new HeadlessException();
+    }
+    */
+
+    @Override
+    protected void init() {
+        lockAWT();
+        try {
+            ComponentInternals.setComponentInternals(new ComponentInternalsImpl());
+            //???AWT: new EventQueue(this); // create the system EventQueue
+            //???AWT: dispatcher = new Dispatcher(this);
+            desktopProperties = new HashMap<String, Object>();
+            //???AWT: desktopPropsSupport = new PropertyChangeSupport(this);
+//          ???AWT: awtEventsManager = new AWTEventsManager();
+//          ???AWT: dispatchThread = new HeadlessEventDispatchThread(this, dispatcher);            
+//          ???AWT: dtk = DTK.getDTK();
+            dispatchThread.start();            
+        } finally {
+            unlockAWT();
+        }
+    }
+
+    @Override
+    public boolean isDynamicLayoutActive() throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+    @Override
+    protected boolean isDynamicLayoutSet() throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+    @Override
+    public boolean isFrameStateSupported(int state) throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+    @Override
+    protected void loadSystemColors(int[] systemColors) throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+    @Override
+    public Map<java.awt.font.TextAttribute, ?> mapInputMethodHighlight(
+            InputMethodHighlight highlight) throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+    @Override
+    Map<java.awt.font.TextAttribute, ?> mapInputMethodHighlightImpl(
+            InputMethodHighlight highlight) throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+    @Override
+    public void setDynamicLayout(boolean dynamic) throws HeadlessException {
+        throw new HeadlessException();
+    }
+
+    @Override
+    public void setLockingKeyState(int keyCode, boolean on) throws UnsupportedOperationException {
+        throw new HeadlessException();
+    }
+}
diff --git a/awt/java/awt/IllegalComponentStateException.java b/awt/java/awt/IllegalComponentStateException.java
new file mode 100644
index 0000000..21dc35f
--- /dev/null
+++ b/awt/java/awt/IllegalComponentStateException.java
@@ -0,0 +1,51 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt;
+
+/**
+ * The IllegalComponentStateException class is used to provide 
+ * notification that AWT component is not in an appropriate state 
+ * for the requested operation.
+ */
+public class IllegalComponentStateException extends IllegalStateException {
+
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = -1889339587208144238L;
+
+    /**
+     * Instantiates a new IllegalComponentStateException with
+     * the specified message.
+     * 
+     * @param s the String message which describes the exception.
+     */
+    public IllegalComponentStateException(String s) {
+        super(s);
+    }
+
+    /**
+     * Instantiates a new IllegalComponentStateException without
+     * detailed message.
+     */
+    public IllegalComponentStateException() {
+    }
+
+}
+
diff --git a/awt/java/awt/Image.java b/awt/java/awt/Image.java
new file mode 100644
index 0000000..c217e38
--- /dev/null
+++ b/awt/java/awt/Image.java
@@ -0,0 +1,203 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.awt.image.AreaAveragingScaleFilter;
+import java.awt.image.FilteredImageSource;
+import java.awt.image.ImageFilter;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.awt.image.ReplicateScaleFilter;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Image abstract class represents the graphic images. 
+ */
+public abstract class Image {
+
+    /** 
+     * The UndefinedProperty object should be returned if
+     * property is not defined for a particular image. 
+     */
+    public static final Object UndefinedProperty = new Object();  //$NON-LOCK-1$
+
+    /** 
+     * The Constant SCALE_DEFAULT indicates the default image
+     * scaling algorithm. 
+     */
+    public static final int SCALE_DEFAULT = 1;
+
+    /** 
+     * The Constant SCALE_FAST indicates an image scaling algorithm which 
+     * places a higher priority on scaling speed than on the image's smoothness. 
+     */
+    public static final int SCALE_FAST = 2;
+
+    /** 
+     * The Constant SCALE_SMOOTH indicates an image scaling algorithm which 
+     * places a higher priority on image smoothness than on scaling speed. 
+     */
+    public static final int SCALE_SMOOTH = 4;
+
+    /** 
+     * The Constant SCALE_REPLICATE indicates the image scaling 
+     * algorithm in the ReplicateScaleFilter class. 
+     */
+    public static final int SCALE_REPLICATE = 8;
+
+    /** 
+     * The Constant SCALE_AREA_AVERAGING indicates  
+     * the area averaging image scaling algorithm. 
+     */
+    public static final int SCALE_AREA_AVERAGING = 16;
+
+    /** 
+     * The acceleration priority indicates image acceleration.   
+     */
+    protected float accelerationPriority = 0.5f;
+
+    /** The Constant capabilities. */
+    private static final ImageCapabilities capabilities = new ImageCapabilities(false);
+
+    /**
+     * Gets the image property with the specified name.
+     * The UndefinedProperty object should be return if the property is 
+     * not specified for this image.  The return value should be null if the
+     * property is currently unknown yet and the specified ImageObserver is
+     * to be notified later. 
+     * 
+     * @param name the name of image's property.
+     * @param observer the ImageObserver.
+     * 
+     * @return the Object which represents value of the specified property.
+     */
+    public abstract Object getProperty(String name, ImageObserver observer);
+
+    /**
+     * Gets the ImageProducer object which represents data of this Image.
+     * 
+     * @return the ImageProducer object which represents data of this Image.
+     */
+    public abstract ImageProducer getSource();
+
+    /**
+     * Gets the width of this image. The specified ImageObserver object 
+     * is notified when the width of this image is available.
+     * 
+     * @param observer the ImageObserver object which is 
+     * is notified when the width of this image is available.
+     * 
+     * @return the width of image, or -1 if the width of this image 
+     * is not available.
+     */
+    public abstract int getWidth(ImageObserver observer);
+
+    /**
+     * Gets the height of this image. The specified ImageObserver object 
+     * is notified when the height of this image is available.
+     * 
+     * @param observer the ImageObserver object which is 
+     * is notified when the height of this image is available.
+     * 
+     * @return the height of image, or -1 if the height of this image 
+     * is not available.
+     */
+    public abstract int getHeight(ImageObserver observer);
+
+    /**
+     * Gets the scaled instance of this Image. This method returns 
+     * an Image object constructed from the source of this image 
+     * with the specified width, height, and applied scaling
+     * alghorithm.
+     * 
+     * @param width the width of scaled Image. 
+     * @param height the height of scaled Image.
+     * @param hints the constant which indicates scaling algorithm. 
+     * 
+     * @return the scaled Image.
+     */
+    public Image getScaledInstance(int width, int height, int hints) {
+        ImageFilter filter;
+        if ((hints & (SCALE_SMOOTH | SCALE_AREA_AVERAGING)) != 0) {
+            filter = new AreaAveragingScaleFilter(width, height);
+        } else {
+            filter = new ReplicateScaleFilter(width, height);
+        }
+        ImageProducer producer = new FilteredImageSource(getSource(), filter);
+        return Toolkit.getDefaultToolkit().createImage(producer);
+    }
+
+    /**
+     * Gets a Graphics object for rendering this image. 
+     * This method can be used for off-screen images.
+     * 
+     * @return a Graphics object for rendering to this image.
+     */
+    public abstract Graphics getGraphics();
+
+    /**
+     * Flushes resources which are used by this Image object. 
+     * This method resets the image to the reconstructered state
+     * from the image's source.
+     */
+    public abstract void flush();
+
+    /**
+     * Gets the acceleration priority of this image.
+     * 
+     * @return the acceleration priority of this image.
+     */
+    public float getAccelerationPriority() {
+        return accelerationPriority;
+    }
+
+    /**
+     * Sets the acceleration priority for this image.  
+     *  
+     * @param priority the new acceleration priority (value in the
+     * range 0-1).
+     */
+    public void setAccelerationPriority(float priority) {
+        if (priority < 0 || priority > 1) {
+            // awt.10A=Priority must be a value between 0 and 1, inclusive
+            throw new IllegalArgumentException(Messages.getString("awt.10A")); //$NON-NLS-1$
+        }
+        accelerationPriority = priority;
+    }
+
+    /**
+     * Gets an ImageCapabilities object of this Image object
+     * for the specified GraphicsConfiguration. 
+     * 
+     * @param gc the specified GraphicsConfiguration object 
+     * (null value means default GraphicsConfiguration).
+     * 
+     * @return an ImageCapabilities object of this Image object
+     * for the specified GraphicsConfiguration.
+     */
+    public ImageCapabilities getCapabilities(GraphicsConfiguration gc) {
+        // Note: common image is not accelerated.
+        return capabilities;
+    }
+}
+
+
diff --git a/awt/java/awt/ImageCapabilities.java b/awt/java/awt/ImageCapabilities.java
new file mode 100644
index 0000000..6e9ecfc
--- /dev/null
+++ b/awt/java/awt/ImageCapabilities.java
@@ -0,0 +1,74 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Alexey A. Petrenko
+ * @version $Revision$
+ */
+package java.awt;
+
+/**
+ * The ImageCapabilities class gives information about an image's capabilities.
+ */
+public class ImageCapabilities implements Cloneable {
+    
+    /** The accelerated. */
+    private final boolean accelerated;
+
+    /**
+     * Instantiates a new ImageCapabilities with the specified
+     * acceleration flag which indicates whether acceleration
+     * is desired or not.
+     * 
+     * @param accelerated the accelerated flag.
+     */
+    public ImageCapabilities(boolean accelerated) {
+        this.accelerated = accelerated;
+    }
+
+    /**
+     * Returns a copy of this ImageCapabilities object.
+     * 
+     * @return the copy of this ImageCapabilities object.
+     */
+    @Override
+    public Object clone() {
+        return new ImageCapabilities(accelerated);
+    }
+
+    /**
+     * Returne true if the Image of this ImageCapabilities is or can be
+     * accelerated.
+     *  
+     * @return true, if the Image of this ImageCapabilities is or can be
+     * accelerated, false otherwise.
+     */
+    public boolean isAccelerated() {
+        return accelerated;
+    }
+
+    /**
+     * Returns true if this ImageCapabilities applies to
+     * the VolatileImage which can lose its surfaces.
+     * 
+     * @return true if this ImageCapabilities applies to
+     * the VolatileImage which can lose its surfaces, 
+     * false otherwise.
+     */
+    public boolean isTrueVolatile() {
+        return true;
+    }
+}
diff --git a/awt/java/awt/Insets.java b/awt/java/awt/Insets.java
new file mode 100644
index 0000000..61f3fd8
--- /dev/null
+++ b/awt/java/awt/Insets.java
@@ -0,0 +1,165 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Dmitry A. Durnev
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.io.Serializable;
+
+import org.apache.harmony.misc.HashCode;
+
+
+/**
+ * The Insets class represents the borders of a container. 
+ * This class describes the space that a container should leave at each edge:
+ * the top, the bottom, the right side, and the left side. 
+ * The space can be filled with a border, a blank space, or a title.
+ */
+public class Insets implements Cloneable, Serializable {
+
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = -2272572637695466749L;
+
+    /**
+     * The top inset indicates the size of the space added to the 
+     * top of the rectangle.
+     */
+    public int top;
+
+    /** 
+     * The left inset indicates the size of the space added to the 
+     * left side of the rectangle.
+     */
+    public int left;
+
+    /** 
+     * The bottom inset indicates the size of the space subtracted from 
+     * the bottom of the rectangle.
+     */
+    public int bottom;
+
+    /** The right inset indicates the size of the space subtracted from 
+     * the right side of the rectangle. 
+     */
+    public int right;
+
+    /**
+     * Instantiates a new Inset object with the specified top, left, bottom,
+     * right parameters.
+     * 
+     * @param top the top inset.
+     * @param left the left inset.
+     * @param bottom the bottom inset.
+     * @param right the right inset.
+     */
+    public Insets(int top, int left, int bottom, int right) {
+        setValues(top, left, bottom, right);
+    }
+
+    /**
+     * Returns a hash code of the Insets object.
+     * 
+     * @return a hash code of the Insets object.
+     */
+    @Override
+    public int hashCode() {
+        int hashCode = HashCode.EMPTY_HASH_CODE;
+        hashCode = HashCode.combine(hashCode, top);
+        hashCode = HashCode.combine(hashCode, left);
+        hashCode = HashCode.combine(hashCode, bottom);
+        hashCode = HashCode.combine(hashCode, right);
+        return hashCode;
+    }
+
+    /**
+     * Returns a copy of this Insets object.
+     * 
+     * @return a copy of this Insets object.
+     */
+    @Override
+    public Object clone() {
+        return new Insets(top, left, bottom, right);
+    }
+
+    /**
+     * Checks if this Insets object is equal to the specified object.
+     * 
+     * @param o the Object to be compared.
+     * 
+     * @return true, if the object is an Insets object whose data values
+     * are equal to those of this object, false otherwise.
+     */
+    @Override
+    public boolean equals(Object o) {
+        if (o == this) {
+            return true;
+        }
+        if (o instanceof Insets) {
+            Insets i = (Insets) o;
+            return ((i.left == left) && (i.bottom == bottom) &&
+                    (i.right == right) && (i.top == top));
+        }
+        return false;
+    }
+
+    /**
+     * Returns a String representation of this Insets object.
+     * 
+     * @return a String representation of this Insets object.
+     */
+    @Override
+    public String toString() {
+        /* The format is based on 1.5 release behavior 
+         * which can be revealed by the following code:
+         * System.out.println(new Insets(1, 2, 3, 4));
+         */
+
+        return (getClass().getName() +
+                "[left=" + left + ",top=" + top + //$NON-NLS-1$ //$NON-NLS-2$
+                ",right=" + right + ",bottom="  + bottom + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+    }
+
+    /**
+     * Sets top, left, bottom, and right insets to the specified values.
+     * 
+     * @param top the top inset.
+     * @param left the left inset.
+     * @param bottom the bottom inset.
+     * @param right the right inset.
+     */
+    public void set(int top, int left, int bottom, int right) {
+        setValues(top, left, bottom, right);
+    }
+
+    /**
+     * Sets the values.
+     * 
+     * @param top the top
+     * @param left the left
+     * @param bottom the bottom
+     * @param right the right
+     */
+    private void setValues(int top, int left, int bottom, int right) {
+        this.top = top;
+        this.left = left;
+        this.bottom = bottom;
+        this.right = right;
+    }
+}
+
diff --git a/awt/java/awt/ItemSelectable.java b/awt/java/awt/ItemSelectable.java
new file mode 100644
index 0000000..a46364b
--- /dev/null
+++ b/awt/java/awt/ItemSelectable.java
@@ -0,0 +1,53 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.awt.event.ItemListener;
+
+/**
+ * The ItemSelectable interface represents a set of items which can be selected.
+ */
+public interface ItemSelectable {
+
+    /**
+     * Adds an ItemListener for receiving item events when the state of an item 
+     * is changed by the user. 
+     * 
+     * @param l the ItemListener.
+     */
+    public void addItemListener(ItemListener l);
+
+    /**
+     * Gets an array of the selected objects or null if there is no selected object.
+     * 
+     * @return an array of the selected objects or null if there is no selected 
+     * object.
+     */
+    public Object[] getSelectedObjects();
+
+    /**
+     * Removes the specified ItemListener.
+     * 
+     * @param l the ItemListener which will be removed.
+     */
+    public void removeItemListener(ItemListener l);
+
+}
diff --git a/awt/java/awt/MenuComponent.java b/awt/java/awt/MenuComponent.java
new file mode 100644
index 0000000..9eb4f3d
--- /dev/null
+++ b/awt/java/awt/MenuComponent.java
@@ -0,0 +1,1041 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package java.awt;
+
+import java.awt.event.FocusListener;
+import java.awt.event.MouseEvent;
+import java.awt.peer.MenuComponentPeer;
+import java.io.Serializable;
+import java.util.Locale;
+//import javax.accessibility.Accessible;
+//import javax.accessibility.AccessibleComponent;
+//import javax.accessibility.AccessibleContext;
+//import javax.accessibility.AccessibleRole;
+//import javax.accessibility.AccessibleSelection;
+//import javax.accessibility.AccessibleStateSet;
+import org.apache.harmony.awt.gl.MultiRectArea;
+import org.apache.harmony.awt.state.MenuItemState;
+import org.apache.harmony.awt.state.MenuState;
+
+/**
+ * The MenuComponent abstract class is the superclass for menu 
+ * components. Menu components receive and process AWT events.
+ */
+public abstract class MenuComponent implements Serializable {
+    
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = -4536902356223894379L;
+
+    /** The name. */
+    private String name;
+
+    /** The font. */
+    private Font font;
+
+    /** The parent. */
+    MenuContainer parent;
+
+    /** The deprecated event handler. */
+    boolean deprecatedEventHandler = true;
+
+    /** The selected item index. */
+    private int selectedItemIndex;
+
+    //???AWT: private AccessibleContext accessibleContext;
+
+    /** The toolkit. */
+    final Toolkit toolkit = Toolkit.getDefaultToolkit();
+
+    //???AWT
+    /*
+    protected abstract class AccessibleAWTMenuComponent extends AccessibleContext implements
+            Serializable, AccessibleComponent, AccessibleSelection {
+        private static final long serialVersionUID = -4269533416223798698L;
+
+        public void addFocusListener(FocusListener listener) {
+        }
+
+        public boolean contains(Point pt) {
+            return false;
+        }
+
+        public Accessible getAccessibleAt(Point pt) {
+            return null;
+        }
+
+        public Color getBackground() {
+            return null;
+        }
+
+        public Rectangle getBounds() {
+            return null;
+        }
+
+        public Cursor getCursor() {
+            return null;
+        }
+
+        public Font getFont() {
+            return MenuComponent.this.getFont();
+        }
+
+        public FontMetrics getFontMetrics(Font font) {
+            return null;
+        }
+
+        public Color getForeground() {
+            return null;
+        }
+
+        public Point getLocation() {
+            return null;
+        }
+
+        public Point getLocationOnScreen() {
+            return null;
+        }
+
+        public Dimension getSize() {
+            return null;
+        }
+
+        public boolean isEnabled() {
+            return true; // always enabled
+        }
+
+        public boolean isFocusTraversable() {
+            return true; // always focus traversable
+        }
+
+        public boolean isShowing() {
+            return true;// always showing
+        }
+
+        public boolean isVisible() {
+            return true; // always visible
+        }
+
+        public void removeFocusListener(FocusListener listener) {
+        }
+
+        public void requestFocus() {
+        }
+
+        public void setBackground(Color color) {
+        }
+
+        public void setBounds(Rectangle rect) {
+        }
+
+        public void setCursor(Cursor cursor) {
+        }
+
+        public void setEnabled(boolean enabled) {
+        }
+
+        public void setFont(Font font) {
+            MenuComponent.this.setFont(font);
+        }
+
+        public void setForeground(Color color) {
+        }
+
+        public void setLocation(Point pt) {
+        }
+
+        public void setSize(Dimension pt) {
+        }
+
+        public void setVisible(boolean visible) {
+        }
+
+        public void addAccessibleSelection(int index) {
+        }
+
+        public void clearAccessibleSelection() {
+        }
+
+        public Accessible getAccessibleSelection(int index) {
+            return null;
+        }
+
+        public int getAccessibleSelectionCount() {
+            return 0;
+        }
+
+        public boolean isAccessibleChildSelected(int index) {
+            return false;
+        }
+
+        public void removeAccessibleSelection(int index) {
+        }
+
+        public void selectAllAccessibleSelection() {
+        }
+
+        @Override
+        public Accessible getAccessibleChild(int index) {
+            return null;
+        }
+
+        @Override
+        public int getAccessibleChildrenCount() {
+            return 0;
+        }
+
+        @Override
+        public AccessibleComponent getAccessibleComponent() {
+            return this;
+        }
+
+        @Override
+        public String getAccessibleDescription() {
+            return super.getAccessibleDescription();
+        }
+
+        @Override
+        public int getAccessibleIndexInParent() {
+            toolkit.lockAWT();
+            try {
+                Accessible aParent = getAccessibleParent();
+                int aIndex = -1;
+                if (aParent instanceof MenuComponent) {
+                    MenuComponent parent = (MenuComponent) aParent;
+                    int count = parent.getItemCount();
+                    for (int i = 0; i < count; i++) {
+                        MenuComponent comp = parent.getItem(i);
+                        if (comp instanceof Accessible) {
+                            aIndex++;
+                            if (comp == MenuComponent.this) {
+                                return aIndex;
+                            }
+                        }
+                    }
+                }
+                return -1;
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        @Override
+        public String getAccessibleName() {
+            return super.getAccessibleName();
+        }
+
+        @Override
+        public Accessible getAccessibleParent() {
+            toolkit.lockAWT();
+            try {
+                Accessible aParent = super.getAccessibleParent();
+                if (aParent != null) {
+                    return aParent;
+                }
+                MenuContainer parent = getParent();
+                if (parent instanceof Accessible) {
+                    aParent = (Accessible) parent;
+                }
+                return aParent;
+            } finally {
+                toolkit.unlockAWT();
+            }
+        }
+
+        @Override
+        public AccessibleRole getAccessibleRole() {
+            return AccessibleRole.AWT_COMPONENT;
+        }
+
+        @Override
+        public AccessibleSelection getAccessibleSelection() {
+            return this;
+        }
+
+        @Override
+        public AccessibleStateSet getAccessibleStateSet() {
+            return new AccessibleStateSet();
+        }
+
+        @Override
+        public Locale getLocale() {
+            return Locale.getDefault();
+        }
+    }
+    */
+
+    /**
+     * The accessor to MenuComponent internal state,
+     * utilized by the visual theme.
+     * 
+     * @throws HeadlessException the headless exception
+     */
+    //???AWT
+    /*
+    class State implements MenuState {
+        Dimension size;
+
+        Dimension getSize() {
+            if (size == null) {
+                calculate();
+            }
+            return size;
+        }
+
+        public int getWidth() {
+            return getSize().width;
+        }
+
+        public int getHeight() {
+            return getSize().height;
+        }
+
+        public Font getFont() {
+            return MenuComponent.this.getFont();
+        }
+
+        public int getItemCount() {
+            return MenuComponent.this.getItemCount();
+        }
+
+        public int getSelectedItemIndex() {
+            return MenuComponent.this.getSelectedItemIndex();
+        }
+
+        public boolean isFontSet() {
+            return MenuComponent.this.isFontSet();
+        }
+
+        @SuppressWarnings("deprecation")
+        public FontMetrics getFontMetrics(Font f) {
+            return MenuComponent.this.toolkit.getFontMetrics(f);
+        }
+
+        public Point getLocation() {
+            return MenuComponent.this.getLocation();
+        }
+
+        public MenuItemState getItem(int index) {
+            MenuItem item = MenuComponent.this.getItem(index);
+            return item.itemState;
+        }
+
+        public void setSize(int w, int h) {
+            this.size = new Dimension(w, h);
+        }
+
+        void calculate() {
+            size = new Dimension();
+            size.setSize(toolkit.theme.calculateMenuSize(this));
+        }
+
+        void reset() {
+            for (int i = 0; i < getItemCount(); i++) {
+                ((MenuItem.State) getItem(i)).reset();
+            }
+        }
+
+    }
+    */
+    
+    /**
+     * Pop-up box for menu. It transfers the paint events, 
+     * keyboard and mouse events to the menu component itself
+     */
+    //???AWT
+    /*
+    class MenuPopupBox extends PopupBox {
+        private final Point lastMousePos = new Point();
+
+        @Override
+        boolean isMenu() {
+            return true;
+        }
+
+        @Override
+        void paint(Graphics gr) {
+            MenuComponent.this.paint(gr);
+        }
+
+        @Override
+        void onKeyEvent(int eventId, int vKey, long when, int modifiers) {
+            MenuComponent.this.onKeyEvent(eventId, vKey, when, modifiers);
+        }
+
+        @Override
+        void onMouseEvent(int eventId, Point where, int mouseButton, long when, int modifiers,
+                int wheelRotation) {
+            // prevent conflict of mouse and keyboard
+            // when sub-menu drops down due to keyboard navigation
+            if (lastMousePos.equals(where)
+                    && (eventId == MouseEvent.MOUSE_MOVED || eventId == MouseEvent.MOUSE_ENTERED)) {
+                return;
+            }
+            lastMousePos.setLocation(where);
+            MenuComponent.this.onMouseEvent(eventId, where, mouseButton, when, modifiers);
+        }
+    }
+    */
+    
+    /**
+     * Instantiates a new MenuComponent object.
+     * 
+     * @throws HeadlessException if the graphical interface
+     * environment can't support MenuComponents
+     */
+    public MenuComponent() throws HeadlessException {
+        toolkit.lockAWT();
+        try {
+            Toolkit.checkHeadless();
+            name = autoName();
+            selectedItemIndex = -1;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Gets the name of the MenuComponent object.
+     * 
+     * @return the name of the MenuComponent object.
+     */
+    public String getName() {
+        toolkit.lockAWT();
+        try {
+            return name;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Returns a String representation of the MenuComponent object.
+     * 
+     * @return a String representation of the MenuComponent object.
+     */
+    @Override
+    public String toString() {
+        toolkit.lockAWT();
+        try {
+            return getClass().getName() + "[" + paramString() + "]"; //$NON-NLS-1$ //$NON-NLS-2$
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Gets the Parent menu Container .
+     * 
+     * @return the parent
+     */
+    public MenuContainer getParent() {
+        toolkit.lockAWT();
+        try {
+            return parent;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Sets the name of the MenuComponent to the specified string.
+     * 
+     * @param name the new name of the MenuComponent object. 
+     */
+    public void setName(String name) {
+        toolkit.lockAWT();
+        try {
+            this.name = name;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Dispatches AWT event.
+     * 
+     * @param event the AWTEvent.
+     */
+    public final void dispatchEvent(AWTEvent event) {
+        toolkit.lockAWT();
+        try {
+            processEvent(event);
+            if (deprecatedEventHandler) {
+                postDeprecatedEvent(event);
+            }
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Post deprecated event.
+     * 
+     * @param event the event
+     */
+    void postDeprecatedEvent(AWTEvent event) {
+        Event evt = event.getEvent();
+        if (evt != null) {
+            postEvent(evt);
+        }
+    }
+
+    /**
+     * Gets the peer of the MenuComponent; an application must not
+     * use this method directly.
+     * 
+     * @return the MenuComponentPeer object.
+     *
+     * @deprecated an application must not use this method directly.
+     */
+    @Deprecated
+    public MenuComponentPeer getPeer() throws org.apache.harmony.luni.util.NotImplementedException {
+        toolkit.lockAWT();
+        try {
+        } finally {
+            toolkit.unlockAWT();
+        }
+        if (true) {
+            throw new RuntimeException("Method is not implemented"); //TODO: implement //$NON-NLS-1$
+        }
+        return null;
+    }
+
+    /**
+     * Gets the locking object of this MenuComponent.
+     * 
+     * @return the locking object of this MenuComponent.
+     */
+    protected final Object getTreeLock() {
+        return toolkit.awtTreeLock;
+    }
+
+    /**
+     * Posts the Event to the MenuComponent.
+     * 
+     * @param e the Event.
+     * 
+     * @return true, if the event is posted successfully; 
+     * false otherwise.
+     * 
+     * @deprecated Replaced dispatchEvent method.
+     */
+    @SuppressWarnings("deprecation")
+    @Deprecated
+    public boolean postEvent(Event e) {
+        toolkit.lockAWT();
+        try {
+            if (parent != null) {
+                return parent.postEvent(e);
+            }
+            return false;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Returns the string representation of the MenuComponent state.
+     * 
+     * @return returns the string representation of the MenuComponent
+     * state.
+     */
+    protected String paramString() {
+        toolkit.lockAWT();
+        try {
+            return getName();
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    //???AWT
+    /*
+    public AccessibleContext getAccessibleContext() {
+        toolkit.lockAWT();
+        try {
+            if (accessibleContext == null) {
+                accessibleContext = createAccessibleContext();
+            }
+            return accessibleContext;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+    */
+
+    /**
+     * Gets the font of the MenuComponent object.
+     * 
+     * @return the Font of the MenuComponent object.
+     */
+    public Font getFont() {
+        toolkit.lockAWT();
+        try {
+            if (font == null && hasDefaultFont()) {
+                return toolkit.getDefaultFont();
+            }
+            if (font == null && parent != null) {
+                return parent.getFont();
+            }
+            return font;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Checks if is font set.
+     * 
+     * @return true, if is font set
+     */
+    boolean isFontSet() {
+        return font != null
+                || ((parent instanceof MenuComponent) && ((MenuComponent) parent).isFontSet());
+    }
+
+    /**
+     * Checks for default font.
+     * 
+     * @return true, if successful
+     */
+    boolean hasDefaultFont() {
+        return false;
+    }
+
+    /**
+     * Processes an AWTEevent on this menu component.
+     * 
+     * @param event the AWTEvent.
+     */
+    protected void processEvent(AWTEvent event) {
+        toolkit.lockAWT();
+        try {
+            // do nothing
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Removes the peer of the MenuComponent.
+     */
+    public void removeNotify() {
+        toolkit.lockAWT();
+        try {
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Sets the Font for this MenuComponent object.
+     * 
+     * @param font the new Font to be used for this MenuComponent.
+     */
+    public void setFont(Font font) {
+        toolkit.lockAWT();
+        try {
+            this.font = font;
+        } finally {
+            toolkit.unlockAWT();
+        }
+    }
+
+    /**
+     * Sets the parent.
+     * 
+     * @param parent the new parent
+     */
+    void setParent(MenuContainer parent) {
+        this.parent = parent;
+    }
+
+    /**
+     * Gets the location.
+     * 
+     * @return the location
+     */
+    Point getLocation() {
+        // to be overridden
+        return new Point(0, 0);
+    }
+
+    /**
+     * Gets the width.
+     * 
+     * @return the width
+     */
+    int getWidth() {
+        // to be overridden
+        return 1;
+    }
+
+    /**
+     * Gets the height.
+     * 
+     * @return the height
+     */
+    int getHeight() {
+        // to be overridden
+        return 1;
+    }
+
+    /**
+     * Recursively find the menu item for a menu shortcut.
+     * 
+     * @param gr the gr
+     * 
+     * @return the menu item;
+     * or null if the item is not available for this shortcut
+     */
+    //???AWT
+    /*
+    MenuItem getShortcutMenuItemImpl(MenuShortcut ms) {
+        if (ms == null) {
+            return null;
+        }
+        for (int i = 0; i < getItemCount(); i++) {
+            MenuItem mi = getItem(i);
+            if (mi instanceof Menu) {
+                mi = ((Menu) mi).getShortcutMenuItemImpl(ms);
+                if (mi != null) {
+                    return mi;
+                }
+            } else if (ms.equals(mi.getShortcut())) {
+                return mi;
+            }
+        }
+        return null;
+    }
+    */
+
+    void paint(Graphics gr) {
+        gr.setColor(Color.LIGHT_GRAY);
+        gr.fillRect(0, 0, getWidth(), getHeight());
+        gr.setColor(Color.BLACK);
+    }
+
+    /**
+     * Mouse events handler.
+     * 
+     * @param eventId - one of the MouseEvent.MOUSE_* constants
+     * @param where - mouse location
+     * @param mouseButton - mouse button that was pressed or released
+     * @param when - event time
+     * @param modifiers - input event modifiers
+     */
+    void onMouseEvent(int eventId, Point where, int mouseButton, long when, int modifiers) {
+        // to be overridden
+    }
+
+    /**
+     * Keyboard event handler.
+     * 
+     * @param eventId - one of the KeyEvent.KEY_* constants
+     * @param vKey - the key code
+     * @param when - event time
+     * @param modifiers - input event modifiers
+     */
+    void onKeyEvent(int eventId, int vKey, long when, int modifiers) {
+        // to be overridden
+    }
+
+    /**
+     * Post the ActionEvent or ItemEvent,
+     * depending on type of the menu item.
+     * 
+     * @param index the index
+     * 
+     * @return the item rect
+     */
+    //???AWT
+    /*
+    void fireItemAction(int item, long when, int modifiers) {
+        MenuItem mi = getItem(item);
+        mi.itemSelected(when, modifiers);
+    }
+
+    MenuItem getItem(int index) {
+        // to be overridden
+        return null;
+    }
+
+    int getItemCount() {
+        return 0;
+    }
+    */
+
+    /**
+     * @return The sub-menu of currently selecetd item, 
+     * or null if such a sub-menu is not available 
+     */
+    //???AWT
+    /*
+    Menu getSelectedSubmenu() {
+        if (selectedItemIndex < 0) {
+            return null;
+        }
+        MenuItem item = getItem(selectedItemIndex);
+        return (item instanceof Menu) ? (Menu) item : null;
+    }
+    */
+
+    /**
+     * Convenience method for selectItem(index, true)
+     */
+    //???AWT
+    /*
+    void selectItem(int index) {
+        selectItem(index, true);
+    }
+    */
+
+    /**
+     * Change the selection in the menu 
+     * @param index - new selecetd item's index
+     * @param showSubMenu - if new selected item has a sub-menu,
+     * should that sub-menu be displayed 
+     */
+    //???AWT
+    /*
+    void selectItem(int index, boolean showSubMenu) {
+        if (selectedItemIndex == index) {
+            return;
+        }
+        if (selectedItemIndex >= 0 && getItem(selectedItemIndex) instanceof Menu) {
+            ((Menu) getItem(selectedItemIndex)).hide();
+        }
+        MultiRectArea clip = getUpdateClip(index, selectedItemIndex);
+        selectedItemIndex = index;
+        Graphics gr = getGraphics(clip);
+        if (gr != null) {
+            paint(gr);
+        }
+        if (showSubMenu) {
+            showSubMenu(selectedItemIndex);
+        }
+    }
+    */
+
+    /**
+     * Change the selected item to the next one in the requested direction
+     * moving cyclically, skipping separators
+     * @param forward - the direction to move the selection
+     * @param showSubMenu - if new selected item has a sub-menu,
+     * should that sub-menu be displayed 
+     */
+    //???AWT
+    /*
+    void selectNextItem(boolean forward, boolean showSubMenu) {
+        int selected = getSelectedItemIndex();
+        int count = getItemCount();
+        if (count == 0) {
+            return;
+        }
+        if (selected < 0) {
+            selected = (forward ? count - 1 : 0);
+        }
+        int i = selected;
+        do {
+            i = (forward ? (i + 1) : (i + count - 1)) % count;
+            i %= count;
+            MenuItem item = getItem(i);
+            if (!"-".equals(item.getLabel())) { //$NON-NLS-1$
+                selectItem(i, showSubMenu);
+                return;
+            }
+        } while (i != selected);
+    }
+
+    
+    void showSubMenu(int index) {
+        if ((index < 0) || !isActive()) {
+            return;
+        }
+        MenuItem item = getItem(index);
+        if (item instanceof Menu) {
+            Menu menu = ((Menu) getItem(index));
+            if (menu.getItemCount() == 0) {
+                return;
+            }
+            Point location = getSubmenuLocation(index);
+            menu.show(location.x, location.y, false);
+        }
+    }
+    */
+
+    /**
+     * @return - the menu bar which is the root of crrent menu's hierarchy;
+     * or null if the hierarchy root is not a menu bar 
+     */
+    //???AWT
+    /*
+    MenuBar getMenuBar() {
+        if (parent instanceof MenuBar) {
+            return (MenuBar) parent;
+        }
+        if (parent instanceof MenuComponent) {
+            return ((MenuComponent) parent).getMenuBar();
+        }
+        return null;
+    }
+
+    PopupBox getPopupBox() {
+        return null;
+    }
+    */
+
+    Rectangle getItemRect(int index) {
+        // to be overridden
+        return null;
+    }
+
+    /**
+     * Determine the clip region when menu selection is changed
+     * from index1 to index2.
+     * 
+     * @param index1 - old selected intem
+     * @param index2 - new selected item
+     * 
+     * @return - the region to repaint
+     */
+    final MultiRectArea getUpdateClip(int index1, int index2) {
+        MultiRectArea clip = new MultiRectArea();
+        if (index1 >= 0) {
+            clip.add(getItemRect(index1));
+        }
+        if (index2 >= 0) {
+            clip.add(getItemRect(index2));
+        }
+        return clip;
+    }
+
+    /**
+     * Gets the submenu location.
+     * 
+     * @param index the index
+     * 
+     * @return the submenu location
+     */
+    Point getSubmenuLocation(int index) {
+        // to be overridden
+        return new Point(0, 0);
+    }
+
+    /**
+     * Gets the selected item index.
+     * 
+     * @return the selected item index
+     */
+    int getSelectedItemIndex() {
+        return selectedItemIndex;
+    }
+
+    /**
+     * Hide.
+     */
+    void hide() {
+        selectedItemIndex = -1;
+        if (parent instanceof MenuComponent) {
+            ((MenuComponent) parent).itemHidden(this);
+        }
+    }
+
+    /**
+     * Item hidden.
+     * 
+     * @param mc the mc
+     */
+    void itemHidden(MenuComponent mc) {
+        // to be overridden
+    }
+
+    /**
+     * Checks if is visible.
+     * 
+     * @return true, if is visible
+     */
+    boolean isVisible() {
+        return true;
+    }
+
+    /**
+     * Checks if is active.
+     * 
+     * @return true, if is active
+     */
+    boolean isActive() {
+        return true;
+    }
+
+    /**
+     * Hide all menu hierarchy.
+     */
+    void endMenu() {
+        //???AWT: toolkit.dispatcher.popupDispatcher.deactivateAll();
+    }
+
+    /**
+     * Handle the mouse click or Enter key event on a menu's item.
+     * 
+     * @param when - the event time
+     * @param modifiers - input event modifiers
+     */
+    void itemSelected(long when, int modifiers) {
+        endMenu();
+    }
+
+    /**
+     * Auto name.
+     * 
+     * @return the string
+     */
+    String autoName() {
+        String name = getClass().getName();
+        if (name.indexOf("$") != -1) { //$NON-NLS-1$
+            return null;
+        }
+        //???AWT: int number = toolkit.autoNumber.nextMenuComponent++;
+        int number = 0;
+        name = name.substring(name.lastIndexOf(".") + 1) + Integer.toString(number); //$NON-NLS-1$
+        return name;
+    }
+
+    /**
+     * Creates the Graphics object for the pop-up box of this menu component.
+     * 
+     * @param clip - the clip to set on this Graphics
+     * 
+     * @return - the created Graphics object,
+     * or null if such object is not available.
+     */
+    Graphics getGraphics(MultiRectArea clip) {
+        // to be overridden
+        return null;
+    }
+
+    /**
+     * @return accessible context specific for particular menu component
+     */
+    //???AWT
+    /*
+    AccessibleContext createAccessibleContext() {
+        return null;
+    }
+    */
+}
diff --git a/awt/java/awt/MenuContainer.java b/awt/java/awt/MenuContainer.java
new file mode 100644
index 0000000..7a48f13
--- /dev/null
+++ b/awt/java/awt/MenuContainer.java
@@ -0,0 +1,56 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt;
+
+/**
+ * The MenuContainer interface represents all menu containers.
+ */
+public interface MenuContainer {
+
+    /**
+     * Removes the specified MenuComponent from the MenuContainer.
+     * 
+     * @param c the MenuComponent.
+     */
+    public void remove(MenuComponent c);
+
+    /**
+     * Gets the Font of the MenuContainer.
+     * 
+     * @return the font of the MenuContainer.
+     */
+    public Font getFont();
+
+    /**
+     * Posts an Event.
+     * 
+     * @param e the Event.
+     * 
+     * @return true if the event is posted successfully; 
+     * false otherwise.
+     * 
+     * @deprecated Replaced by dispatchEvent method.
+     */
+    @Deprecated
+    public boolean postEvent(Event e);
+
+}
+
diff --git a/awt/java/awt/ModalContext.java b/awt/java/awt/ModalContext.java
new file mode 100644
index 0000000..32a5912
--- /dev/null
+++ b/awt/java/awt/ModalContext.java
@@ -0,0 +1,64 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt;
+
+/**
+ *
+ * The context for nested event loop. It can be dialog, popup menu etc.
+ */
+class ModalContext {
+
+    private boolean running = false;
+
+    private final Toolkit toolkit;
+
+    ModalContext() {
+        toolkit = Toolkit.getDefaultToolkit();
+    }
+
+    /**
+     * Set up and run modal loop in this context
+     *
+     */
+    void runModalLoop() {
+        running = true;
+        toolkit.dispatchThread.runModalLoop(this);
+    }
+
+    /**
+     * Leave the modal loop running in this context
+     * This method doesn't stops the loop immediately,
+     * it just sets the flag that says the modal loop to stop
+     *
+     */
+    void endModalLoop() {
+        running = false;
+    }
+
+    /**
+     *
+     * @return modal loop is currently running in this context
+     */
+    boolean isModalLoopRunning() {
+        return running;
+    }
+
+}
diff --git a/awt/java/awt/MouseDispatcher.java b/awt/java/awt/MouseDispatcher.java
new file mode 100644
index 0000000..df48f9d
--- /dev/null
+++ b/awt/java/awt/MouseDispatcher.java
@@ -0,0 +1,418 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Dmitry A. Durnev, Michael Danilov, Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.awt.event.MouseWheelEvent;
+import java.awt.event.MouseWheelListener;
+import java.awt.Dispatcher.MouseGrabManager;
+import java.util.EventListener;
+
+import org.apache.harmony.awt.wtk.NativeEvent;
+import org.apache.harmony.awt.wtk.NativeWindow;
+
+
+class MouseDispatcher {
+
+    // Fields for synthetic mouse click events generation
+    private static final int clickDelta = 5;
+    private final long[] lastPressTime = new long[] {0l, 0l, 0l};
+    private final Point[] lastPressPos = new Point[] {null, null, null};
+    private final boolean[] buttonPressed = new boolean[] {false, false, false};
+    private final int[] clickCount = new int[] {0, 0, 0};
+
+    // Fields for mouse entered/exited support
+    private Component lastUnderPointer = null;
+    private final Point lastScreenPos = new Point(-1, -1);
+
+    // Fields for redundant mouse moved/dragged filtering
+    private Component lastUnderMotion = null;
+    private Point lastLocalPos = new Point(-1, -1);
+
+    private final MouseGrabManager mouseGrabManager;
+    private final Toolkit toolkit;
+
+    static Point convertPoint(Component src, int x, int y, Component dest) {
+        Point srcPoint = getAbsLocation(src);
+        Point destPoint = getAbsLocation(dest);
+
+        return new Point(x + (srcPoint.x - destPoint.x),
+                         y + (srcPoint.y - destPoint.y));
+    }
+
+    static Point convertPoint(Component src, Point p, Component dst) {
+        return convertPoint(src, p.x, p.y, dst);
+    }
+
+    private static Point getAbsLocation(Component comp) {
+        Point location = new Point(0, 0);
+// BEGIN android-changed: AWT components not supported
+//        for (Component parent = comp; parent != null; parent = parent.parent) {
+//            Point parentPos = (parent instanceof EmbeddedWindow ?
+//                               parent.getNativeWindow().getScreenPos() :
+//                               parent.getLocation());
+//
+//            location.translate(parentPos.x, parentPos.y);
+//
+//            if (parent instanceof Window) {
+//                break;
+//            }
+//        }
+// END android-changed
+
+        return location;
+    }
+
+    MouseDispatcher(MouseGrabManager mouseGrabManager,
+                    Toolkit toolkit) {
+        this.mouseGrabManager = mouseGrabManager;
+        this.toolkit = toolkit;
+    }
+
+    Point getPointerPos() {
+        return lastScreenPos;
+    }
+
+    boolean dispatch(Component src, NativeEvent event) {
+        int id = event.getEventId();
+
+        lastScreenPos.setLocation(event.getScreenPos());
+        checkMouseEnterExit(event.getInputModifiers(), event.getTime());
+
+        if (id == MouseEvent.MOUSE_WHEEL) {
+// BEGIN android-changed: AWT components not supported
+//            dispatchWheelEvent(src, event);
+// END android-changed
+        } else if ((id != MouseEvent.MOUSE_ENTERED) &&
+                   (id != MouseEvent.MOUSE_EXITED)) {
+            PointerInfo info = new PointerInfo(src, event.getLocalPos());
+
+            mouseGrabManager.preprocessEvent(event);
+            findEventSource(info);
+            if ((id == MouseEvent.MOUSE_PRESSED) ||
+                (id == MouseEvent.MOUSE_RELEASED)) {
+
+                dispatchButtonEvent(info, event);
+            } else if ((id == MouseEvent.MOUSE_MOVED) ||
+                       (id == MouseEvent.MOUSE_DRAGGED)) {
+
+                dispatchMotionEvent(info, event);
+            }
+        }
+
+        return false;
+    }
+
+    private void checkMouseEnterExit(int modifiers, long when) {
+// BEGIN android-changed: AWT components not supported
+//        PointerInfo info = findComponentUnderPointer();
+//        Component curUnderPointer =
+//                propagateEvent(info, AWTEvent.MOUSE_EVENT_MASK,
+//                               MouseListener.class, false).src;
+//
+//        if (curUnderPointer != lastUnderPointer) {
+//            Point pos = info.position;
+//            if ((lastUnderPointer != null) &&
+//                 lastUnderPointer.isMouseExitedExpected()) {
+//
+//                Point exitPos = convertPoint(null, lastScreenPos.x,
+//                                             lastScreenPos.y, lastUnderPointer);
+//
+//                postMouseEnterExit(MouseEvent.MOUSE_EXITED, modifiers, when,
+//                                   exitPos.x, exitPos.y, lastUnderPointer);
+//            }
+//            setCursor(curUnderPointer);
+//            if (curUnderPointer != null) {
+//                postMouseEnterExit(MouseEvent.MOUSE_ENTERED, modifiers, when,
+//                                   pos.x, pos.y, curUnderPointer);
+//            }
+//            lastUnderPointer = curUnderPointer;
+//        }
+// END android-changed
+    }
+
+    private void setCursor(Component comp) {
+        if (comp == null) {
+            return;
+        }
+        Component grabOwner = mouseGrabManager.getSyntheticGrabOwner();
+        Component cursorComp = ((grabOwner != null) &&
+                                 grabOwner.isShowing() ? grabOwner : comp);
+        cursorComp.setCursor();
+    }
+
+    private void postMouseEnterExit(int id, int mod, long when,
+                                    int x, int y, Component comp) {
+        if (comp.isIndirectlyEnabled()) {
+            toolkit.getSystemEventQueueImpl().postEvent(
+                    new MouseEvent(comp, id, when, mod, x, y, 0, false));
+            comp.setMouseExitedExpected(id == MouseEvent.MOUSE_ENTERED);
+        } else {
+            comp.setMouseExitedExpected(false);
+        }
+    }
+
+ // BEGIN android-changed: AWT components not supported
+//    private PointerInfo findComponentUnderPointer() {
+//        NativeWindow nativeWindow = toolkit.getWindowFactory().
+//        getWindowFromPoint(lastScreenPos);
+//
+//        if (nativeWindow != null) {
+//            Component comp = toolkit.getComponentById(nativeWindow.getId());
+//
+//            if (comp != null) {
+//                Window window = comp.getWindowAncestor();
+//                Point pointerPos = convertPoint(null, lastScreenPos.x,
+//                                                lastScreenPos.y, window);
+//
+//                if (window.getClient().contains(pointerPos)) {
+//                    PointerInfo info = new PointerInfo(window, pointerPos);
+//
+//                    fall2Child(info);
+//
+//                    return info;
+//                }
+//            }
+//        }
+//
+//        return new PointerInfo(null, null);
+//    }
+// END android-changed
+    
+    private void findEventSource(PointerInfo info) {
+        Component grabOwner = mouseGrabManager.getSyntheticGrabOwner();
+
+        if (grabOwner != null && grabOwner.isShowing()) {
+            info.position = convertPoint(info.src, info.position, grabOwner);
+            info.src = grabOwner;
+        } else {
+            //???AWT: rise2TopLevel(info);
+            //???AWT: fall2Child(info);
+        }
+    }
+
+ // BEGIN android-changed: AWT components not supported
+//    private void rise2TopLevel(PointerInfo info) {
+//        while (!(info.src instanceof Window)) {
+//            info.position.translate(info.src.x, info.src.y);
+//            info.src = info.src.parent;
+//        }
+//    }
+//
+//    private void fall2Child(PointerInfo info) {
+//        Insets insets = info.src.getInsets();
+//
+//        final Point pos = info.position;
+//        final int x = pos.x;
+//        final int y = pos.y;
+//        if ((x >= insets.left) && (y >= insets.top) &&
+//                (x < (info.src.w - insets.right)) &&
+//                (y < (info.src.h - insets.bottom)))
+//        {
+//            Component[] children = ((Container) info.src).getComponents();
+//
+//            for (Component child : children) {
+//                if (child.isShowing()) {
+//                    if (child.contains(x - child.getX(),
+//                            y - child.getY()))
+//                    {
+//                        info.src = child;
+//                        pos.translate(-child.x, -child.y);
+//
+//                        if (child instanceof Container) {
+//                            fall2Child(info);
+//                        }
+//
+//                        return;
+//                    }
+//                }
+//            }
+//        }
+//    }
+// END android-changed
+
+    private void dispatchButtonEvent(PointerInfo info, NativeEvent event) {
+        int button = event.getMouseButton();
+        long time = event.getTime();
+        int id = event.getEventId();
+        int index = button - 1;
+        boolean clickRequired = false;
+
+        propagateEvent(info, AWTEvent.MOUSE_EVENT_MASK,
+                       MouseListener.class, false);
+        if (id == MouseEvent.MOUSE_PRESSED) {
+            int clickInterval = toolkit.dispatcher.clickInterval;
+            mouseGrabManager.onMousePressed(info.src);
+            buttonPressed[index] = true;
+            clickCount[index] = (!deltaExceeded(index, info) &&
+                    ((time - lastPressTime[index]) <= clickInterval)) ?
+                    clickCount[index] + 1 : 1;
+            lastPressTime[index] = time;
+            lastPressPos[index] = info.position;
+        } else {
+            mouseGrabManager.onMouseReleased(info.src);
+            // set cursor back on synthetic mouse grab end:
+// BEGIN android-changed: AWT components not supported
+//            setCursor(findComponentUnderPointer().src);
+// END android-changed
+            if (buttonPressed[index]) {
+                buttonPressed[index] = false;
+                clickRequired = !deltaExceeded(index, info);
+            } else {
+                clickCount[index] = 0;
+            }
+        }
+        if (info.src.isIndirectlyEnabled()) {
+            final Point pos = info.position;
+            final int mod = event.getInputModifiers();
+            toolkit.getSystemEventQueueImpl().postEvent(
+                            new MouseEvent(info.src, id, time, mod, pos.x,
+                            pos.y, clickCount[index],
+                            event.getTrigger(), button));
+            if (clickRequired) {
+                toolkit.getSystemEventQueueImpl().postEvent(
+                            new MouseEvent(info.src,
+                            MouseEvent.MOUSE_CLICKED,
+                            time, mod, pos.x, pos.y,
+                            clickCount[index], false,
+                            button));
+            }
+        }
+    }
+
+    private boolean deltaExceeded(int index, PointerInfo info) {
+        final Point lastPos = lastPressPos[index];
+        if (lastPos == null) {
+            return true;
+        }
+        return ((Math.abs(lastPos.x - info.position.x) > clickDelta) ||
+                (Math.abs(lastPos.y - info.position.y) > clickDelta));
+    }
+
+    private void dispatchMotionEvent(PointerInfo info, NativeEvent event) {
+        propagateEvent(info, AWTEvent.MOUSE_MOTION_EVENT_MASK,
+                       MouseMotionListener.class, false);
+        final Point pos = info.position;
+        if ((lastUnderMotion != info.src) ||
+            !lastLocalPos.equals(pos)) {
+
+            lastUnderMotion = info.src;
+            lastLocalPos = pos;
+
+            if (info.src.isIndirectlyEnabled()) {
+                toolkit.getSystemEventQueueImpl().postEvent(
+                            new MouseEvent(info.src, event.getEventId(),
+                            event.getTime(),
+                            event.getInputModifiers(),
+                            pos.x, pos.y, 0, false));
+            }
+        }
+    }
+
+    MouseWheelEvent createWheelEvent(Component src, NativeEvent event,
+                                     Point where) {
+
+        Integer scrollAmountProperty =
+            (Integer)toolkit.getDesktopProperty("awt.wheelScrollingSize"); //$NON-NLS-1$
+        int amount = 1;
+        int type = MouseWheelEvent.WHEEL_UNIT_SCROLL;
+
+        if (scrollAmountProperty != null) {
+            amount = scrollAmountProperty.intValue();
+            if (amount == -1) {
+                type = MouseWheelEvent.WHEEL_BLOCK_SCROLL;
+                amount = 1;
+            }
+        }
+        return new MouseWheelEvent(src, event.getEventId(),
+                event.getTime(), event.getInputModifiers(),
+                where.x, where.y, 0, false, type, amount,
+                event.getWheelRotation());
+    }
+
+// BEGIN android-changed: AWT components not supported
+//    private void dispatchWheelEvent(Component src, NativeEvent event) {
+//        PointerInfo info = findComponentUnderPointer();
+//
+//        if (info.src == null) {
+//            info.src = src;
+//            info.position = event.getLocalPos();
+//        }
+//
+//        propagateEvent(info, AWTEvent.MOUSE_WHEEL_EVENT_MASK,
+//                       MouseWheelListener.class, true);
+//        if ((info.src != null) && info.src.isIndirectlyEnabled()) {
+//            toolkit.getSystemEventQueueImpl().postEvent(
+//                    createWheelEvent(info.src, event, info.position));
+//        }
+//    }
+// END android-changed
+
+    private PointerInfo propagateEvent(PointerInfo info, long mask,
+                                       Class<? extends EventListener> type, boolean pierceHW) {
+        Component src = info.src;
+        while ((src != null) &&
+               (src.isLightweight() || pierceHW) &&
+              !(src.isMouseEventEnabled(mask) ||
+               (src.getListeners(type).length > 0))) {
+
+            info.position.translate(src.x, src.y);
+// BEGIN android-changed: AWT components not supported
+//            src = src.parent;
+// END android-changed
+            info.src = src;
+        }
+
+        return info;
+    }
+
+// BEGIN android-changed: AWT components not supported
+//    Window findWindowAt(Point p) {
+//        NativeWindow nativeWindow =
+//            toolkit.getWindowFactory().getWindowFromPoint(p);
+//
+//        Window window = null;
+//        if (nativeWindow != null) {
+//            Component comp = toolkit.getComponentById(nativeWindow.getId());
+//
+//            if (comp != null) {
+//                window = comp.getWindowAncestor();
+//            }
+//        }
+//        return window;
+//    }
+// END android-changed
+
+    private class PointerInfo {
+
+        Component src;
+        Point position;
+
+        PointerInfo(Component src, Point position) {
+            this.src = src;
+            this.position = position;
+        }
+
+    }
+
+}
diff --git a/awt/java/awt/Paint.java b/awt/java/awt/Paint.java
new file mode 100644
index 0000000..f8732c8
--- /dev/null
+++ b/awt/java/awt/Paint.java
@@ -0,0 +1,52 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Alexey A. Petrenko
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.ColorModel;
+
+/**
+ * The Paint interface provides possibility of generating 
+ * color patterns in device space for fill, draw, or stroke operations 
+ * in a Graphics2D.
+ */
+public interface Paint extends Transparency {
+    
+    /**
+     * Creates the PaintContext which is used to generate color 
+     * patterns for rendering operations of Graphics2D.
+     * 
+     * @param cm the ColorModel object, or null.
+     * @param deviceBounds the Rectangle represents the bounding box of
+     * device space for the graphics rendering operations.
+     * @param userBounds the Rectangle represents bounding box of
+     * user space for the graphics rendering operations.
+     * @param xform the AffineTransform for translation from user space 
+     * to device space.
+     * @param hints the RenderingHints preferences.
+     * 
+     * @return the PaintContext for generating color patterns.
+     */
+    PaintContext createContext(ColorModel cm, Rectangle deviceBounds,
+            Rectangle2D userBounds, AffineTransform xform,
+            RenderingHints hints);
+}
diff --git a/awt/java/awt/PaintContext.java b/awt/java/awt/PaintContext.java
new file mode 100644
index 0000000..647de8b
--- /dev/null
+++ b/awt/java/awt/PaintContext.java
@@ -0,0 +1,64 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Alexey A. Petrenko
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.awt.image.ColorModel;
+import java.awt.image.Raster;
+
+/**
+ * The PaintContext interface determines the specific environment for
+ * generating color patterns in device space for fill, draw, or stroke 
+ * rendering operations using Graphics2D. This interface provides colors
+ * through the Raster object associated with the specific ColorModel 
+ * for Graphics2D rendering operations.
+ */
+public interface PaintContext {
+    
+    /**
+     * Releases the resources allocated for the operation.
+     */
+    void dispose();
+
+    /**
+     * Gets the color model.
+     * 
+     * @return the ColorModel object.
+     */
+    ColorModel getColorModel();
+
+    /**
+     * Gets the Raster which defines the colors of the specified rectangular 
+     * area for Graphics2D rendering operations.
+     * 
+     * @param x the X coordinate of the device space area for which 
+     * colors are generated.
+     * @param y the Y coordinate of the device space area for which 
+     * colors are generated.
+     * @param w the width of the device space area for which 
+     * colors are generated.
+     * @param h the height of the device space area for which 
+     * colors are generated.
+     * 
+     * @return the Raster object which contains the colors of the specified 
+     * rectangular area for Graphics2D rendering operations.
+     */
+    Raster getRaster(int x, int y, int w, int h);
+}
diff --git a/awt/java/awt/Point.java b/awt/java/awt/Point.java
new file mode 100644
index 0000000..99418ed
--- /dev/null
+++ b/awt/java/awt/Point.java
@@ -0,0 +1,195 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Denis M. Kishenko
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.awt.geom.Point2D;
+import java.io.Serializable;
+
+/**
+ * The Point class represents a point location with coordinates X, Y in 
+ * current coordinate system.
+ */
+public class Point extends Point2D implements Serializable {
+
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = -5276940640259749850L;
+
+    /** The X coordinate of Point. */
+    public int x;
+    
+    /** The Y coordinate of Point. */
+    public int y;
+
+    /**
+     * Instantiates a new point with (0, O) coordinates, the origin of 
+     * coordinate system.
+     */
+    public Point() {
+        setLocation(0, 0);
+    }
+
+    /**
+     * Instantiates a new point with (x, y) coordinates.
+     * 
+     * @param x the X coordinate of Point.
+     * @param y the Y coordinate of Point.
+     */
+    public Point(int x, int y) {
+        setLocation(x, y);
+    }
+
+    /**
+     * Instantiates a new point, giving it the same locaion as
+     * the parameter p.
+     * 
+     * @param p the Point object giving the coordinates of the new point.
+     */
+    public Point(Point p) {
+        setLocation(p.x, p.y);
+    }
+
+    /**
+     * Compares current Point with the specified object.
+     * 
+     * @param obj the Object to be compared.
+     * 
+     * @return true, if the Object being compared is a Point 
+     * whose coordinates are equal to the coordinates of this 
+     * Point, otherwise false.
+     * 
+     * @see java.awt.geom.Point2D#equals(Object)
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (obj instanceof Point) {
+            Point p = (Point)obj;
+            return x == p.x && y == p.y;
+        }
+        return false;
+    }
+
+    /**
+     * Returns string representation of the current Point object.
+     * 
+     * @return a string representation of the current Point object.
+     */
+    @Override
+    public String toString() {
+        return getClass().getName() + "[x=" + x + ",y=" + y + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+    }
+
+    /**
+     * Gets X coordinate of Point as a double.
+     * 
+     * @return X coordinate of the point as a double.
+     * 
+     * @see java.awt.geom.Point2D#getX()
+     */
+    @Override
+    public double getX() {
+        return x;
+    }
+
+    /**
+     * Gets Y coordinate of Point as a double.
+     * 
+     * @return Y coordinate of the point as a double.
+     * 
+     * @see java.awt.geom.Point2D#getY()
+     */
+    @Override
+    public double getY() {
+        return y;
+    }
+
+    /**
+     * Gets the location of the Point as a new Point object.
+     * 
+     * @return a copy of the Point.
+     */
+    public Point getLocation() {
+        return new Point(x, y);
+    }
+
+    /**
+     * Sets the location of the Point to the same coordinates as p.
+     * 
+     * @param p the Point that gives the new location.
+     */
+    public void setLocation(Point p) {
+        setLocation(p.x, p.y);
+    }
+
+    /**
+     * Sets the location of the Point to the coordinates X, Y.
+     * 
+     * @param x the X coordinate of the Point's new location.
+     * @param y the Y coordinate of the Point's new location.
+     */
+    public void setLocation(int x, int y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    /**
+     * Sets the location of Point to the specified double coordinates.
+     * 
+     * @param x the X the Point's new location.
+     * @param y the Y the Point's new location.
+     *  
+     * @see java.awt.geom.Point2D#setLocation(double, double)
+     */
+    @Override
+    public void setLocation(double x, double y) {
+        x = x < Integer.MIN_VALUE ? Integer.MIN_VALUE : x > Integer.MAX_VALUE ? Integer.MAX_VALUE : x;
+        y = y < Integer.MIN_VALUE ? Integer.MIN_VALUE : y > Integer.MAX_VALUE ? Integer.MAX_VALUE : y;
+        setLocation((int)Math.round(x), (int)Math.round(y));
+    }
+
+    /**
+     * Moves the Point to the specified (x, y) location.
+     * 
+     * @param x the X coordinate of the new location.
+     * @param y the Y coordinate of the new location. 
+     */
+    public void move(int x, int y) {
+        setLocation(x, y);
+    }
+
+    /**
+     * Translates current Point moving it from the position (x, y) 
+     * to the new position given by (x+dx, x+dy) coordinates.
+     * 
+     * @param dx the horizontal delta - the Point is moved to this distance along
+     * X axis.
+     * @param dy the vertical delta - the Point is moved to this distance along
+     * Y axis.
+     */
+    public void translate(int dx, int dy) {
+        x += dx;
+        y += dy;
+    }
+
+}
+
diff --git a/awt/java/awt/Polygon.java b/awt/java/awt/Polygon.java
new file mode 100644
index 0000000..6f3fc97
--- /dev/null
+++ b/awt/java/awt/Polygon.java
@@ -0,0 +1,494 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Denis M. Kishenko
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.io.Serializable;
+import java.util.NoSuchElementException;
+
+import org.apache.harmony.awt.gl.*;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Polygon class defines an closed area specified by n vertices and 
+ * n edges. The coordinates of the vertices are specified by x, y arrays.
+ * The edges are the line segments from the point (x[i], y[i]) to the point 
+ * (x[i+1], y[i+1]), for -1 < i < (n-1) plus the line segment from 
+ * the point (x[n-1], y[n-1]) to the point (x[0], y[0]) point. 
+ * The Polygon is empty if the number of vertices is zero.   
+ */
+public class Polygon implements Shape, Serializable {
+
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = -6460061437900069969L;
+
+    /** The points buffer capacity. */
+    private static final int BUFFER_CAPACITY = 4;
+    
+    /** The number of Polygon vertices.*/
+    public int npoints;
+    
+    /** The array of X coordinates of the vertices. */
+    public int[] xpoints;
+    
+    /** The array of Y coordinates of the vertices. */
+    public int[] ypoints;
+    
+    /**  
+     * The smallest Rectangle that completely contains this Polygon. 
+     */
+    protected Rectangle bounds;
+
+    /*
+     * Polygon path iterator  
+     */
+    /**
+     * The internal Class Iterator.
+     */
+    class Iterator implements PathIterator {
+
+        /** The source Polygon object. */
+        public Polygon p;
+        
+        /** The path iterator transformation. */
+        public AffineTransform t;
+        
+        /** The current segmenet index. */
+        public int index;
+
+        /**
+         * Constructs a new Polygon.Iterator for the given polygon and transformation
+         * 
+         * @param at - the AffineTransform object to apply rectangle path
+         * @param p the p
+         */
+        public Iterator(AffineTransform at, Polygon p) {
+            this.p = p;
+            this.t = at;
+            if (p.npoints == 0) {
+                index = 1;
+            }
+        }
+
+        public int getWindingRule() {
+            return WIND_EVEN_ODD;
+        }
+
+        public boolean isDone() {
+            return index > p.npoints;
+        }
+
+        public void next() {
+            index++;
+        }
+
+        public int currentSegment(double[] coords) {
+            if (isDone()) {
+                // awt.110=Iterator out of bounds
+                throw new NoSuchElementException(Messages.getString("awt.110")); //$NON-NLS-1$
+            }
+            if (index == p.npoints) {
+                return SEG_CLOSE;
+            }
+            coords[0] = p.xpoints[index];
+            coords[1] = p.ypoints[index];
+            if (t != null) {
+                t.transform(coords, 0, coords, 0, 1);
+            }
+            return index == 0 ? SEG_MOVETO : SEG_LINETO;
+        }
+
+        public int currentSegment(float[] coords) {
+            if (isDone()) {
+                // awt.110=Iterator out of bounds
+                throw new NoSuchElementException(Messages.getString("awt.110")); //$NON-NLS-1$
+            }
+            if (index == p.npoints) {
+                return SEG_CLOSE;
+            }
+            coords[0] = p.xpoints[index];
+            coords[1] = p.ypoints[index];
+            if (t != null) {
+                t.transform(coords, 0, coords, 0, 1);
+            }
+            return index == 0 ? SEG_MOVETO : SEG_LINETO;
+        }
+    }
+
+    /**
+     * Instantiates a new empty polygon.
+     */
+    public Polygon() {
+        xpoints = new int[BUFFER_CAPACITY];
+        ypoints = new int[BUFFER_CAPACITY];
+    }
+
+    /**
+     * Instantiates a new polygon with the specified number of vertices,
+     * and the given arrays of x, y vertex coordinates. The length of 
+     * each coordinate array may not be less than the specified number of 
+     * vertices but may be greater. Only the first n elements are used from 
+     * each coordinate array.
+     * 
+     * @param xpoints the array of X vertex coordinates. 
+     * @param ypoints the array of Y vertex coordinates.
+     * @param npoints the number vertices of the polygon.
+     * @throws IndexOutOfBoundsException if the length of xpoints or ypoints
+     * is less than n.
+     * @throws NegativeArraySizeException if n is negative.
+     */
+    public Polygon(int[] xpoints, int[] ypoints, int npoints) {
+        if (npoints > xpoints.length || npoints > ypoints.length) {
+            // awt.111=Parameter npoints is greater than array length
+            throw new IndexOutOfBoundsException(Messages.getString("awt.111")); //$NON-NLS-1$
+        }
+        if (npoints < 0) {
+            // awt.112=Negative number of points
+            throw new NegativeArraySizeException(Messages.getString("awt.112")); //$NON-NLS-1$
+        }
+        this.npoints = npoints;
+        this.xpoints = new int[npoints];
+        this.ypoints = new int[npoints];
+        System.arraycopy(xpoints, 0, this.xpoints, 0, npoints);
+        System.arraycopy(ypoints, 0, this.ypoints, 0, npoints);
+    }
+
+    /**
+     * Resets the current Polygon to an empty Polygon. More precisely, 
+     * the number of Polygon vertices is set to zero, but x, y coordinates 
+     * arrays are not affected.  
+     */
+    public void reset() {
+        npoints = 0;
+        bounds = null;
+    }
+
+    /**
+     * Invalidates the data that depends on the vertex coordinates. 
+     * This method should be called after direct manipulations  
+     * of the x, y vertex coordinates arrays to avoid unpredictable 
+     * results of methods which rely on the bounding box.
+     */
+    public void invalidate() {
+        bounds = null;
+    }
+
+    /**
+     * Adds the point to the Polygon and updates the bounding box 
+     * accordingly.
+     * 
+     * @param px the X coordinate of the added vertex.
+     * @param py the Y coordinate of the added vertex.
+     */
+    public void addPoint(int px, int py) {
+        if (npoints == xpoints.length) {
+            int[] tmp;
+
+            tmp = new int[xpoints.length + BUFFER_CAPACITY];
+            System.arraycopy(xpoints, 0, tmp, 0, xpoints.length);
+            xpoints = tmp;
+
+            tmp = new int[ypoints.length + BUFFER_CAPACITY];
+            System.arraycopy(ypoints, 0, tmp, 0, ypoints.length);
+            ypoints = tmp;
+        }
+
+        xpoints[npoints] = px;
+        ypoints[npoints] = py;
+        npoints++;
+
+        if (bounds != null) {
+            bounds.setFrameFromDiagonal(
+                    Math.min(bounds.getMinX(), px),
+                    Math.min(bounds.getMinY(), py),
+                    Math.max(bounds.getMaxX(), px),
+                    Math.max(bounds.getMaxY(), py));
+        }
+    }
+
+    /**
+     * Gets the bounding rectangle of the Polygon. The bounding rectangle
+     * is the smallest rectangle which contains the Polygon.
+     * 
+     * @return the bounding rectangle of the Polygon.
+     * 
+     * @see java.awt.Shape#getBounds()
+     */
+    public Rectangle getBounds() {
+        if (bounds != null) {
+            return bounds;
+        }
+        if (npoints == 0) {
+            return new Rectangle();
+        }
+
+        int bx1 = xpoints[0];
+        int by1 = ypoints[0];
+        int bx2 = bx1;
+        int by2 = by1;
+
+        for (int i = 1; i < npoints; i++) {
+            int x = xpoints[i];
+            int y = ypoints[i];
+            if (x < bx1) {
+                bx1 = x;
+            } else if (x > bx2) {
+                bx2 = x;
+            }
+            if (y < by1) {
+                by1 = y;
+            } else if (y > by2) {
+                by2 = y;
+            }
+        }
+
+        return bounds = new Rectangle(bx1, by1, bx2 - bx1, by2 - by1);
+    }
+
+    /**
+     * Gets the bounding rectangle of the Polygon. The bounding rectangle
+     * is the smallest rectangle which contains the Polygon.
+     * 
+     * @return the bounding rectangle of the Polygon.
+     * 
+     * @deprecated Use getBounds() method.
+     */
+    @Deprecated
+    public Rectangle getBoundingBox() {
+        return getBounds();
+    }
+
+    /**
+     * Gets the Rectangle2D which represents Polygon bounds.
+     * The bounding rectangle is the smallest rectangle which contains 
+     * the Polygon.
+     * 
+     * @return the bounding rectangle of the Polygon.
+     * 
+     * @see java.awt.Shape#getBounds2D()
+     */
+    public Rectangle2D getBounds2D() {
+        return getBounds().getBounds2D();
+    }
+
+    /**
+     * Translates all vertices of Polygon the specified distances
+     * along X, Y axis.
+     * 
+     * @param mx the distance to translate horizontally.
+     * @param my the distance to translate vertically.
+     */
+    public void translate(int mx, int my) {
+        for (int i = 0; i < npoints; i++) {
+            xpoints[i] += mx;
+            ypoints[i] += my;
+        }
+        if (bounds != null) {
+            bounds.translate(mx, my);
+        }
+    }
+
+    /**
+     * Checks whether or not the point given by the coordinates x, y lies inside 
+     * the Polygon.
+     * 
+     * @param x the X coordinate of the point to check.
+     * @param y the Y coordinate of the point to check.
+     * 
+     * @return true, if the specified point lies inside the Polygon,
+     * otherwise false.
+     * 
+     * @deprecated Use contains(int, int) method.
+     */
+    @Deprecated
+    public boolean inside(int x, int y) {
+        return contains((double) x, (double) y);
+    }
+
+    /**
+     * Checks whether or not the point given by the coordinates x, y lies inside 
+     * the Polygon.
+     * 
+     * @param x the X coordinate of the point to check.
+     * @param y the Y coordinate of the point to check.
+     * 
+     * @return true, if the specified point lies inside the Polygon,
+     * otherwise false.
+     */
+    public boolean contains(int x, int y) {
+        return contains((double) x, (double) y);
+    }
+
+    /**
+     * Checks whether or not the point with specified double coordinates 
+     * lies inside the Polygon.
+     * 
+     * @param x the X coordinate of the point to check.
+     * @param y the Y coordinate of the point to check.
+     * 
+     * @return true, if the point given by the double coordinates 
+     * lies inside the Polygon, otherwise false.
+     * 
+     * @see java.awt.Shape#contains(double, double)
+     */
+    public boolean contains(double x, double y) {
+        return Crossing.isInsideEvenOdd(Crossing.crossShape(this, x, y));
+    }
+
+    /**
+     * Checks whether or not the rectangle determined by the parameters  
+     * [x, y, width, height] lies inside the Polygon.
+     * 
+     * @param x the X coordinate of the rectangles's left upper 
+     * corner as a double.
+     * @param y the Y coordinate of the rectangles's left upper 
+     * corner as a double.
+     * @param width the width of rectangle as a double.
+     * @param width the height of rectangle as a double.
+     * 
+     * @return true, if the specified rectangle lies inside the Polygon,
+     * otherwise false.
+     * 
+     * @see java.awt.Shape#contains(double, double, double, double)
+     */
+    public boolean contains(double x, double y, double width, double height) {
+        int cross = Crossing.intersectShape(this, x, y, width, height);
+        return cross != Crossing.CROSSING && Crossing.isInsideEvenOdd(cross);
+    }
+
+    /**
+     * Checks whether or not the rectangle determined by the parameters  
+     * [x, y, width, height] intersects the interior of
+     * the Polygon.
+     * 
+     * @param x the X coordinate of the rectangles's left upper 
+     * corner as a double.
+     * @param y the Y coordinate of the rectangles's left upper 
+     * corner as a double.
+     * @param width the width of rectangle as a double.
+     * @param width the height of rectangle as a double.
+     * 
+     * @return true, if the specified rectangle intersects the interior of
+     * the Polygon, otherwise false.
+     * 
+     * @see java.awt.Shape#intersects(double, double, double, double)
+     */
+    public boolean intersects(double x, double y, double width, double height) {
+        int cross = Crossing.intersectShape(this, x, y, width, height);
+        return cross == Crossing.CROSSING || Crossing.isInsideEvenOdd(cross);
+    }
+
+    /**
+     * Checks whether or not the specified rectangle lies inside the Polygon.
+     * 
+     * @param rect the Rectangle2D object.
+     * 
+     * @return true, if the specified rectangle lies inside the Polygon,
+     * otherwise false.
+     * 
+     * @see java.awt.Shape#contains(java.awt.geom.Rectangle2D)
+     */
+    public boolean contains(Rectangle2D rect) {
+        return contains(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
+    }
+
+    /**
+     * Checks whether or not the specified Point lies inside the Polygon.
+     * 
+     * @param point the Point object.
+     * 
+     * @return true, if the specified Point lies inside the Polygon,
+     * otherwise false.
+     */
+    public boolean contains(Point point) {
+        return contains(point.getX(), point.getY());
+    }
+
+    /**
+     * Checks whether or not the specified Point2D lies inside the Polygon.
+     * 
+     * @param point the Point2D object.
+     * 
+     * @return true, if the specified Point2D lies inside the Polygon,
+     * otherwise false.
+     * 
+     * @see java.awt.Shape#contains(java.awt.geom.Point2D)
+     */
+    public boolean contains(Point2D point) {
+        return contains(point.getX(), point.getY());
+    }
+
+    /**
+     * Checks whether or not the interior of rectangle specified by 
+     * the Rectangle2D object intersects the interior of the Polygon.
+     * 
+     * @param rect the Rectangle2D object.
+     * 
+     * @return true, if the Rectangle2D intersects the interior of
+     * the Polygon, otherwise false.
+     * 
+     * @see java.awt.Shape#intersects(java.awt.geom.Rectangle2D)
+     */
+    public boolean intersects(Rectangle2D rect) {
+        return intersects(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
+    }
+
+    /**
+     * Gets the PathIterator object which gives the coordinates of 
+     * the polygon, transformed according to the specified AffineTransform.
+     * 
+     * @param t the specified AffineTransform object, or null.
+     * 
+     * @return PathIterator object for the Polygon.
+     * 
+     * @see java.awt.Shape#getPathIterator(java.awt.geom.AffineTransform)
+     */
+    public PathIterator getPathIterator(AffineTransform t) {
+        return new Iterator(t, this);
+    }
+
+    /**
+     * Gets the PathIterator object which gives the coordinates of 
+     * the polygon, transformed according to the specified AffineTransform.
+     * The flatness parameter is ignored.
+     * 
+     * @param t the specified AffineTransform object, or null.
+     * @param flatness the maximum number of the control points for 
+     * a given curve which varies from colinear before a subdivided curve 
+     * is replaced by a straight line connecting the endpoints. 
+     * This parameter is ignored for the Polygon class.
+     * 
+     * @return PathIterator object for the Polygon.
+     *  
+     * @see java.awt.Shape#getPathIterator(java.awt.geom.AffineTransform, double)
+     */
+    public PathIterator getPathIterator(AffineTransform t, double flatness) {
+        return new Iterator(t, this);
+    }
+
+}
+
diff --git a/awt/java/awt/Rectangle.java b/awt/java/awt/Rectangle.java
new file mode 100644
index 0000000..86c4dfc
--- /dev/null
+++ b/awt/java/awt/Rectangle.java
@@ -0,0 +1,686 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Denis M. Kishenko
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.awt.geom.Rectangle2D;
+import java.io.Serializable;
+
+/**
+ * The Rectangle class defines the rectangular area in terms of its
+ * upper left corner coordinates [x,y], its width, and its height.  
+ * A Rectangle specified by [x, y, width, height] parameters has an 
+ * outline path with corners at [x, y], [x + width,y], [x + width,y + height], 
+ * and [x, y + height]. 
+ * <br><br>
+ * The rectangle is empty if the width or height is negative or zero. 
+ * In this case the isEmpty method returns true.
+ */
+public class Rectangle extends Rectangle2D implements Shape, Serializable {
+
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = -4345857070255674764L;
+
+    /** The X coordinate of the rectangle's left upper corner. */
+    public int x;
+    
+    /** The Y coordinate of the rectangle's left upper corner. */
+    public int y;
+    
+    /** The width of rectangle. */
+    public int width;
+    
+    /** The height of rectangle. */
+    public int height;
+
+    /**
+     * Instantiates a new rectangle with [0, 0] upper left corner coordinates,
+     * the width and the height are zero.
+     */
+    public Rectangle() {
+        setBounds(0, 0, 0, 0);
+    }
+
+    /**
+     * Instantiates a new rectangle whose upper left corner coordinates are
+     * given by the Point object (p.X and p.Y), and the width and 
+     * the height are zero. 
+     * 
+     * @param p the Point specifies the upper left corner coordinates of 
+     * the rectangle.
+     */
+    public Rectangle(Point p) {
+        setBounds(p.x, p.y, 0, 0);
+    }
+
+    /**
+      * Instantiates a new rectangle whose upper left corner coordinates are
+     * given by the Point object (p.X and p.Y), and the width and the height
+     * are given by Dimension object (d.width and d.height). 
+     * 
+     * @param p the Point specifies the upper left corner coordinates of 
+     * the rectangle.
+     * @param d the Dimention specifies the width and the height of the rectangle. 
+     */
+    public Rectangle(Point p, Dimension d) {
+        setBounds(p.x, p.y, d.width, d.height);
+    }
+
+    /**
+     * Instantiates a new rectangle determined by the upper left corner 
+     * coordinates (x, y), width and height.
+     * 
+     * @param x the X upper left corner coordinate of the rectangle.
+     * @param y the Y upper left corner coordinate of the rectangle.
+     * @param width the width of rectangle.
+     * @param height the height of rectangle. 
+     */
+    public Rectangle(int x, int y, int width, int height) {
+        setBounds(x, y, width, height);
+    }
+
+    /**
+     * Instantiates a new rectangle with [0, 0] as its upper left 
+     * corner coordinates and the specified width and height.
+     * 
+     * @param width the width of rectangle.
+     * @param height the height of rectangle. 
+     */
+    public Rectangle(int width, int height) {
+        setBounds(0, 0, width, height);
+    }
+
+    /**
+     * Instantiates a new rectangle with the same coordinates 
+     * as the given source rectangle.
+     * 
+     * @param r the Rectangle object which parameters will be used for 
+     * instantiating a new Rectangle.
+     */
+    public Rectangle(Rectangle r) {
+        setBounds(r.x, r.y, r.width, r.height);
+    }
+/*
+    public Rectangle(Dimension d) {
+        setBounds(0, 0, d.width, d.height);
+    }
+*/
+    /**
+     * Gets the X coordinate of bound as a double.
+     * 
+     * @return the X coordinate of bound as a double.
+     *   
+     * @see java.awt.geom.RectangularShape#getX()
+     */
+    @Override
+    public double getX() {
+        return x;
+    }
+
+    /**
+     * Gets the Y coordinate of bound as a double.
+     * 
+     * @return the Y coordinate of bound as a double.
+     * 
+     * @see java.awt.geom.RectangularShape#getY()
+     */
+    @Override
+    public double getY() {
+        return y;
+    }
+
+    /**
+     * Gets the height of the rectangle as a double.
+     * 
+     * @return the height of the rectangle as a double. 
+     * 
+     * @see java.awt.geom.RectangularShape#getHeight()
+     */
+    @Override
+    public double getHeight() {
+        return height;
+    }
+
+    /**
+     * Gets the width of the rectangle as a double.
+     * 
+     * @return the width of the rectangle as a double.
+     *  
+     * @see java.awt.geom.RectangularShape#getWidth()
+     */
+    @Override
+    public double getWidth() {
+        return width;
+    }
+
+    /**
+     * Determines whether or not the rectangle is empty. The rectangle is empty if 
+     * its width or height is negative or zero.
+     * 
+     * @return true, if the rectangle is empty, otherwise false.
+     * 
+     * @see java.awt.geom.RectangularShape#isEmpty()
+     */
+    @Override
+    public boolean isEmpty() {
+        return width <= 0 || height <= 0;
+    }
+
+    /**
+     * Gets the size of a Rectangle as Dimention object.
+     * 
+     * @return a Dimention object which represents size of the rectangle.
+     */
+    public Dimension getSize() {
+        return new Dimension(width, height);
+    }
+
+    /**
+     * Sets the size of the Rectangle.
+     * 
+     * @param width the new width of the rectangle. 
+     * @param height the new height of the rectangle.
+     */
+    public void setSize(int width, int height) {
+        this.width = width;
+        this.height = height;
+    }
+
+    /**
+     * Sets the size of a Rectangle specified as Dimension object.
+     * 
+     * @param d a Dimension object which represents new size of a rectangle.
+     */
+    public void setSize(Dimension d) {
+        setSize(d.width, d.height);
+    }
+
+    /**
+     * Gets the location of a rectangle's upper left corner as a Point object.
+     * 
+     * @return the Point object with coordinates equal to the upper left corner 
+     * of the rectangle.
+     */
+    public Point getLocation() {
+        return new Point(x, y);
+    }
+
+    /**
+     * Sets the location of the rectangle in terms of its upper left 
+     * corner coordinates X and Y.
+     * 
+     * @param x the X coordinate of the rectangle's upper left corner.
+     * @param y the Y coordinate of the rectangle's upper left corner.
+     */
+    public void setLocation(int x, int y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    /**
+     * Sets the location of a rectangle using a Point object to give the 
+     * coordinates of the upper left corner.
+     * 
+     * @param p the Point object which represents the new upper left corner 
+     * coordinates of rectangle.  
+     */
+    public void setLocation(Point p) {
+        setLocation(p.x, p.y);
+    }
+
+    /**
+     * Moves a rectangle to the new location by moving its upper left corner
+     * to the point with coordinates X and Y.
+     * 
+     * @param x the new X coordinate of the rectangle's upper left corner.
+     * @param y the new Y coordinate of the rectangle's upper left corner.
+     * 
+     * @deprecated Use setLocation(int, int) method.
+     */
+    @Deprecated
+    public void move(int x, int y) {
+        setLocation(x, y);
+    }
+
+    /**
+     * Sets the rectangle to be the nearest rectangle with integer coordinates 
+     * bounding the rectangle defined by the double-valued parameters.
+     * 
+     * @param x the X coordinate of the upper left corner of the double-valued
+     * rectangle to be bounded.
+     * @param y the Y coordinate of the upper left corner of the double-valued
+     * rectangle to be bounded.
+     * @param width the width of the rectangle to be bounded.
+     * @param height the height of the rectangle to be bounded.      
+     * 
+     * @see java.awt.geom.Rectangle2D#setRect(double, double, double, double)
+     */
+    @Override
+    public void setRect(double x, double y, double width, double height) {
+        int x1 = (int)Math.floor(x);
+        int y1 = (int)Math.floor(y);
+        int x2 = (int)Math.ceil(x + width);
+        int y2 = (int)Math.ceil(y + height);
+        setBounds(x1, y1, x2 - x1, y2 - y1);
+    }
+
+    /**
+     * Sets a new size for the rectangle.
+     * 
+     * @param width the rectangle's new width.
+     * @param height the rectangle's new height.
+     * 
+     * @deprecated use the setSize(int, int) method.
+     */
+    @Deprecated
+    public void resize(int width, int height) {
+        setBounds(x, y, width, height);
+    }
+
+    /**
+     * Resets the bounds of a rectangle to the specified x, y, width and height 
+     * parameters.
+     * 
+     * @param x the new X coordinate of the upper left corner.
+     * @param y the new Y coordinate of the upper left corner.
+     * @param width the new width of rectangle.
+     * @param height the new height of rectangle. 
+     * 
+     * @deprecated use setBounds(int, int, int, int) method
+     */
+    @Deprecated
+    public void reshape(int x, int y, int width, int height) {
+        setBounds(x, y, width, height);
+    }
+
+    /**
+     * Gets bounds of the rectangle as a new Rectangle object.
+     *  
+     * @return the Rectangle object with the same bounds as 
+     * the original rectangle. 
+     * 
+     * @see java.awt.geom.RectangularShape#getBounds()
+     */
+    @Override
+    public Rectangle getBounds() {
+        return new Rectangle(x, y, width, height);
+    }
+
+    /**
+     * Gets the bounds of the original rectangle as a Rectangle2D object.
+     *  
+     * @return the Rectangle2D object which represents the bounds of 
+     * the original rectangle. 
+     * 
+     * @see java.awt.geom.Rectangle2D#getBounds2D()
+     */
+    @Override
+    public Rectangle2D getBounds2D() {
+        return getBounds();
+    }
+
+    /**
+     * Sets the bounds of a rectangle to the specified x, y, width, and height 
+     * parameters.
+     * 
+     * @param x the X coordinate of the upper left corner.
+     * @param y the Y coordinate of the upper left corner.
+     * @param width the width of rectangle.
+     * @param height the height of rectangle. 
+     */
+    public void setBounds(int x, int y, int width, int height) {
+        this.x = x;
+        this.y = y;
+        this.height = height;
+        this.width = width;
+    }
+
+    /**
+     * Sets the bounds of the rectangle to match the bounds of the
+     * Rectangle object sent as a parameter.
+     * 
+     * @param r the Rectangle object which specifies the new bounds. 
+     */
+    public void setBounds(Rectangle r) {
+        setBounds(r.x, r.y, r.width, r.height);
+    }
+
+    /**
+     * Enlarges the rectangle by moving each corner outward from the 
+     * center by a distance of dx horizonally and a distance of dy 
+     * vertically. Specifically, changes a rectangle with 
+     * [x, y, width, height] parameters to 
+     * a rectangle with [x-dx, y-dy, width+2*dx, height+2*dy]
+     * parameters. 
+     *   
+     * @param dx the horizontal distance to move each corner coordinate.
+     * @param dy the vertical distance to move each corner coordinate.
+     */
+    public void grow(int dx, int dy) {
+        x -= dx;
+        y -= dy;
+        width += dx + dx;
+        height += dy + dy;
+    }
+
+    /**
+     * Moves a rectangle a distance of mx along the x coordinate axis 
+     * and a distance of my along y coordinate axis.
+     * 
+     * @param mx the horizontal translation increment.
+     * @param my the vertical translation increment.
+     */
+    public void translate(int mx, int my) {
+        x += mx;
+        y += my;
+    }
+
+    /**
+     * Enlarges the rectangle to cover the specified point.
+     * 
+     * @param px the X coordinate of the new point to be covered by the rectangle.
+     * @param py the Y coordinate of the new point to be covered by the rectangle.
+     */
+    public void add(int px, int py) {
+        int x1 = Math.min(x, px);
+        int x2 = Math.max(x + width, px);
+        int y1 = Math.min(y, py);
+        int y2 = Math.max(y + height, py);
+        setBounds(x1, y1, x2 - x1, y2 - y1);
+    }
+
+    /**
+     * Enlarges the rectangle to cover the specified point with the
+     * new point given as a Point object.
+     * 
+     * @param p the Point object that specifies the new point to 
+     * be covered by the rectangle.
+     */
+    public void add(Point p) {
+        add(p.x, p.y);
+    }
+
+    /**
+     * Adds a new rectangle to the original rectangle, the result is an union of
+     * the specified specified rectangle and original rectangle.
+     * 
+     * @param r the Rectangle which is added to the original rectangle. 
+     */
+    public void add(Rectangle r) {
+        int x1 = Math.min(x, r.x);
+        int x2 = Math.max(x + width, r.x + r.width);
+        int y1 = Math.min(y, r.y);
+        int y2 = Math.max(y + height, r.y + r.height);
+        setBounds(x1, y1, x2 - x1, y2 - y1);
+    }
+
+    /**
+     * Determines whether or not the point with specified coordinates [px, py] 
+     * is within the bounds of the rectangle.
+     * 
+     * @param px the X coordinate of point.
+     * @param py the Y coordinate of point.
+     * 
+     * @return true, if the point with specified coordinates [px, py] is 
+     * within the bounds of the rectangle, otherwise false.
+     */
+    public boolean contains(int px, int py) {
+        if (isEmpty()) {
+            return false;
+        }
+        if (px < x || py < y) {
+            return false;
+        }
+        px -= x;
+        py -= y;
+        return px < width && py < height;
+    }
+
+    /**
+     * Determines whether or not the point given as a Point object 
+     * is within the bounds of the rectangle.
+     * 
+     * @param p the Point object
+     * 
+     * @return true, if the point p is within the bounds of the 
+     * rectangle, otherwise false.
+     */
+    public boolean contains(Point p) {
+        return contains(p.x, p.y);
+    }
+
+    /**
+     * Determines whether or not the rectangle specified by [rx, ry, rw, rh] 
+     * parameters is located inside the original rectangle.
+     * 
+     * @param rx the X coordinate of the rectangle to compare.
+     * @param ry the Y coordinate of the rectangle to compare.
+     * @param rw the width of the rectangle to compare.
+     * @param rh the height of the rectangle to compare.
+     * 
+     * @return true, if a rectangle with [rx, ry, rw, rh] parameters is entirely
+     * contained in the original rectangle, otherwise false.
+     */
+    public boolean contains(int rx, int ry, int rw, int rh) {
+        return contains(rx, ry) && contains(rx + rw - 1, ry + rh - 1);
+    }
+
+    /**
+     * Compares whether or not the rectangle specified by the Rectangle object
+     * is located inside the original rectangle.
+     * 
+     * @param r the Rectangle object.
+     * 
+     * @return true, if the rectangle specified by Rectangle object is entirely
+     * contained in the original rectangle, otherwise false.
+     */
+    public boolean contains(Rectangle r) {
+        return contains(r.x, r.y, r.width, r.height);
+    }
+
+    /**
+     * Compares whether or not a point with specified coordinates [px, py] belongs 
+     * to a rectangle.
+     * 
+     * @param px the X coordinate of a point.
+     * @param py the Y coordinate of a point.
+     * 
+     * @return true, if a point with specified coordinates [px, py] belongs 
+     * to a rectangle, otherwise false.
+     * 
+     * @deprecated use contains(int, int) method.
+     */
+    @Deprecated
+    public boolean inside(int px, int py) {
+        return contains(px, py);
+    }
+
+    /**
+     * Returns the intersection of the original rectangle with the 
+     * specified Rectangle2D.
+     * 
+     * @param r the Rectangle2D object.
+     * 
+     * @return the Rectangle2D object that is the result of intersecting 
+     * the original rectangle with the specified Rectangle2D.
+     * 
+     * @see java.awt.geom.Rectangle2D#createIntersection(java.awt.geom.Rectangle2D)
+     */
+    @Override
+    public Rectangle2D createIntersection(Rectangle2D r) {
+        if (r instanceof Rectangle) {
+            return intersection((Rectangle) r);
+        }
+        Rectangle2D dst = new Rectangle2D.Double();
+        Rectangle2D.intersect(this, r, dst);
+        return dst;
+    }
+
+    /**
+     * Returns the intersection of the original rectangle with the 
+     * specified rectangle. An empty rectangle is returned if there is no
+     * intersection.
+     * 
+     * @param r the Rectangle object.
+     * 
+     * @return the Rectangle object is result of the original rectangle with the 
+     * specified rectangle. 
+     */
+    public Rectangle intersection(Rectangle r) {
+        int x1 = Math.max(x, r.x);
+        int y1 = Math.max(y, r.y);
+        int x2 = Math.min(x + width, r.x + r.width);
+        int y2 = Math.min(y + height, r.y + r.height);
+        return new Rectangle(x1, y1, x2 - x1, y2 - y1);
+    }
+
+    /**
+     * Determines whether or not the original rectangle intersects 
+     * the specified rectangle.
+     * 
+     * @param r the Rectangle object.
+     * 
+     * @return true, if the two rectangles overlap; otherwise false.
+     */
+    public boolean intersects(Rectangle r) {
+        return !intersection(r).isEmpty();
+    }
+
+    /**
+     * Determines where the specified Point is located with respect to 
+     * the rectangle. This method computes whether the point is to the 
+     * right or to the left of the rectangle and whether it is above 
+     * or below the rectangle, and packs the result into an int by 
+     * using a binary OR operation with the following masks:
+     * <ul>
+     *<li>Rectangle2D.OUT_LEFT</li>
+     *<li>Rectangle2D.OUT_TOP</li>
+     *<li>Rectangle2D.OUT_RIGHT</li>
+     *<li>Rectangle2D.OUT_BOTTOM</li>
+     *</ul>
+     *
+     * If the rectangle is empty, all masks are set, and if the 
+     * point is inside the rectangle, none are set.
+     * 
+     * @param px the X coordinate of the specified point.
+     * @param py the Y coordinate of the specified point.
+     * 
+     * @return the location of the Point relative to the rectangle 
+     * as the result of logical OR operation with all out masks.
+     * 
+     * @see java.awt.geom.Rectangle2D#outcode(double, double)
+     */
+    @Override
+    public int outcode(double px, double py) {
+        int code = 0;
+
+        if (width <= 0) {
+            code |= OUT_LEFT | OUT_RIGHT;
+        } else
+            if (px < x) {
+                code |= OUT_LEFT;
+            } else
+                if (px > x + width) {
+                    code |= OUT_RIGHT;
+                }
+
+        if (height <= 0) {
+            code |= OUT_TOP | OUT_BOTTOM;
+        } else
+            if (py < y) {
+                code |= OUT_TOP;
+            } else
+                if (py > y + height) {
+                    code |= OUT_BOTTOM;
+                }
+
+        return code;
+    }
+
+    /**
+     * Enlarges the rectangle to cover the specified Rectangle2D.
+     * 
+     * @param r the Rectangle2D object.
+     * 
+     * @return the union of the original and the specified Rectangle2D.
+     * 
+     * @see java.awt.geom.Rectangle2D#createUnion(java.awt.geom.Rectangle2D)
+     */
+    @Override
+    public Rectangle2D createUnion(Rectangle2D r) {
+        if (r instanceof Rectangle) {
+            return union((Rectangle)r);
+        }
+        Rectangle2D dst = new Rectangle2D.Double();
+        Rectangle2D.union(this, r, dst);
+        return dst;
+    }
+
+    /**
+     * Enlarges the rectangle to cover the specified rectangle.
+     * 
+     * @param r the Rectangle.
+     * 
+     * @return the union of the original and the specified rectangle.
+     */
+    public Rectangle union(Rectangle r) {
+        Rectangle dst = new Rectangle(this);
+        dst.add(r);
+        return dst;
+    }
+
+    /**
+     * Compares the original Rectangle with the specified object.
+     * 
+     * @param obj the specified Object for comparison.
+     * 
+     * @return true, if the specified Object is a rectangle with the 
+     * same dimensions as the original rectangle, otherwise false.
+     * 
+     * @see java.awt.geom.Rectangle2D#equals(Object)
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (obj instanceof Rectangle) {
+            Rectangle r = (Rectangle)obj;
+            return r.x == x && r.y == y && r.width == width && r.height == height;
+        }
+        return false;
+    }
+
+    /**
+     * Returns a string representation of the rectangle; the string contains 
+     * [x, y, width, height] parameters of the rectangle.
+     * 
+     * @return the string representation of the rectangle.
+     */
+    @Override
+    public String toString() {
+        // The output format based on 1.5 release behaviour. It could be obtained in the following way
+        // System.out.println(new Rectangle().toString())
+        return getClass().getName() + "[x=" + x + ",y=" + y + //$NON-NLS-1$ //$NON-NLS-2$
+            ",width=" + width + ",height=" + height + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+    }
+
+}
+
diff --git a/awt/java/awt/RenderingHints.java b/awt/java/awt/RenderingHints.java
new file mode 100644
index 0000000..4957884
--- /dev/null
+++ b/awt/java/awt/RenderingHints.java
@@ -0,0 +1,601 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Alexey A. Petrenko
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * The RenderingHints class represents preferences for the rendering algorithms. 
+ * The preferences are arbitrary and can be specified by Map objects or by 
+ * key-value pairs. 
+ */
+public class RenderingHints implements Map<Object, Object>, Cloneable {
+    
+    /**
+     * The Constant KEY_ALPHA_INTERPOLATION - alpha interpolation rendering 
+     * hint key. 
+     */
+    public static final Key KEY_ALPHA_INTERPOLATION = new KeyImpl(1);
+    
+    /** 
+     * The Constant VALUE_ALPHA_INTERPOLATION_DEFAULT - alpha interpolation
+     * rendering hint value.
+     */
+    public static final Object VALUE_ALPHA_INTERPOLATION_DEFAULT = new KeyValue(KEY_ALPHA_INTERPOLATION);
+    
+    /** 
+     * The Constant VALUE_ALPHA_INTERPOLATION_SPEED - alpha interpolation
+     * rendering hint value.
+     */
+    public static final Object VALUE_ALPHA_INTERPOLATION_SPEED = new KeyValue(KEY_ALPHA_INTERPOLATION);
+    
+    /** 
+     * The Constant VALUE_ALPHA_INTERPOLATION_QUALITY - alpha interpolation
+     * rendering hint value.
+     */
+    public static final Object VALUE_ALPHA_INTERPOLATION_QUALITY = new KeyValue(KEY_ALPHA_INTERPOLATION);
+
+    /** 
+     * The Constant KEY_ANTIALIASING - antialiasing rendering 
+     * hint key. 
+     */
+    public static final Key KEY_ANTIALIASING = new KeyImpl(2);
+    
+    /**
+     * The Constant VALUE_ANTIALIAS_DEFAULT - antialiasing
+     * rendering hint value. 
+     */
+    public static final Object VALUE_ANTIALIAS_DEFAULT = new KeyValue(KEY_ANTIALIASING);
+    
+    /** 
+     * The Constant VALUE_ANTIALIAS_ON - antialiasing
+     * rendering hint value.
+     */
+    public static final Object VALUE_ANTIALIAS_ON = new KeyValue(KEY_ANTIALIASING);
+    
+    /**
+     * The Constant VALUE_ANTIALIAS_OFF - antialiasing
+     * rendering hint value.
+     */
+    public static final Object VALUE_ANTIALIAS_OFF = new KeyValue(KEY_ANTIALIASING);
+
+    /** 
+     * The Constant KEY_COLOR_RENDERING  - color rendering 
+     * hint key.
+     */
+    public static final Key KEY_COLOR_RENDERING = new KeyImpl(3);
+    
+    /**
+     * The Constant VALUE_COLOR_RENDER_DEFAULT - color
+     * rendering hint value. 
+     */
+    public static final Object VALUE_COLOR_RENDER_DEFAULT = new KeyValue(KEY_COLOR_RENDERING);
+    
+    /** 
+     * The Constant VALUE_COLOR_RENDER_SPEED  - color
+     * rendering hint value. 
+     */
+    public static final Object VALUE_COLOR_RENDER_SPEED = new KeyValue(KEY_COLOR_RENDERING);
+    
+    /** 
+     * The Constant VALUE_COLOR_RENDER_QUALITY - color
+     * rendering hint value.
+     */
+    public static final Object VALUE_COLOR_RENDER_QUALITY = new KeyValue(KEY_COLOR_RENDERING);
+
+    /**
+     *  The Constant KEY_DITHERING  - dithering
+     * rendering hint key.
+     */
+    public static final Key KEY_DITHERING = new KeyImpl(4);
+    
+    /**
+     * The Constant VALUE_DITHER_DEFAULT - dithering
+     * rendering hint value.
+     */
+    public static final Object VALUE_DITHER_DEFAULT = new KeyValue(KEY_DITHERING);
+    
+    /** 
+     * The Constant VALUE_DITHER_DISABLE - dithering
+     * rendering hint value.
+     */
+    public static final Object VALUE_DITHER_DISABLE = new KeyValue(KEY_DITHERING);
+    
+    /** 
+     * The Constant VALUE_DITHER_DISABLE - dithering
+     * rendering hint value.
+     */
+    public static final Object VALUE_DITHER_ENABLE = new KeyValue(KEY_DITHERING);
+
+    /** 
+     * The Constant KEY_FRACTIONALMETRICS - fractional metrics
+     * rendering hint key.
+     */
+    public static final Key KEY_FRACTIONALMETRICS = new KeyImpl(5);
+    
+    /**
+     * The Constant VALUE_FRACTIONALMETRICS_DEFAULT - fractional metrics
+     * rendering hint value.
+     */
+    public static final Object VALUE_FRACTIONALMETRICS_DEFAULT = new KeyValue(KEY_FRACTIONALMETRICS);
+    
+    /**
+     * The Constant VALUE_FRACTIONALMETRICS_ON - fractional metrics
+     * rendering hint value.
+     */
+    public static final Object VALUE_FRACTIONALMETRICS_ON = new KeyValue(KEY_FRACTIONALMETRICS);
+    
+    /**
+     *  The Constant VALUE_FRACTIONALMETRICS_OFF - fractional metrics
+     * rendering hint value.
+     */
+    public static final Object VALUE_FRACTIONALMETRICS_OFF = new KeyValue(KEY_FRACTIONALMETRICS);
+
+    /** 
+     * The Constant KEY_INTERPOLATION - interpolation
+     * rendering hint key.
+     */
+    public static final Key KEY_INTERPOLATION = new KeyImpl(6);
+    
+    /** 
+     * The Constant VALUE_INTERPOLATION_BICUBIC - interpolation
+     * rendering hint value. 
+     */
+    public static final Object VALUE_INTERPOLATION_BICUBIC = new KeyValue(KEY_INTERPOLATION);
+    
+    /**
+     * The Constant VALUE_INTERPOLATION_BILINEAR - interpolation
+     * rendering hint value.
+     */
+    public static final Object VALUE_INTERPOLATION_BILINEAR = new KeyValue(KEY_INTERPOLATION);
+    
+    /** The Constant VALUE_INTERPOLATION_NEAREST_NEIGHBOR - interpolation
+     * rendering hint value.
+     */
+    public static final Object VALUE_INTERPOLATION_NEAREST_NEIGHBOR = new KeyValue(KEY_INTERPOLATION);
+
+    /**
+     * The Constant KEY_RENDERING - rendering hint key.
+     */
+    public static final Key KEY_RENDERING = new KeyImpl(7);
+    
+    /** 
+     * The Constant VALUE_RENDER_DEFAULT - rendering hint value. 
+     */
+    public static final Object VALUE_RENDER_DEFAULT = new KeyValue(KEY_RENDERING);
+    
+    /** 
+     * The Constant VALUE_RENDER_SPEED - rendering hint value. 
+     */
+    public static final Object VALUE_RENDER_SPEED = new KeyValue(KEY_RENDERING);
+    
+    /** 
+     * The Constant VALUE_RENDER_QUALITY - rendering hint value. 
+     */
+    public static final Object VALUE_RENDER_QUALITY = new KeyValue(KEY_RENDERING);
+
+    /** 
+     * The Constant KEY_STROKE_CONTROL - stroke control hint key. 
+     */
+    public static final Key KEY_STROKE_CONTROL = new KeyImpl(8);
+    
+    /** 
+     * The Constant VALUE_STROKE_DEFAULT - stroke hint value. 
+     */
+    public static final Object VALUE_STROKE_DEFAULT = new KeyValue(KEY_STROKE_CONTROL);
+    
+    /** 
+     * The Constant VALUE_STROKE_NORMALIZE - stroke hint value. 
+     */
+    public static final Object VALUE_STROKE_NORMALIZE = new KeyValue(KEY_STROKE_CONTROL);
+    
+    /** 
+     * The Constant VALUE_STROKE_PURE - stroke hint value. 
+     */
+    public static final Object VALUE_STROKE_PURE = new KeyValue(KEY_STROKE_CONTROL);
+
+    /** 
+     * The Constant KEY_TEXT_ANTIALIASING - text antialiasing hint key. 
+     */
+    public static final Key KEY_TEXT_ANTIALIASING = new KeyImpl(9);
+    
+    /**
+     *  The Constant VALUE_TEXT_ANTIALIAS_DEFAULT - text antialiasing hint key. 
+     */
+    public static final Object VALUE_TEXT_ANTIALIAS_DEFAULT = new KeyValue(KEY_TEXT_ANTIALIASING);
+    
+    /**
+     * The Constant VALUE_TEXT_ANTIALIAS_ON - text antialiasing hint key.
+     */
+    public static final Object VALUE_TEXT_ANTIALIAS_ON = new KeyValue(KEY_TEXT_ANTIALIASING);
+    
+    /**
+     * The Constant VALUE_TEXT_ANTIALIAS_OFF - text antialiasing hint key. 
+     */
+    public static final Object VALUE_TEXT_ANTIALIAS_OFF = new KeyValue(KEY_TEXT_ANTIALIASING);
+
+    /** The map. */
+    private HashMap<Object, Object> map = new HashMap<Object, Object>();
+    
+    /**
+     * Instantiates a new rendering hints object from specified Map object with defined
+     * key/value pairs or null for empty RenderingHints. 
+     * 
+     * @param map the Map object with defined key/value pairs or null for
+     * empty RenderingHints. 
+     */
+    public RenderingHints(Map<Key, ?> map) {
+        super();
+        if (map != null) {
+            putAll(map);
+        }
+    }
+
+    /**
+     * Instantiates a new rendering hints object with the specified key/value pair.
+     * 
+     * @param key the key of hint property.
+     * @param value the value of hint property.
+     */
+    public RenderingHints(Key key, Object value) {
+        super();
+        put(key, value);
+    }
+
+    /**
+     * Adds the properties represented by key/value pairs from the specified
+     * RenderingHints object to current object.
+     * 
+     * @param hints the RenderingHints to be added.
+     */
+    public void add(RenderingHints hints) {
+        map.putAll(hints.map);
+    }
+
+    /**
+     * Puts the specified value to the specified key. Neither the key nor 
+     * the value can be null.
+     * 
+     * @param key the rendering hint key.
+     * @param value the rendering hint value. 
+     * 
+     * @return the previous rendering hint value assigned to the key or null.
+     * 
+     */
+    public Object put(Object key, Object value) {
+        if (!((Key)key).isCompatibleValue(value)) {
+            throw new IllegalArgumentException();
+        }
+
+        return map.put(key, value);
+    }
+
+    /**
+     * Removes the specified key and corresponding value from 
+     * the RenderingHints object.
+     * 
+     * @param key the specified hint key to be removed.
+     * 
+     * @return the object of previous rendering hint value which is 
+     * assigned to the specified key, or null.
+     */
+    public Object remove(Object key) {
+        return map.remove(key);
+    }
+
+    /**
+     * Gets the value assigned to the specified key.
+     * 
+     * @param key the rendering hint key.
+     * 
+     * @return the object assigned to the specified key.
+     */
+    public Object get(Object key) {
+        return map.get(key);
+    }
+
+    /**
+     * Returns a set of rendering hints keys for current RenderingHints object.
+     * 
+     * @return the set of rendering hints keys. 
+     */
+    public Set<Object> keySet() {
+        return map.keySet();
+    }
+
+    /**
+     * Returns a set of Map.Entry objects which contain current RenderingHint
+     * key/value pairs.
+     * 
+     * @return the a set of mapped RenderingHint key/value pairs.
+     */
+    public Set<Map.Entry<Object, Object>> entrySet() {
+        return map.entrySet();
+    }
+
+    /**
+     * Puts all of the preferences from the specified Map into 
+     * the current RenderingHints object. These mappings replace 
+     * all existing preferences.
+     * 
+     * @param m the specified Map of preferences.
+     */
+    public void putAll(Map<?, ?> m) {
+        if (m instanceof RenderingHints) {
+            map.putAll(((RenderingHints) m).map);
+        } else {
+            Set<?> entries = m.entrySet();
+
+            if (entries != null){
+                Iterator<?> it = entries.iterator();
+                while (it.hasNext()) {
+                    Map.Entry<?, ?> entry = (Map.Entry<?, ?>) it.next();
+                    Key key = (Key) entry.getKey();
+                    Object val = entry.getValue();
+                    put(key, val);
+                }
+            }
+        }
+    }
+
+    /**
+     * Returns a Collection of values contained in current RenderingHints object.
+     * 
+     * @return the Collection of RenderingHints's values.
+     */
+    public Collection<Object> values() {
+        return map.values();
+    }
+
+    /**
+     * Checks whether or not current RenderingHints object contains at least one
+     * the value which is equal to the specified Object.
+     * 
+     * @param value the specified Object.
+     * 
+     * @return true, if the specified object is assigned to at least one
+     * RenderingHint's key, false otherwise.
+     */
+    public boolean containsValue(Object value) {
+        return map.containsValue(value);
+    }
+
+    /**
+     * Checks whether or not current RenderingHints object contains the key
+     * which is equal to the specified Object.
+     * 
+     * @param key the specified Object.
+     * 
+     * @return true, if the RenderingHints object contains the specified Object
+     * as a key, false otherwise.
+     * 
+     */
+    public boolean containsKey(Object key) {
+        if (key == null) {
+            throw new NullPointerException();
+        }
+
+        return map.containsKey(key);
+    }
+
+    /**
+     * Checks whether or not the RenderingHints object contains any 
+     * key/value pairs.
+     * 
+     * @return true, if the RenderingHints object is empty, false otherwise.
+     */
+    public boolean isEmpty() {
+        return map.isEmpty();
+    }
+
+    /**
+     * Clears the RenderingHints of all key/value pairs.
+     */
+    public void clear() {
+        map.clear();
+    }
+
+    /**
+     * Returns the number of key/value pairs in the RenderingHints.
+     * 
+     * @return the number of key/value pairs.
+     */
+    public int size() {
+        return map.size();
+    }
+
+    /**
+     * Compares the RenderingHints object with the specified object.
+     * 
+     * @param o the specified Object to be compaired.
+     * 
+     * @return true, if the Object is a Map whose key/value pairs 
+     * match this RenderingHints' key/value pairs, 
+     * false otherwise.
+     */
+    @Override
+    public boolean equals(Object o) {
+        if (!(o instanceof Map)) {
+            return false;
+        }
+
+        Map<?, ?> m = (Map<?, ?>)o;
+        Set<?> keys = keySet();
+        if (!keys.equals(m.keySet())) {
+            return false;
+        }
+
+        Iterator<?> it = keys.iterator();
+        while (it.hasNext()) {
+            Key key = (Key)it.next();
+            Object v1 = get(key);
+            Object v2 = m.get(key);
+            if (!(v1==null?v2==null:v1.equals(v2))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Returns the hash code for this RenderingHints object.
+     * 
+     * @return the hash code for this RenderingHints object.
+     */
+    @Override
+    public int hashCode() {
+        return map.hashCode();
+    }
+
+    /**
+     * Returns the clone of the RenderingHints object with the same contents.
+     * 
+     * @return the clone of the RenderingHints instance.
+     */
+    @SuppressWarnings("unchecked")
+    @Override
+    public Object clone() {
+        RenderingHints clone = new RenderingHints(null);
+        clone.map = (HashMap<Object, Object>)this.map.clone();
+        return clone;
+    }
+
+    /**
+     * Returns the string representation of the RenderingHints object.
+     * 
+     * @return the String object which represents RenderingHints object. 
+     */
+    @Override
+    public String toString() {
+        return "RenderingHints["+map.toString()+"]"; //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * The RenderingHints.Key class is abstract and defines a base type for 
+     * all RenderingHints keys.
+     */
+    public abstract static class Key {
+        
+        /** The key. */
+        private final int key;
+
+        /**
+         * Instantiates a new key with unique int identifier. 
+         * No two objects of the same subclass with the same integer key
+         * can be instantiated. 
+         * 
+         * @param key the unique key.
+         */
+        protected Key(int key) {
+            this.key = key;
+        }
+
+        /**
+         * Compares the Key object with the specified object.
+         * 
+         * @param o the specified Object to be compaired.
+         * 
+         * @return true, if the Key is equal to the specified object, 
+         * false otherwise.
+         */
+        @Override
+        public final boolean equals(Object o) {
+            return this == o;
+        }
+
+        /**
+         * Returns the hash code for this Key object.
+         * 
+         * @return the hash code for this Key object.
+         */
+        @Override
+        public final int hashCode() {
+            return System.identityHashCode(this);
+        }
+
+        /**
+         * Returns int unique key with which this Key object has been 
+         * instantiated.
+         * 
+         * @return the int unique key with which this Key object has been 
+         * instantiated.
+         */
+        protected final int intKey() {
+            return key;
+        }
+
+        /**
+         * Checks whether or not specified value is compatible with the Key.
+         * 
+         * @param val the Object.
+         * 
+         * @return true, if the specified value is compatible with the Key,
+         * false otherwise.
+         */
+        public abstract boolean isCompatibleValue(Object val);
+    }
+
+    /**
+     * Private implementation of Key class.
+     */
+    private static class KeyImpl extends Key {
+
+        /**
+         * Instantiates a new key impl.
+         * 
+         * @param key the key
+         */
+        protected KeyImpl(int key) {
+            super(key);
+        }
+
+        @Override
+        public boolean isCompatibleValue(Object val) {
+            if (!(val instanceof KeyValue)) {
+                return false;
+            }
+
+            return ((KeyValue)val).key == this;
+        }
+    }
+
+    /**
+     * Private class KeyValue is used as value for Key class instance.
+     */
+    private static class KeyValue {
+        
+        /** The key. */
+        private final Key key;
+
+        /**
+         * Instantiates a new key value.
+         * 
+         * @param key the key
+         */
+        protected KeyValue(Key key) {
+            this.key = key;
+        }
+    }
+}
diff --git a/awt/java/awt/Shape.java b/awt/java/awt/Shape.java
new file mode 100644
index 0000000..3dbad25
--- /dev/null
+++ b/awt/java/awt/Shape.java
@@ -0,0 +1,162 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Alexey A. Petrenko
+ * @version $Revision$
+ */
+package java.awt;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * The Shape interface defines a geometric shape defined by a boundary 
+ * (outline) path. The path outline can be accessed through a 
+ * PathIterator object. The Shape 
+ * interface provides methods for obtaining the bounding box (which is 
+ * the smallest rectangle containing the shape and for obtaining a PathIterator 
+ * object for current Shape, as well as utility methods which 
+ * determine if the Shape contains or intersects a Rectangle or contains a Point.
+ */
+public interface Shape {
+    
+    /**
+     * Checks whether or not the point with specified coordinates lies inside 
+     * the Shape.
+     * 
+     * @param x the X coordinate.
+     * @param y the Y coordinate.
+     * 
+     * @return true, if the specified coordinates lie inside the Shape,
+     * otherwise false.
+     */
+    public boolean contains(double x, double y);
+
+    /**
+     * Checks whether or not the rectangle with specified 
+     * [x, y, width, height] parameters lies inside the Shape.
+     * 
+     * @param x the X double coordinate of the rectangle's upper left 
+     * corner.
+     * @param y the Y double coordinate of the rectangle's upper left 
+     * corner.
+     * @param w the width of rectangle.
+     * @param h the height of rectangle.
+     * 
+     * @return true, if the specified rectangle lies inside the Shape,
+     * otherwise false.
+     */
+    public boolean contains(double x, double y, double w, double h);
+
+    /**
+     * Checks whether or not the specified Point2D lies inside the Shape.
+     * 
+     * @param point the Point2D object.
+     * 
+     * @return true, if the specified Point2D lies inside the Shape,
+     * otherwise false.
+     */
+    public boolean contains(Point2D point);
+
+    /**
+     * Checks whether or not the specified rectangle lies inside the Shape.
+     * 
+     * @param r the Rectangle2D object.
+     * 
+     * @return true, if the specified rectangle lies inside the Shape,
+     * otherwise false.
+     */
+    public boolean contains(Rectangle2D r);
+
+    /**
+     * Gets the bounding rectangle of the Shape. The bounding rectangle
+     * is the smallest rectangle which contains the Shape.
+     * 
+     * @return the bounding rectangle of the Shape.
+     */
+    public Rectangle getBounds();
+
+    /**
+     * Gets the Rectangle2D which represents Shape bounds.
+     * The bounding rectangle is the smallest rectangle which contains 
+     * the Shape.
+     * 
+     * @return the bounding rectangle of the Shape.
+     */
+    public Rectangle2D getBounds2D();
+
+    /**
+     * Gets the PathIterator object of the Shape which provides 
+     * access to the shape's boundary modified 
+     * by the specified AffineTransform.
+     * 
+     * @param at the specified AffineTransform object, or null.
+     * 
+     * @return PathIterator object for the Shape.
+     */
+    public PathIterator getPathIterator(AffineTransform at);
+
+    /**
+     * Gets the PathIterator object of the Shape which provides 
+     * access to the coordinates of the shapes boundary modified 
+     * by the specified AffineTransform. The flatness parameter
+     * defines the amount of subdivision of the curved segments and
+     * specifies the maximum distance which every point on the 
+     * unflattened transformed curve can deviate from the returned 
+     * flattened path segments.  
+     * 
+     * @param at the specified AffineTransform object, or null.
+     * @param flatness the maximum number of the control points for 
+     * a given curve which varies from colinear before a subdivided 
+     * curve is replaced by a straight line connecting the endpoints. 
+     * 
+     * @return PathIterator object for the Shape.
+     */
+    public PathIterator getPathIterator(AffineTransform at, double flatness);
+
+    /**
+     * Checks whether or not the interior of rectangular specified by 
+     * [x, y, width, height] parameters intersects the interior of
+     * the Shape.
+     * 
+     * @param x the X double coordinate of the rectangle's upper left
+     * corner.
+     * @param y the Y double coordinate of the rectangle's upper left 
+     * corner.
+     * @param w the width of rectangle.
+     * @param h the height of rectangle.
+     * 
+     * @return true, if the rectangle specified by 
+     * [x, y, width, height] parameters intersects the interior of
+     * the Shape, otherwise false.
+     * 
+     */
+    public boolean intersects(double x, double y, double w, double h);
+
+    /**
+     * Checks whether or not the interior of rectangl specified by 
+     * Rectangle2D object intersects the interior of the Shape.
+     * 
+     * @param r the Rectangle2D object.
+     * 
+     * @return true, if the Rectangle2D intersects the interior of
+     * the Shape, otherwise false.
+     */
+    public boolean intersects(Rectangle2D r);
+}
diff --git a/awt/java/awt/Stroke.java b/awt/java/awt/Stroke.java
new file mode 100644
index 0000000..e6d683d
--- /dev/null
+++ b/awt/java/awt/Stroke.java
@@ -0,0 +1,47 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Alexey A. Petrenko
+ * @version $Revision$
+ */
+package java.awt;
+
+/**
+ * The Stroke interface gives a pen style to be used by the 
+ * Graphics2D interface. It provides a means for getting a stroked version 
+ * of a shape, which is the version that is suitable for drawing via 
+ * the Graphics2D interface. Stroking a shape gives the shape's outline
+ * a width or drawing style. 
+ * <p>
+ * The Draw methods from Graphics2D interface should use the Stroke object for 
+ * rendering the shape's outline. The stroke should be set by 
+ * setStroke(java.awt.Stroke) method of the Graphics2D interface. 
+ * @see java.awt.Graphics2D#setStroke(java.awt.Stroke)
+ */
+public interface Stroke {
+    
+    /**
+     * Creates the stroked shape, which is the version that is suitable for drawing via 
+     * the Graphics2D interface. Stroking a shape gives the shape's outline
+     * a width or drawing style.
+     * 
+     * @param p the original shape.
+     * 
+     * @return the stroked shape.
+     */
+    public Shape createStrokedShape(Shape p);
+}
diff --git a/awt/java/awt/Toolkit.java b/awt/java/awt/Toolkit.java
new file mode 100644
index 0000000..0c066b2
--- /dev/null
+++ b/awt/java/awt/Toolkit.java
@@ -0,0 +1,1338 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package java.awt;
+
+import java.awt.event.AWTEventListener;
+import java.awt.event.AWTEventListenerProxy;
+import java.awt.event.InputEvent;
+import java.awt.im.InputMethodHighlight;
+import java.awt.image.ColorModel;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.awt.peer.FontPeer;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+
+import java.lang.reflect.InvocationTargetException;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Collections;
+import java.util.EventListener;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.MissingResourceException;
+import java.util.Properties;
+import java.util.ResourceBundle;
+
+import org.apache.harmony.awt.ChoiceStyle;
+import org.apache.harmony.awt.ComponentInternals;
+import org.apache.harmony.awt.ContextStorage;
+import org.apache.harmony.awt.ReadOnlyIterator;
+import org.apache.harmony.awt.internal.nls.Messages;
+import org.apache.harmony.awt.wtk.CreationParams;
+import org.apache.harmony.awt.wtk.GraphicsFactory;
+import org.apache.harmony.awt.wtk.NativeCursor;
+
+import org.apache.harmony.awt.wtk.NativeEventQueue;
+import org.apache.harmony.awt.wtk.NativeEventThread;
+import org.apache.harmony.awt.wtk.ShutdownWatchdog;
+import org.apache.harmony.awt.wtk.Synchronizer;
+import org.apache.harmony.awt.wtk.WTK;
+
+/**
+ * The Toolkit class is the representation of the platform-specific 
+ * Abstract Window Toolkit implementation. Toolkit's subclasses 
+ * are used to bind the various components to particular native 
+ * toolkit implementations.
+ */
+public abstract class Toolkit {
+    
+    /** The Constant RECOURCE_PATH. */
+    private static final String RECOURCE_PATH = "org.apache.harmony.awt.resources.AWTProperties"; //$NON-NLS-1$
+    
+    /** The Constant properties. */
+    private static final ResourceBundle properties = loadResources(RECOURCE_PATH);
+    
+    /** The dispatcher. */
+    Dispatcher dispatcher;
+
+    /** The system event queue core. */
+    private EventQueueCore systemEventQueueCore;
+
+    /** The dispatch thread. */
+    EventDispatchThread dispatchThread;
+
+    /** The native thread. */
+    NativeEventThread nativeThread;
+
+    /** The awt events manager. */
+    protected AWTEventsManager awtEventsManager;
+
+    /**
+     * The Class AWTTreeLock.
+     */
+    private class AWTTreeLock {
+    }
+
+    /** The awt tree lock. */
+    final Object awtTreeLock = new AWTTreeLock();
+
+    /** The synchronizer. */
+    private final Synchronizer synchronizer = ContextStorage.getSynchronizer();
+
+    /** The shutdown watchdog. */
+    final ShutdownWatchdog shutdownWatchdog = new ShutdownWatchdog();
+
+    /** The auto number. */
+    final AutoNumber autoNumber = new AutoNumber();
+
+    /** The event type lookup. */
+    final AWTEvent.EventTypeLookup eventTypeLookup = new AWTEvent.EventTypeLookup();
+
+    /** The b dynamic layout set. */    
+    private boolean bDynamicLayoutSet = true;
+
+    /** The set of desktop properties that user set directly. */
+    private final HashSet<String> userPropSet = new HashSet<String>();
+
+    /** The desktop properties. */
+    protected Map<String, Object> desktopProperties;
+
+    /** The desktop props support. */
+    protected PropertyChangeSupport desktopPropsSupport;
+
+    /**
+     * For this component the native window is being created
+     * It is used in the callback-driven window creation
+     * (e.g. on Windows in the handler of WM_CREATE event)
+     * to establish the connection between this component
+     * and its native window.
+     */
+    private Object recentNativeWindowComponent;
+
+    /** The wtk. */
+    private WTK wtk;
+
+    /**
+     * The Class ComponentInternalsImpl.
+     */
+    protected final class ComponentInternalsImpl extends ComponentInternals {
+
+        /**
+         * Shutdown.
+         */
+        @Override
+        public void shutdown() {
+            dispatchThread.shutdown();
+        }
+       
+        /**
+         * Sets the desktop property to the specified value and fires a property 
+         * change event.  
+         * 
+         * @param name the name of property.
+         * @param value the new value of property.
+         */
+        @Override
+        public void setDesktopProperty(String name, Object value) {
+            Toolkit.this.setDesktopProperty(name, value);
+        }
+    }
+
+
+    /**
+     * A lot of methods must throw HeadlessException
+     * if <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code>.
+     * 
+     * @throws HeadlessException the headless exception
+     */
+    static void checkHeadless() throws HeadlessException {
+        if (GraphicsEnvironment.getLocalGraphicsEnvironment().isHeadlessInstance())
+            throw new HeadlessException();
+    }
+
+    /**
+     * Lock awt.
+     */
+    final void lockAWT() {
+        synchronizer.lock();
+    }
+
+    /**
+     * Static lock awt.
+     */
+    static final void staticLockAWT() {
+        ContextStorage.getSynchronizer().lock();
+    }
+
+    /**
+     * Unlock awt.
+     */
+    final void unlockAWT() {
+        synchronizer.unlock();
+    }
+
+    /**
+     * Static unlock awt.
+     */
+    static final void staticUnlockAWT() {
+        ContextStorage.getSynchronizer().unlock();
+    }    
+
+    /**
+     * InvokeAndWait under AWT lock. W/o this method system can hang up.
+     * Added to support modality (Dialog.show() & PopupMenu.show()) from
+     * not event dispatch thread. Use in other cases is not recommended.
+     *
+     * Still can be called only for whole API methods that
+     * cannot be called from other classes API methods.
+     * Examples:
+     *      show() for modal dialogs    - correct, only user can call it,
+     *                                      directly or through setVisible(true)
+     *      setBounds() for components  - incorrect, setBounds()
+     *                                      can be called from layoutContainer()
+     *                                      for layout managers
+     * 
+     * @param runnable the runnable
+     * 
+     * @throws InterruptedException the interrupted exception
+     * @throws InvocationTargetException the invocation target exception
+     */
+    final void unsafeInvokeAndWait(Runnable runnable) throws InterruptedException,
+            InvocationTargetException {
+        synchronizer.storeStateAndFree();
+        try {
+            EventQueue.invokeAndWait(runnable);
+        } finally {
+            synchronizer.lockAndRestoreState();
+        }
+    }
+
+    /**
+     * Gets the synchronizer.
+     * 
+     * @return the synchronizer
+     */
+    final Synchronizer getSynchronizer() {
+        return synchronizer;
+    }
+
+    /**
+     * Gets the wTK.
+     * 
+     * @return the wTK
+     */
+    final WTK getWTK() {
+        return wtk;
+    }
+
+    /**
+     * Gets the property with the specified key and default value. 
+     * This method returns the defValue if the property is not found. 
+     * 
+     * @param propName the name of property.
+     * @param defVal the default value.
+     * 
+     * @return the property value.
+     */
+    public static String getProperty(String propName, String defVal) {
+        if (propName == null) {
+            // awt.7D=Property name is null
+            throw new NullPointerException(Messages.getString("awt.7D")); //$NON-NLS-1$
+        }
+        staticLockAWT();
+        try {
+            String retVal = null;
+            if (properties != null) {
+                try {
+                    retVal = properties.getString(propName);
+                } catch (MissingResourceException e) {
+                } catch (ClassCastException e) {
+                }
+            }
+            return (retVal == null) ? defVal : retVal;
+        } finally {
+            staticUnlockAWT();
+        }
+    }
+    
+    /**
+     * Gets the default Toolkit.
+     * 
+     * @return the default Toolkit
+     */
+    public static Toolkit getDefaultToolkit() {
+        synchronized (ContextStorage.getContextLock()) {
+            if (ContextStorage.shutdownPending()) {
+                return null;
+            }
+            Toolkit defToolkit = ContextStorage.getDefaultToolkit();
+            if (defToolkit != null) {
+                return defToolkit;
+            }
+            staticLockAWT();
+            try {
+                defToolkit = GraphicsEnvironment.isHeadless() ?
+                        new HeadlessToolkit() : new ToolkitImpl();
+                ContextStorage.setDefaultToolkit(defToolkit);
+                return defToolkit;
+            } finally {
+                staticUnlockAWT();
+            }
+            //TODO: read system property named awt.toolkit
+            //and create an instance of the specified class,
+            //by default use ToolkitImpl
+        }
+    }
+    
+    /**
+     * Gets the default Font.
+     * 
+     * @return the derault Font for Toolkit.
+     */
+    Font getDefaultFont() {
+        return wtk.getSystemProperties().getDefaultFont();
+    }
+    
+    /**
+     * Load resources.
+     * 
+     * @param path the path
+     * 
+     * @return the resource bundle
+     */
+    private static ResourceBundle loadResources(String path) {
+        try {
+            return ResourceBundle.getBundle(path);
+        } catch (MissingResourceException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Gets the wTK class name.
+     * 
+     * @return the wTK class name
+     */
+    private static String getWTKClassName() {
+        return "com.android.internal.awt.AndroidWTK";
+    }
+
+    /**
+     * Gets the component by id.
+     * 
+     * @param id the id
+     * 
+     * @return the component by id
+     */
+    Component getComponentById(long id) {
+        if (id == 0) {
+            return null;
+        }
+        return null;
+    }
+
+    /**
+     * Gets the GraphicsFactory.
+     * 
+     * @return the GraphicsFactory object.
+     */
+    public GraphicsFactory getGraphicsFactory() {
+        return wtk.getGraphicsFactory();
+    }
+
+    /**
+     * Instantiates a new toolkit.
+     */
+    public Toolkit() {        
+        init();
+    }
+
+    /**
+     * Inits AWT.
+     */
+    protected void init() {
+        lockAWT();
+        try {
+            ComponentInternals.setComponentInternals(new ComponentInternalsImpl());
+            new EventQueue(this); // create the system EventQueue
+            dispatcher = new Dispatcher(this);
+            final String className = getWTKClassName();
+            desktopProperties = new HashMap<String, Object>();
+            desktopPropsSupport = new PropertyChangeSupport(this);
+            awtEventsManager = new AWTEventsManager();
+            dispatchThread = new EventDispatchThread(this, dispatcher);
+            nativeThread = new NativeEventThread();
+            NativeEventThread.Init init = new NativeEventThread.Init() {
+                public WTK init() {
+                    wtk = createWTK(className);
+                    wtk.getNativeEventQueue().setShutdownWatchdog(shutdownWatchdog);
+                    synchronizer.setEnvironment(wtk, dispatchThread);
+                    ContextStorage.setWTK(wtk);
+                    return wtk;
+                }
+            };
+            nativeThread.start(init);
+            dispatchThread.start();
+            wtk.getNativeEventQueue().awake();
+        } finally {
+            unlockAWT();
+        }
+    }
+    
+    /**
+     * Synchronizes this toolkit's graphics.
+     */
+    public abstract void sync();
+
+    /**
+     * Returns the construction status of a specified image that is being created.
+     * 
+     * @param a0 the image to be checked.
+     * @param a1 the width of scaled image for which the status is being checked, or -1.
+     * @param a2 the height of scaled image for which the status is being checked, or -1.
+     * @param a3 the ImageObserver object to be notified while 
+     * the image is being prepared.
+     * 
+     * @return the ImageObserver flags which give the current state of the image data.
+     */
+    public abstract int checkImage(Image a0, int a1, int a2, ImageObserver a3);
+   
+    /**
+     * Creates the image with the specified ImageProducer.
+     * 
+     * @param a0 the ImageProducer to be used for image creation.
+     * 
+     * @return the image with the specified ImageProducer.
+     */
+    public abstract Image createImage(ImageProducer a0);
+
+    /**
+     * Creates the image from the specified byte array, offset and length.
+     * The byte array should contain data with image format supported by 
+     * Toolkit such as JPEG, GIF, or PNG.  
+     * 
+     * @param a0 the byte array with the image data.
+     * @param a1 the offset of the beggining the image data in the byte array.
+     * @param a2 the length of the image data in the byte array.
+     * 
+     * @return the created Image.
+     */
+    public abstract Image createImage(byte[] a0, int a1, int a2);
+
+    /**
+     * Creates the image using image data from the specified URL.
+     * 
+     * @param a0 the URL for extracting image data.
+     * 
+     * @return the Image.
+     */
+    public abstract Image createImage(URL a0);
+
+    /**
+     * Creates the image using image data from the specified file.
+     * 
+     * @param a0 the file name which contains image data of supported format.
+     * 
+     * @return the Image.
+     */
+    public abstract Image createImage(String a0);
+
+    /**
+     * Gets the color model.
+     * 
+     * @return the ColorModel of Toolkit's screen.
+     * 
+     * @throws HeadlessException if the 
+     * GraphicsEnvironment.isHeadless() method returns true.
+     */
+    public abstract ColorModel getColorModel() throws HeadlessException;
+    
+    /**
+     * Gets the screen device metrics for the specified font.
+     * 
+     * @param font the Font.
+     * 
+     * @return the FontMetrics for the specified Font.
+     * 
+     * @deprecated Use getLineMetrics method from Font class.
+     */
+        
+    @Deprecated
+    public abstract FontMetrics getFontMetrics(Font font);
+
+    /**
+     * Prepares the specified image for rendering on the screen with the
+     * specified size.
+     * 
+     * @param a0 the Image to be prepared.
+     * @param a1 the width of the screen representation or -1 for the current screen.
+     * @param a2 the height of the screen representation or -1 for the current screen.
+     * @param a3 the ImageObserver object to be notified as soon as 
+     * the image is prepared.
+     * 
+     * @return true, if image is fully prepared; false otherwise.
+     */
+    public abstract boolean prepareImage(Image a0, int a1, int a2, ImageObserver a3);
+
+    /**
+     * Creates an audio beep.
+     */
+    public abstract void beep();
+
+    /**
+     * Returns the array of font names which are available in this Toolkit.
+     * 
+     * @return the array of font names which are available in this Toolkit.
+     * 
+     * @deprecated use GraphicsEnvironment.getAvailableFontFamilyNames() method.
+     */
+    @Deprecated
+    public abstract String[] getFontList();
+    
+    /**
+     * Gets the the Font implementation using the specified peer 
+     * interface.
+     * 
+     * @param a0 the Font name to be implemented.
+     * @param a1 the the font style: PLAIN, BOLD, ITALIC.
+     * 
+     * @return the FontPeer implementation of the specified Font.
+     * 
+     * @deprecated use java.awt.GraphicsEnvironment.getAllFonts method.
+     */
+
+    @Deprecated
+    protected abstract FontPeer getFontPeer(String a0, int a1);
+
+    /**
+     * Gets the image from the specified file which contains image data in
+     * a supported image format (such as JPEG, GIF, or PNG); this method 
+     * should return the same Image for multiple calls of this method with 
+     * the same image file name.
+     * 
+     * @param a0 the file name which contains image data in
+     * a supported image format (such as JPEG, GIF, or PNG).
+     * 
+     * @return the Image.
+     */
+    public abstract Image getImage(String a0);
+
+    /**
+     * Gets the image from the specified URL which contains image data in
+     * a supported image format (such as JPEG, GIF, or PNG); this method 
+     * should return the same Image for multiple calls of this method with 
+     * the same image URL.
+     * 
+     * @param a0 the URL which contains image data in
+     * a supported image format (such as JPEG, GIF, or PNG).
+     * 
+     * @return the Image.
+     */
+    public abstract Image getImage(URL a0);
+
+    /**
+     * Gets the screen resolution.
+     * 
+     * @return the screen resolution.
+     * 
+     * @throws HeadlessException if the GraphicsEnvironment.isHeadless()
+     * method returns true.
+     */
+    public abstract int getScreenResolution() throws HeadlessException;
+
+    /**
+     * Gets the screen size.
+     * 
+     * @return a Dimension object containing the width and height of
+     * the screen.
+     * 
+     * @throws HeadlessException if the GraphicsEnvironment.isHeadless()
+     * method returns true.
+     */
+    public abstract Dimension getScreenSize() throws HeadlessException;
+
+    /**
+     * Gets the EventQueue instance without checking access.
+     * 
+     * @return the system EventQueue.
+     */
+    protected abstract EventQueue getSystemEventQueueImpl();
+
+    /**
+     * Returns a map of text attributes for the abstract level description 
+     * of the specified input method highlight, or null if no mapping is found. 
+     *  
+     * @param highlight the InputMethodHighlight.
+     * 
+     * @return the Map<java.awt.font. text attribute,?>
+     * 
+     * @throws HeadlessException if the GraphicsEnvironment.isHeadless()
+     * method returns true.
+     */
+    public abstract Map<java.awt.font.TextAttribute, ?> mapInputMethodHighlight(
+            InputMethodHighlight highlight) throws HeadlessException;
+
+    /**
+     * Map input method highlight impl.
+     * 
+     * @param highlight the highlight
+     * 
+     * @return the map<java.awt.font. text attribute,?>
+     * 
+     * @throws HeadlessException the headless exception
+     */
+    Map<java.awt.font.TextAttribute, ?> mapInputMethodHighlightImpl(
+            InputMethodHighlight highlight) throws HeadlessException {
+        HashMap<java.awt.font.TextAttribute, ?> map = new HashMap<java.awt.font.TextAttribute, Object>();
+        wtk.getSystemProperties().mapInputMethodHighlight(highlight, map);
+        return Collections.<java.awt.font.TextAttribute, Object> unmodifiableMap(map);
+    }
+
+    /**
+     * Adds the specified PropertyChangeListener listener for the specified
+     * property.
+     * 
+     * @param propName the property name for which the specified PropertyChangeListener
+     * will be added. 
+     * @param l the PropertyChangeListener object.
+     */
+    public void addPropertyChangeListener(String propName, PropertyChangeListener l) {
+        lockAWT();
+        try {
+            if (desktopProperties.isEmpty()) {
+                initializeDesktopProperties();
+            }
+        } finally {
+            unlockAWT();
+        }
+        if (l != null) { // there is no guarantee that null listener will not be added
+            desktopPropsSupport.addPropertyChangeListener(propName, l);
+        }
+    }
+
+    /**
+     * Returns an array of the property change listeners registered with
+     * this Toolkit.
+     * 
+     * @return an array of the property change listeners registered with
+     * this Toolkit. 
+     */
+    public PropertyChangeListener[] getPropertyChangeListeners() {
+        return desktopPropsSupport.getPropertyChangeListeners();
+    }
+
+    /**
+     * Returns an array of the property change listeners registered with
+     * this Toolkit for notification regarding the specified property.
+     * 
+     * @param propName the property name for which the PropertyChangeListener
+     * was registered.
+     * 
+     * @return the array of PropertyChangeListeners registered for the specified 
+     * property name.
+     */
+    public PropertyChangeListener[] getPropertyChangeListeners(String propName) {
+        return desktopPropsSupport.getPropertyChangeListeners(propName);
+    }
+
+    /**
+     * Removes the specified property change listener registered for the
+     * specified property name.
+     * 
+     * @param propName the property name.
+     * @param l the PropertyChangeListener registered for the specified property name.
+     */
+    public void removePropertyChangeListener(String propName, PropertyChangeListener l) {
+        desktopPropsSupport.removePropertyChangeListener(propName, l);
+    }
+    
+    /**
+     * Creates a custom cursor with the specified Image, hot spot, and cursor
+     * description.
+     * 
+     * @param img the image of activated cursor.
+     * @param hotSpot the Point giving the coordinates of the cursor's hot spot. 
+     * @param name the cursor description.
+     * 
+     * @return the cursor with the specified Image, hot spot, and cursor
+     * description.
+     * 
+     * @throws IndexOutOfBoundsException if the hot spot values are outside  
+     * the bounds of the cursor.
+     * @throws HeadlessException if isHeadless() method of GraphicsEnvironment
+     * class returns true.
+     */
+    public Cursor createCustomCursor(Image img, Point hotSpot, String name)
+            throws IndexOutOfBoundsException, HeadlessException {
+        lockAWT();
+        try {
+            int w = img.getWidth(null), x = hotSpot.x;
+            int h = img.getHeight(null), y = hotSpot.y;
+            if (x < 0 || x >= w || y < 0 || y >= h) {
+                // awt.7E=invalid hotSpot
+                throw new IndexOutOfBoundsException(Messages.getString("awt.7E")); //$NON-NLS-1$
+            }
+            return new Cursor(name, img, hotSpot);
+        } finally {
+            unlockAWT();
+        }
+    }
+
+    /**
+     * Returns the supported cursor dimension which is closest to the 
+     * specified width and height. If the Toolkit only supports a single 
+     * cursor size, this method should return the supported cursor size.
+     * If custom cursor is not supported, a dimension of 0, 0 should be
+     * returned.
+     * 
+     * @param prefWidth the preffered cursor width.
+     * @param prefHeight the preffered cursor height.
+     * 
+     * @return the supported cursor dimension which is closest to the 
+     * specified width and height.
+     * 
+     * @throws HeadlessException if GraphicsEnvironment.isHeadless() 
+     * returns true.
+     */
+    public Dimension getBestCursorSize(int prefWidth, int prefHeight) throws HeadlessException {
+        lockAWT();
+        try {
+            return wtk.getCursorFactory().getBestCursorSize(prefWidth, prefHeight);
+        } finally {
+            unlockAWT();
+        }
+    }
+
+    /**
+     * Gets the value for the specified desktop property. 
+     * 
+     * @param propName the property name.
+     * 
+     * @return the Object that is the property's value.
+     */
+    public final Object getDesktopProperty(String propName) {
+        lockAWT();
+        try {
+            if (desktopProperties.isEmpty()) {
+                initializeDesktopProperties();
+            }
+            if (propName.equals("awt.dynamicLayoutSupported")) { //$NON-NLS-1$
+                // dynamicLayoutSupported is special case
+                return Boolean.valueOf(isDynamicLayoutActive());
+            }
+            Object val = desktopProperties.get(propName);
+            if (val == null) {
+                // try to lazily load prop value
+                // just for compatibility, our lazilyLoad is empty
+                val = lazilyLoadDesktopProperty(propName);
+            }
+            return val;
+        } finally {
+            unlockAWT();
+        }
+    }
+
+    /**
+     * Returns the locking key state for the specified key.
+     * 
+     * @param a0 the key code: VK_CAPS_LOCK, VK_NUM_LOCK, VK_SCROLL_LOCK, 
+     * or VK_KANA_LOCK.
+     * 
+     * @return true if the specified key code is in the locked state,
+     * false otherwise.
+     * 
+     * @throws UnsupportedOperationException if the state of this key 
+     * can't be retrieved, or if the keyboard doesn't have this key.
+     * @throws NotImplementedException if this method is not implemented.
+     */
+    public boolean getLockingKeyState(int a0) throws UnsupportedOperationException, org.apache.harmony.luni.util.NotImplementedException {
+        lockAWT();
+        try {
+        } finally {
+            unlockAWT();
+        }
+        if (true) {
+            throw new RuntimeException("Method is not implemented"); //TODO: implement //$NON-NLS-1$
+        }
+        return true;
+    }
+
+    /**
+     * Returns the maximum number of colors which the Toolkit supports for
+     * custom cursor.
+     * 
+     * @return the maximum cursor colors.
+     * 
+     * @throws HeadlessException if the GraphicsEnvironment.isHeadless()
+     * method returns true.
+     */
+    public int getMaximumCursorColors() throws HeadlessException {
+        lockAWT();
+        try {
+            return wtk.getCursorFactory().getMaximumCursorColors();
+        } finally {
+            unlockAWT();
+        }
+    }
+
+    /**
+     * Gets the menu shortcut key mask.
+     *
+     * @return the menu shortcut key mask.
+     * 
+     * @throws HeadlessException if the GraphicsEnvironment.isHeadless()
+     * method returns true.
+     */
+    public int getMenuShortcutKeyMask() throws HeadlessException {
+        lockAWT();
+        try {
+            return InputEvent.CTRL_MASK;
+        } finally {
+            unlockAWT();
+        }
+    }
+
+    /**
+     * Gets the screen insets.
+     * 
+     * @param gc the GraphicsConfiguration.
+     * 
+     * @return the insets of this toolkit.
+     * 
+     * @throws HeadlessException if the GraphicsEnvironment.isHeadless()
+     * method returns true.
+     */
+    public Insets getScreenInsets(GraphicsConfiguration gc) throws HeadlessException {
+        if (gc == null) {
+            throw new NullPointerException();
+        }
+        lockAWT();
+        try {
+            return new Insets(0, 0, 0, 0); //TODO: get real screen insets
+        } finally {
+            unlockAWT();
+        }
+    }
+
+    /**
+     * Gets the system EventQueue instance. 
+     * If the default implementation of checkAwtEventQueueAccess is used,
+     * then this results of a call to the security manager's checkPermission
+     * method with an AWTPermission("accessEventQueue") permission.
+     * 
+     * @return the system EventQueue instance.
+     */
+    public final EventQueue getSystemEventQueue() {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkAwtEventQueueAccess();
+        }
+        return getSystemEventQueueImpl();
+    }
+
+    /** 
+     * Gets the system event queue core.
+     * 
+     * @return the system event queue core
+     */
+    EventQueueCore getSystemEventQueueCore() {
+        return systemEventQueueCore;
+    }
+    
+    /**
+     * Sets the system event queue core.
+     * 
+     * @param core the new system event queue core
+     */
+    void setSystemEventQueueCore(EventQueueCore core) {
+        systemEventQueueCore = core;
+    }
+
+    /**
+     * Initialize the desktop properties.
+     */
+    protected void initializeDesktopProperties() {
+        lockAWT();
+        try {
+            wtk.getSystemProperties().init(desktopProperties);
+        } finally {
+            unlockAWT();
+        }
+    }
+
+    /**
+     * Checks if dynamic layout of Containers is active or not.
+     * 
+     * @return true, if is dynamic layout of Containers is active,
+     * false otherwise.
+     * 
+     * @throws HeadlessException if the GraphicsEnvironment.isHeadless()
+     * method returns true.
+     */
+    public boolean isDynamicLayoutActive() throws HeadlessException {
+        lockAWT();
+        try {
+            // always return true
+            return true;
+        } finally {
+            unlockAWT();
+        }
+    }
+
+
+    /**
+     * Returns if the layout of Containers is checked dynamically during resizing,
+     * or statically after resizing is completed. 
+     * 
+     * @return true, if if the layout of Containers is checked dynamically during 
+     * resizing; false, if the layout of Containers is checked statically after 
+     * resizing is completed. 
+     * 
+     * @throws HeadlessException if the GraphicsEnvironment.isHeadless()
+     * method returns true.
+     */
+    protected boolean isDynamicLayoutSet() throws HeadlessException {
+        lockAWT();
+        try {
+            return bDynamicLayoutSet;
+        } finally {
+            unlockAWT();
+        }
+    }
+
+    /**
+     * Checks if the specified frame state is supported by Toolkit or not.
+     * 
+     * @param state the frame state.
+     * 
+     * @return true, if frame state is supported; false othrwise.
+     * 
+     * @throws HeadlessException if the GraphicsEnvironment.isHeadless()
+     * method returns true.
+     */
+    public boolean isFrameStateSupported(int state) throws HeadlessException {
+        lockAWT();
+        try {
+            return wtk.getWindowFactory().isWindowStateSupported(state);
+        } finally {
+            unlockAWT();
+        }
+    }
+
+    /**
+     * Loads the value of the desktop property with the specified property name.
+     * 
+     * @param propName the property name.
+     * 
+     * @return the desktop property values.
+     */
+    protected Object lazilyLoadDesktopProperty(String propName) {
+        return null;
+    }
+
+    /**
+     * Loads the current system color values to the specified array.
+     * 
+     * @param colors the array where the current system color values 
+     * are written by this method.
+     * 
+     * @throws HeadlessException if the GraphicsEnvironment.isHeadless()
+     * method returns true.
+     */
+    protected void loadSystemColors(int[] colors) throws HeadlessException {
+        lockAWT();
+        try {
+        } finally {
+            unlockAWT();
+        }
+    }
+
+    /**
+     * Sets the value of the desktop property with the specified name.
+     * 
+     * @param propName the property's name.
+     * @param value the property's value.
+     */
+    protected final void setDesktopProperty(String propName, Object value) {
+        Object oldVal;
+        lockAWT();
+        try {
+            oldVal = getDesktopProperty(propName);
+            userPropSet.add(propName);
+            desktopProperties.put(propName, value);
+        } finally {
+            unlockAWT();
+        }
+        desktopPropsSupport.firePropertyChange(propName, oldVal, value);
+    }
+
+    /**
+     * Sets the layout state, whether the Container layout is checked 
+     * dynamically during resizing, or statically after resizing is completed. 
+     * 
+     * @param dynamic the new dynamic layout state - if true the layout of 
+     * Containers is checked dynamically during resizing, if false -
+     * statically after resizing is completed.
+     * 
+     * @throws HeadlessException if the GraphicsEnvironment.isHeadless()
+     * method returns true.
+     */
+    public void setDynamicLayout(boolean dynamic) throws HeadlessException {
+        lockAWT();
+        try {
+            bDynamicLayoutSet = dynamic;
+        } finally {
+            unlockAWT();
+        }
+    }
+
+    /**
+     * Sets the locking key state for the specified key code.
+     * 
+     * @param a0 the key code: VK_CAPS_LOCK, VK_NUM_LOCK, VK_SCROLL_LOCK, 
+     * or VK_KANA_LOCK.
+     * @param a1 the state - true to set the specified key code to the locked state,
+     * false - to unlock it.
+     * 
+     * @throws UnsupportedOperationException if the state of this key 
+     * can't be set, or if the keyboard doesn't have this key.
+     * @throws NotImplementedException if this method is not implemented.
+     */
+    public void setLockingKeyState(int a0, boolean a1) throws UnsupportedOperationException, org.apache.harmony.luni.util.NotImplementedException {
+        lockAWT();
+        try {
+        } finally {
+            unlockAWT();
+        }
+        if (true) {
+            throw new RuntimeException("Method is not implemented"); //TODO: implement //$NON-NLS-1$
+        }
+        return;
+    }
+
+
+    /**
+     * On queue empty.
+     */
+    void onQueueEmpty() {
+        throw new RuntimeException("Not implemented!");
+    }
+
+    /**
+     * Creates the wtk.
+     * 
+     * @param clsName the cls name
+     * 
+     * @return the wTK
+     */
+    private WTK createWTK(String clsName) {
+        WTK newWTK = null;
+        try {
+            newWTK = (WTK) Class.forName(clsName).newInstance();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+        return newWTK;
+    }
+
+    /**
+     * Connect the component to its native window
+     * @param winId - id of native window just created
+     */
+    boolean onWindowCreated(long winId) {
+        return false;
+    }
+
+    /**
+     * Gets the native event queue.
+     * 
+     * @return the native event queue
+     */
+    NativeEventQueue getNativeEventQueue() {
+        return wtk.getNativeEventQueue();
+    }
+
+    /**
+     * Returns a shared instance of implementation of org.apache.harmony.awt.wtk.NativeCursor
+     * for current platform for
+     * 
+     * @param type - Java Cursor type
+     * 
+     * @return new instance of implementation of NativeCursor
+     */
+    NativeCursor createNativeCursor(int type) {
+        return wtk.getCursorFactory().getCursor(type);
+    }
+
+    /**
+     * Returns a shared instance of implementation of org.apache.harmony.awt.wtk.NativeCursor
+     * for current platform for custom cursor
+     * 
+     * @param img the img
+     * @param hotSpot the hot spot
+     * @param name the name
+     * 
+     * @return new instance of implementation of NativeCursor
+     */
+    NativeCursor createCustomNativeCursor(Image img, Point hotSpot, String name) {
+        return wtk.getCursorFactory().createCustomCursor(img, hotSpot.x, hotSpot.y);
+    }
+
+    /**
+     * Adds an AWTEventListener to the Toolkit to listen for events
+     * of types corresponding to bits in the specified event mask. 
+     * Event masks are defined in AWTEvent class.
+     * 
+     * @param listener the AWTEventListener.
+     * @param eventMask he bitmask of event types.
+     */
+    public void addAWTEventListener(AWTEventListener listener, long eventMask) {
+        lockAWT();
+        try {
+            SecurityManager security = System.getSecurityManager();
+            if (security != null) {
+                security.checkPermission(awtEventsManager.permission);
+            }
+            awtEventsManager.addAWTEventListener(listener, eventMask);
+        } finally {
+            unlockAWT();
+        }
+    }
+
+    /**
+     * Removes the specified awt event listener.
+     * 
+     * @param listener the AWTEventListener to be removed.
+     */
+    public void removeAWTEventListener(AWTEventListener listener) {
+        lockAWT();
+        try {
+            SecurityManager security = System.getSecurityManager();
+            if (security != null) {
+                security.checkPermission(awtEventsManager.permission);
+            }
+            awtEventsManager.removeAWTEventListener(listener);
+        } finally {
+            unlockAWT();
+        }
+    }
+
+    /**
+     * Gets the array of all AWT event listeners registered with this Toolkit.
+     * 
+     * @return the array of all AWT event listeners registered with this Toolkit.
+     */
+    public AWTEventListener[] getAWTEventListeners() {
+        lockAWT();
+        try {
+            SecurityManager security = System.getSecurityManager();
+            if (security != null) {
+                security.checkPermission(awtEventsManager.permission);
+            }
+            return awtEventsManager.getAWTEventListeners();
+        } finally {
+            unlockAWT();
+        }
+    }
+
+    /**
+     * Returns the array of the AWT event listeners registered with this Toolkit 
+     * for the event types corresponding to the specified event mask.
+     * 
+     * @param eventMask the bit mask of event type.
+     * 
+     * @return the array of the AWT event listeners registered in this Toolkit 
+     * for the event types corresponding to the specified event mask.
+     */
+    public AWTEventListener[] getAWTEventListeners(long eventMask) {
+        lockAWT();
+        try {
+            SecurityManager security = System.getSecurityManager();
+            if (security != null) {
+                security.checkPermission(awtEventsManager.permission);
+            }
+            return awtEventsManager.getAWTEventListeners(eventMask);
+        } finally {
+            unlockAWT();
+        }
+    }
+
+    /**
+     * Dispatch awt event.
+     * 
+     * @param event the event
+     */
+    void dispatchAWTEvent(AWTEvent event) {
+        awtEventsManager.dispatchAWTEvent(event);
+    }
+    
+    /**
+     * The Class AWTEventsManager.
+     */
+    final class AWTEventsManager {
+
+        /** The permission. */
+        AWTPermission permission = new AWTPermission("listenToAllAWTEvents"); //$NON-NLS-1$
+
+        /** The listeners. */
+        private final AWTListenerList<AWTEventListenerProxy> listeners = new AWTListenerList<AWTEventListenerProxy>();
+
+        /**
+         * Adds the awt event listener.
+         * 
+         * @param listener the listener
+         * @param eventMask the event mask
+         */
+        void addAWTEventListener(AWTEventListener listener, long eventMask) {
+            if (listener != null) {
+                listeners.addUserListener(new AWTEventListenerProxy(eventMask, listener));
+            }
+        }
+
+        /**
+         * Removes the awt event listener.
+         * 
+         * @param listener the listener
+         */
+        void removeAWTEventListener(AWTEventListener listener) {
+            if (listener != null) {
+                for (AWTEventListenerProxy proxy : listeners.getUserListeners()) {
+                    if (listener == proxy.getListener()) {
+                        listeners.removeUserListener(proxy);
+                        return;
+                    }
+                }
+            }
+        }
+
+        /**
+         * Gets the aWT event listeners.
+         * 
+         * @return the aWT event listeners
+         */
+        AWTEventListener[] getAWTEventListeners() {
+            HashSet<EventListener> listenersSet = new HashSet<EventListener>();
+            for (AWTEventListenerProxy proxy : listeners.getUserListeners()) {
+                listenersSet.add(proxy.getListener());
+            }
+            return listenersSet.toArray(new AWTEventListener[listenersSet.size()]);
+        }
+
+        /**
+         * Gets the aWT event listeners.
+         * 
+         * @param eventMask the event mask
+         * 
+         * @return the aWT event listeners
+         */
+        AWTEventListener[] getAWTEventListeners(long eventMask) {
+            HashSet<EventListener> listenersSet = new HashSet<EventListener>();
+            for (AWTEventListenerProxy proxy : listeners.getUserListeners()) {
+                if ((proxy.getEventMask() & eventMask) == eventMask) {
+                    listenersSet.add(proxy.getListener());
+                }
+            }
+            return listenersSet.toArray(new AWTEventListener[listenersSet.size()]);
+        }
+
+        /**
+         * Dispatch awt event.
+         * 
+         * @param event the event
+         */
+        void dispatchAWTEvent(AWTEvent event) {
+            AWTEvent.EventDescriptor descriptor = eventTypeLookup.getEventDescriptor(event);
+            if (descriptor == null) {
+                return;
+            }
+            for (AWTEventListenerProxy proxy : listeners.getUserListeners()) {
+                if ((proxy.getEventMask() & descriptor.eventMask) != 0) {
+                    proxy.eventDispatched(event);
+                }
+            }
+        }
+    }
+    
+    /**
+     * The Class AutoNumber.
+     */
+    static final class AutoNumber {
+
+        /** The next component. */
+        int nextComponent = 0;
+
+        /** The next canvas. */
+        int nextCanvas = 0;
+
+        /** The next panel. */
+        int nextPanel = 0;
+
+        /** The next window. */
+        int nextWindow = 0;
+
+        /** The next frame. */
+        int nextFrame = 0;
+
+        /** The next dialog. */
+        int nextDialog = 0;
+
+        /** The next button. */
+        int nextButton = 0;
+
+        /** The next menu component. */
+        int nextMenuComponent = 0;
+
+        /** The next label. */
+        int nextLabel = 0;
+
+        /** The next check box. */
+        int nextCheckBox = 0;
+
+        /** The next scrollbar. */
+        int nextScrollbar = 0;
+
+        /** The next scroll pane. */
+        int nextScrollPane = 0;
+
+        /** The next list. */
+        int nextList = 0;
+
+        /** The next choice. */
+        int nextChoice = 0;
+
+        /** The next file dialog. */
+        int nextFileDialog = 0;
+
+        /** The next text area. */
+        int nextTextArea = 0;
+
+        /** The next text field. */
+        int nextTextField = 0;
+    }
+    
+    private class Lock {
+    }
+
+        /** The lock. */
+    private final Object lock = new Lock();
+        
+}
diff --git a/awt/java/awt/ToolkitImpl.java b/awt/java/awt/ToolkitImpl.java
new file mode 100644
index 0000000..5015aef
--- /dev/null
+++ b/awt/java/awt/ToolkitImpl.java
@@ -0,0 +1,255 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package java.awt;
+
+import java.awt.im.InputMethodHighlight;
+import java.awt.image.ColorModel;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.awt.peer.*;
+import java.io.Serializable;
+import java.net.URL;
+import java.util.Hashtable;
+import java.util.Map;
+import org.apache.harmony.awt.gl.image.*;
+import org.apache.harmony.awt.wtk.GraphicsFactory;
+
+class ToolkitImpl extends Toolkit {
+	
+    static final Hashtable<Serializable, Image> imageCache = new Hashtable<Serializable, Image>();
+
+    @Override
+    public void sync() {
+        lockAWT();
+        try {
+        } finally {
+            unlockAWT();
+        }
+    }
+
+    @Override
+    public int checkImage(Image image, int width, int height, ImageObserver observer) {
+        lockAWT();
+        try {
+            if (width == 0 || height == 0) {
+                return ImageObserver.ALLBITS;
+            }
+            if (!(image instanceof OffscreenImage)) {
+                return ImageObserver.ALLBITS;
+            }
+            OffscreenImage oi = (OffscreenImage) image;
+            return oi.checkImage(observer);
+        } finally {
+            unlockAWT();
+        }
+    }
+
+    @Override
+    public Image createImage(ImageProducer producer) {
+        lockAWT();
+        try {
+            return new OffscreenImage(producer);
+        } finally {
+            unlockAWT();
+        }
+    }
+
+    @Override
+    public Image createImage(byte[] imagedata, int imageoffset, int imagelength) {
+        lockAWT();
+        try {
+            return new OffscreenImage(new ByteArrayDecodingImageSource(imagedata, imageoffset,
+                    imagelength));
+        } finally {
+            unlockAWT();
+        }
+    }
+
+    @Override
+    public Image createImage(URL url) {
+        lockAWT();
+        try {
+            return new OffscreenImage(new URLDecodingImageSource(url));
+        } finally {
+            unlockAWT();
+        }
+    }
+
+    @Override
+    public Image createImage(String filename) {
+        lockAWT();
+        try {
+            return new OffscreenImage(new FileDecodingImageSource(filename));
+        } finally {
+            unlockAWT();
+        }
+    }
+
+    @Override
+    public ColorModel getColorModel() {
+        lockAWT();
+        try {
+            return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice()
+                    .getDefaultConfiguration().getColorModel();
+        } finally {
+            unlockAWT();
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    @Deprecated
+    public FontMetrics getFontMetrics(Font font) {
+        lockAWT();
+        try {
+        	GraphicsFactory gf = getGraphicsFactory();
+            return gf.getFontMetrics(font);
+        } finally {
+            unlockAWT();
+        }
+    }
+    
+    @Override
+    public boolean prepareImage(Image image, int width, int height, ImageObserver observer) {
+        lockAWT();
+        try {
+            if (width == 0 || height == 0) {
+                return true;
+            }
+            if (!(image instanceof OffscreenImage)) {
+                return true;
+            }
+            OffscreenImage oi = (OffscreenImage) image;
+            return oi.prepareImage(observer);
+        } finally {
+            unlockAWT();
+        }
+    }
+
+    @Override
+    public void beep() {
+        lockAWT();
+        try {
+        	// ???AWT: is there nothing to be implemented here?
+        } finally {
+            unlockAWT();
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    @Deprecated
+    public String[] getFontList() {
+        lockAWT();
+        try {
+        } finally {
+            unlockAWT();
+        }
+        return null;
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    @Deprecated
+    protected FontPeer getFontPeer(String a0, int a1) {
+        lockAWT();
+        try {
+            return null;
+        } finally {
+            unlockAWT();
+        }
+    }
+
+    @Override
+    public Image getImage(String filename) {
+        return getImage(filename, this);
+    }
+
+    static Image getImage(String filename, Toolkit toolkit) {
+        synchronized (imageCache) {
+            Image im = (filename == null ? null : imageCache.get(filename));
+
+            if (im == null) {
+                try {
+                    im = toolkit.createImage(filename);
+                    imageCache.put(filename, im);
+                } catch (Exception e) {
+                }
+            }
+
+            return im;
+        }
+    }
+
+    @Override
+    public Image getImage(URL url) {
+        return getImage(url, this);
+    }
+
+    static Image getImage(URL url, Toolkit toolkit) {
+        synchronized (imageCache) {
+            Image im = imageCache.get(url);
+            if (im == null) {
+                try {
+                    im = toolkit.createImage(url);
+                    imageCache.put(url, im);
+                } catch (Exception e) {
+                }
+            }
+            return im;
+        }
+    }
+
+    @Override
+    public int getScreenResolution() throws HeadlessException {
+        lockAWT();
+        try {
+        	return 62;
+        } finally {
+            unlockAWT();
+        }
+    }
+
+    @Override
+    public Dimension getScreenSize() {
+        lockAWT();
+        try {
+            DisplayMode dm = GraphicsEnvironment.getLocalGraphicsEnvironment()
+                    .getDefaultScreenDevice().getDisplayMode();
+            return new Dimension(dm.getWidth(), dm.getHeight());
+        } finally {
+            unlockAWT();
+        }
+    }
+
+    @Override
+    public Map<java.awt.font.TextAttribute, ?> mapInputMethodHighlight(
+            InputMethodHighlight highlight) throws HeadlessException {
+        lockAWT();
+        try {
+            return mapInputMethodHighlightImpl(highlight);
+        } finally {
+            unlockAWT();
+        }
+    }
+
+    @Override
+    protected EventQueue getSystemEventQueueImpl() {
+        return getSystemEventQueueCore().getActiveEventQueue();
+    }
+}
diff --git a/awt/java/awt/Transparency.java b/awt/java/awt/Transparency.java
new file mode 100644
index 0000000..9793114
--- /dev/null
+++ b/awt/java/awt/Transparency.java
@@ -0,0 +1,51 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt;
+
+/**
+ * The Transparency interface defines transparency's general modes.
+ */
+public interface Transparency {
+
+    /** The Constant OPAQUE represents completely opaque data,
+     * all pixels have an alpha value of 1.0. 
+     */
+    public static final int OPAQUE = 1;
+
+    /** The Constant BITMASK represents data which can be either 
+     * completely opaque, with an alpha value of 1.0, or completely 
+     * transparent, with an alpha value of 0.0.
+     */
+    public static final int BITMASK = 2;
+
+    /** The Constant TRANSLUCENT represents data which alpha value
+     * can vary between and including 0.0 and 1.0. */
+    public static final int TRANSLUCENT = 3;
+
+    /**
+     * Gets the transparency mode.
+     * 
+     * @return the transparency mode: OPAQUE, BITMASK or TRANSLUCENT.  
+     */
+    public int getTransparency();
+
+}
+
diff --git a/awt/java/awt/color/CMMException.java b/awt/java/awt/color/CMMException.java
new file mode 100644
index 0000000..16fe76e
--- /dev/null
+++ b/awt/java/awt/color/CMMException.java
@@ -0,0 +1,40 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ */
+package java.awt.color;
+
+/**
+ * The CMMException is thrown as soon as a native CMM error
+ * occures.
+ */
+public class CMMException extends java.lang.RuntimeException {
+    
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = 5775558044142994965L;
+
+    /**
+     * Instantiates a new CMM exception with detail message.
+     * 
+     * @param s the String - detail message.
+     */
+    public CMMException (String s) {
+        super (s);
+    }
+}
diff --git a/awt/java/awt/color/ColorSpace.java b/awt/java/awt/color/ColorSpace.java
new file mode 100644
index 0000000..f961514
--- /dev/null
+++ b/awt/java/awt/color/ColorSpace.java
@@ -0,0 +1,340 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ */
+package java.awt.color;
+
+import java.io.Serializable;
+
+import org.apache.harmony.awt.gl.color.LUTColorConverter;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The ColorSpace class defines a color space type for a Color and provides methods
+ * for arrays of color component operations.
+ */
+public abstract class ColorSpace implements Serializable {
+
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = -409452704308689724L;
+
+    /** The Constant TYPE_XYZ indicates XYZ color space type. */
+    public static final int TYPE_XYZ = 0;
+
+    /** The Constant TYPE_Lab indicates Lab color space type. */
+    public static final int TYPE_Lab = 1;
+
+    /** The Constant TYPE_Luv indicates Luv color space type. */
+    public static final int TYPE_Luv = 2;
+
+    /** The Constant TYPE_YCbCr indicates YCbCr color space type. */
+    public static final int TYPE_YCbCr = 3;
+
+    /** The Constant TYPE_Yxy indicates Yxy color space type. */
+    public static final int TYPE_Yxy = 4;
+
+    /** The Constant TYPE_RGB indicates RGB color space type. */
+    public static final int TYPE_RGB = 5;
+
+    /** The Constant TYPE_GRAY indicates Gray color space type. */
+    public static final int TYPE_GRAY = 6;
+
+    /** The Constant TYPE_HSV indicates HSV color space type. */
+    public static final int TYPE_HSV = 7;
+
+    /** The Constant TYPE_HLS indicates HLS color space type. */
+    public static final int TYPE_HLS = 8;
+
+    /** The Constant TYPE_CMYK indicates CMYK color space type. */
+    public static final int TYPE_CMYK = 9;
+
+    /** The Constant TYPE_CMY indicates CMY color space type. */
+    public static final int TYPE_CMY = 11;
+
+    /** The Constant TYPE_2CLR indicates color spaces with 2 components. */
+    public static final int TYPE_2CLR = 12;
+
+    /** The Constant TYPE_3CLR indicates color spaces with 3 components. */
+    public static final int TYPE_3CLR = 13;
+
+    /** The Constant TYPE_4CLR indicates color spaces with 4 components. */
+    public static final int TYPE_4CLR = 14;
+
+    /** The Constant TYPE_5CLR indicates color spaces with 5 components. */
+    public static final int TYPE_5CLR = 15;
+
+    /** The Constant TYPE_6CLR indicates color spaces with 6 components. */
+    public static final int TYPE_6CLR = 16;
+
+    /** The Constant TYPE_7CLR indicates color spaces with 7 components. */
+    public static final int TYPE_7CLR = 17;
+
+    /** The Constant TYPE_8CLR indicates color spaces with 8 components. */
+    public static final int TYPE_8CLR = 18;
+
+    /** The Constant TYPE_9CLR indicates color spaces with 9 components. */
+    public static final int TYPE_9CLR = 19;
+
+    /** The Constant TYPE_ACLR indicates color spaces with 10 components. */
+    public static final int TYPE_ACLR = 20;
+
+    /** The Constant TYPE_BCLR indicates color spaces with 11 components. */
+    public static final int TYPE_BCLR = 21;
+
+    /** The Constant TYPE_CCLR indicates color spaces with 12 components. */
+    public static final int TYPE_CCLR = 22;
+
+    /** The Constant TYPE_DCLR indicates color spaces with 13 components. */
+    public static final int TYPE_DCLR = 23;
+
+    /** The Constant TYPE_ECLR indicates color spaces with 14 components. */
+    public static final int TYPE_ECLR = 24;
+
+    /** The Constant TYPE_FCLR indicates color spaces with 15 components. */
+    public static final int TYPE_FCLR = 25;
+
+    /** The Constant CS_sRGB indicates standard RGB color space.*/
+    public static final int CS_sRGB = 1000;
+
+    /** The Constant CS_LINEAR_RGB indicates linear RGB color space. */
+    public static final int CS_LINEAR_RGB = 1004;
+
+    /** The Constant CS_CIEXYZ indicates CIEXYZ conversion color space. */
+    public static final int CS_CIEXYZ = 1001;
+
+    /** The Constant CS_PYCC indicates Photo YCC conversion color space. */
+    public static final int CS_PYCC = 1002;
+
+    /** The Constant CS_GRAY indicates linear gray scale color space. */
+    public static final int CS_GRAY = 1003;
+
+    /** The cs_ gray. */
+    private static ColorSpace cs_Gray = null;
+    
+    /** The cs_ pycc. */
+    private static ColorSpace cs_PYCC = null;
+    
+    /** The cs_ ciexyz. */
+    private static ColorSpace cs_CIEXYZ = null;
+    
+    /** The cs_ lrgb. */
+    private static ColorSpace cs_LRGB = null;
+    
+    /** The cs_s rgb. */
+    private static ColorSpace cs_sRGB = null;
+
+    /** The type. */
+    private int type;
+    
+    /** The num components. */
+    private int numComponents;
+
+    /**
+     * Instantiates a ColorSpace with the specified
+     * ColorSpace type and number of components.
+     * 
+     * @param type the type of color space.
+     * @param numcomponents the number of components.
+     */
+    protected ColorSpace(int type, int numcomponents) {
+        this.numComponents = numcomponents;
+        this.type = type;
+    }
+
+    /**
+     * Gets the name of the component for the specified component index.
+     * 
+     * @param idx the index of the component.
+     * 
+     * @return the name of the component.
+     */
+    public String getName(int idx) {
+        if (idx < 0 || idx > numComponents - 1) {
+            // awt.16A=Invalid component index: {0}
+            throw new IllegalArgumentException(Messages.getString("awt.16A", idx)); //$NON-NLS-1$
+        }
+
+      return "Unnamed color component #" + idx; //$NON-NLS-1$
+    }
+
+    /**
+     * Perform transformation a color from this ColorSpace 
+     * into the RGB color space.
+     * 
+     * @param colorvalue the color value in this ColorSpace.
+     * 
+     * @return the float array with color components in the 
+     * RGB color space.
+     */
+    public abstract float[] toRGB(float[] colorvalue);
+
+    /**
+     * Perform transformation a color from this ColorSpace 
+     * into the CS_CIEXYZ color space.
+     * 
+     * @param colorvalue the color value in this ColorSpace.
+     * 
+     * @return the float array with color components in the 
+     * CS_CIEXYZ color space. 
+     */
+    public abstract float[] toCIEXYZ(float[] colorvalue);
+
+    /**
+     * Performs color transformation from the RGB color space 
+     * into this ColorSpace.
+     * 
+     * @param rgbvalue a float array in the RGB color space.
+     * 
+     * @return the float[] an array of transformed color
+     * components. 
+     */
+    public abstract float[] fromRGB(float[] rgbvalue);
+
+    /**
+     * Performs color transformation from the CS_CIEXYZ color space 
+     * into this ColorSpace.
+     * 
+     * @param colorvalue a float array in the CS_CIEXYZ color space.
+     * 
+     * @return the float[] an array of transformed color
+     * components. 
+     */
+    public abstract float[] fromCIEXYZ(float[] colorvalue);
+
+    /**
+     * Gets the minimum normalized color component value for 
+     * the specified component.
+     * 
+     * @param component the component.
+     * 
+     * @return the miniimum normalized value of the component.
+     */
+    public float getMinValue(int component) {
+        if (component < 0 || component > numComponents - 1) {
+            // awt.16A=Invalid component index: {0}
+            throw new IllegalArgumentException(Messages.getString("awt.16A", component)); //$NON-NLS-1$
+        }
+        return 0;
+    }
+
+    /**
+     * Gets the maximum normalized color component value for 
+     * the specified component.
+     * 
+     * @param component the component.
+     * 
+     * @return the maximum normalized value of the component.
+     */
+    public float getMaxValue(int component) {
+        if (component < 0 || component > numComponents - 1) {
+            // awt.16A=Invalid component index: {0}
+            throw new IllegalArgumentException(Messages.getString("awt.16A", component)); //$NON-NLS-1$
+        }
+        return 1;
+    }
+
+    /**
+     * Checks if this ColorSpace has CS_sRGB type or not.
+     * 
+     * @return true, if this ColorSpace has CS_sRGB type, 
+     * false otherwise.
+     */
+    public boolean isCS_sRGB() {
+        // If our color space is sRGB, then cs_sRGB
+        // is already initialized
+        return (this == cs_sRGB);
+    }
+
+    /**
+     * Gets the type of the ColorSpace.
+     * 
+     * @return the type of the ColorSpace.
+     */
+    public int getType() {
+        return type;
+    }
+
+    /**
+     * Gets the number of components for this ColorSpace.
+     * 
+     * @return the number of components.
+     */
+    public int getNumComponents() {
+        return numComponents;
+    }
+
+
+    /**
+     * Gets the single instance of ColorSpace with the specified
+     * ColorSpace: CS_sRGB, CS_LINEAR_RGB, CS_CIEXYZ, CS_GRAY, 
+     * or CS_PYCC.
+     * 
+     * @param colorspace the identifier of the specified Colorspace.
+     * 
+     * @return the single instance of the desired ColorSpace.
+     */
+    public static ColorSpace getInstance(int colorspace) {
+        switch (colorspace) {
+            case CS_sRGB:
+                if (cs_sRGB == null) {
+                    cs_sRGB = new ICC_ColorSpace(
+                            new ICC_ProfileStub(CS_sRGB));
+                    LUTColorConverter.sRGB_CS = cs_sRGB;
+                            //ICC_Profile.getInstance (CS_sRGB));
+                }
+                return cs_sRGB;
+            case CS_CIEXYZ:
+                if (cs_CIEXYZ == null) {
+                    cs_CIEXYZ = new ICC_ColorSpace(
+                            new ICC_ProfileStub(CS_CIEXYZ));
+                            //ICC_Profile.getInstance (CS_CIEXYZ));
+                }
+                return cs_CIEXYZ;
+            case CS_GRAY:
+                if (cs_Gray == null) {
+                    cs_Gray = new ICC_ColorSpace(
+                            new ICC_ProfileStub(CS_GRAY));
+                    LUTColorConverter.LINEAR_GRAY_CS = cs_Gray;
+                            //ICC_Profile.getInstance (CS_GRAY));
+                }
+                return cs_Gray;
+            case CS_PYCC:
+                if (cs_PYCC == null) {
+                    cs_PYCC = new ICC_ColorSpace(
+                            new ICC_ProfileStub(CS_PYCC));
+                            //ICC_Profile.getInstance (CS_PYCC));
+                }
+                return cs_PYCC;
+            case CS_LINEAR_RGB:
+                if (cs_LRGB == null) {
+                    cs_LRGB = new ICC_ColorSpace(
+                            new ICC_ProfileStub(CS_LINEAR_RGB));
+                    LUTColorConverter.LINEAR_GRAY_CS = cs_Gray;
+                            //ICC_Profile.getInstance (CS_LINEAR_RGB));
+                }
+                return cs_LRGB;
+            default:
+        }
+
+        // Unknown argument passed
+        // awt.16B=Not a predefined colorspace
+        throw new IllegalArgumentException(Messages.getString("Not a predefined colorspace")); //$NON-NLS-1$
+    }
+
+}
\ No newline at end of file
diff --git a/awt/java/awt/color/ICC_ColorSpace.java b/awt/java/awt/color/ICC_ColorSpace.java
new file mode 100644
index 0000000..5ece2ef
--- /dev/null
+++ b/awt/java/awt/color/ICC_ColorSpace.java
@@ -0,0 +1,379 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ */
+package java.awt.color;
+
+import org.apache.harmony.awt.gl.color.ColorConverter;
+import org.apache.harmony.awt.gl.color.ColorScaler;
+import org.apache.harmony.awt.gl.color.ICC_Transform;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+import java.io.*;
+
+/**
+ * ICC_ColorSpace class implements ColorSpace abstract class and 
+ * represents device independent and device dependent color spaces.
+ * This color space is based on the International Color Consortium 
+ * Specification (ICC) File Format for Color Profiles: 
+ * <a href="http://www.color.org">http://www.color.org</a>
+ */
+public class ICC_ColorSpace extends ColorSpace {
+    
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = 3455889114070431483L;
+
+    // Need to keep compatibility with serialized form
+    /** The Constant serialPersistentFields. */
+    private static final ObjectStreamField[]
+      serialPersistentFields = {
+        new ObjectStreamField("thisProfile", ICC_Profile.class), //$NON-NLS-1$
+        new ObjectStreamField("minVal", float[].class), //$NON-NLS-1$
+        new ObjectStreamField("maxVal", float[].class), //$NON-NLS-1$
+        new ObjectStreamField("diffMinMax", float[].class), //$NON-NLS-1$
+        new ObjectStreamField("invDiffMinMax", float[].class), //$NON-NLS-1$
+        new ObjectStreamField("needScaleInit", Boolean.TYPE) //$NON-NLS-1$
+    };
+
+
+   /**
+    * According to ICC specification (from http://www.color.org)
+    * "For the CIEXYZ encoding, each component (X, Y, and Z)
+    * is encoded as a u1Fixed15Number".
+    * This means that max value for this encoding is 1 + (32767/32768)
+    */
+    private static final float MAX_XYZ = 1f + (32767f/32768f);
+    
+    /** The Constant MAX_SHORT. */
+    private static final float MAX_SHORT = 65535f;
+    
+    /** The Constant INV_MAX_SHORT. */
+    private static final float INV_MAX_SHORT = 1f/MAX_SHORT;
+    
+    /** The Constant SHORT2XYZ_FACTOR. */
+    private static final float SHORT2XYZ_FACTOR = MAX_XYZ/MAX_SHORT;
+    
+    /** The Constant XYZ2SHORT_FACTOR. */
+    private static final float XYZ2SHORT_FACTOR = MAX_SHORT/MAX_XYZ;
+
+    /** The profile. */
+    private ICC_Profile profile = null;
+    
+    /** The min values. */
+    private float minValues[] = null;
+    
+    /** The max values. */
+    private float maxValues[] = null;
+
+    // cache transforms here - performance gain
+    /** The to rgb transform. */
+    private ICC_Transform toRGBTransform = null;
+    
+    /** The from rgb transform. */
+    private ICC_Transform fromRGBTransform = null;
+    
+    /** The to xyz transform. */
+    private ICC_Transform toXYZTransform = null;
+    
+    /** The from xyz transform. */
+    private ICC_Transform fromXYZTransform = null;
+
+    /** The converter. */
+    private final ColorConverter converter = new ColorConverter();
+    
+    /** The scaler. */
+    private final ColorScaler scaler = new ColorScaler();
+    
+    /** The scaling data loaded. */
+    private boolean scalingDataLoaded = false;
+
+    /** The resolved deserialized inst. */
+    private ICC_ColorSpace resolvedDeserializedInst;
+
+    /**
+     * Instantiates a new ICC color space from an ICC_Profile object.
+     * 
+     * @param pf the ICC_Profile object.
+     */
+    public ICC_ColorSpace(ICC_Profile pf) {
+        super(pf.getColorSpaceType(), pf.getNumComponents());
+
+        int pfClass = pf.getProfileClass();
+
+        switch (pfClass) {
+            case ICC_Profile.CLASS_COLORSPACECONVERSION:
+            case ICC_Profile.CLASS_DISPLAY:
+            case ICC_Profile.CLASS_OUTPUT:
+            case ICC_Profile.CLASS_INPUT:
+                break; // OK, it is color conversion profile
+            default:
+                // awt.168=Invalid profile class.
+                throw new IllegalArgumentException(Messages.getString("awt.168")); //$NON-NLS-1$
+        }
+
+        profile = pf;
+        fillMinMaxValues();
+    }
+
+    /**
+     * Returns the ICC_Profile for this ICC_ColorSpace.
+     * 
+     * @return the ICC_Profile for this ICC_ColorSpace.
+     */
+    public ICC_Profile getProfile() {
+        if (profile instanceof ICC_ProfileStub) {
+            profile = ((ICC_ProfileStub) profile).loadProfile();
+        }
+
+        return profile;
+    }
+
+    @Override
+    public float[] toRGB(float[] colorvalue) {
+        if (toRGBTransform == null) {
+            ICC_Profile sRGBProfile =
+                ((ICC_ColorSpace) ColorSpace.getInstance(CS_sRGB)).getProfile();
+            ICC_Profile[] profiles = {getProfile(), sRGBProfile};
+            toRGBTransform = new ICC_Transform(profiles);
+            if (!scalingDataLoaded) {
+                scaler.loadScalingData(this);
+                scalingDataLoaded = true;
+            }
+        }
+
+        short[] data = new short[getNumComponents()];
+
+        scaler.scale(colorvalue, data, 0);
+
+        short[] converted =
+            converter.translateColor(toRGBTransform, data, null);
+
+        // unscale to sRGB
+        float[] res = new float[3];
+
+        res[0] = ((converted[0] & 0xFFFF)) * INV_MAX_SHORT;
+        res[1] = ((converted[1] & 0xFFFF)) * INV_MAX_SHORT;
+        res[2] = ((converted[2] & 0xFFFF)) * INV_MAX_SHORT;
+
+        return res;
+    }
+
+    @Override
+    public float[] toCIEXYZ(float[] colorvalue) {
+        if (toXYZTransform == null) {
+            ICC_Profile xyzProfile =
+                ((ICC_ColorSpace) ColorSpace.getInstance(CS_CIEXYZ)).getProfile();
+            ICC_Profile[] profiles = {getProfile(), xyzProfile};
+            try {
+                int[] intents = {
+                        ICC_Profile.icRelativeColorimetric,
+                        ICC_Profile.icPerceptual};
+                toXYZTransform = new ICC_Transform(profiles, intents);
+            } catch (CMMException e) { // No such tag, use what we can
+                toXYZTransform = new ICC_Transform(profiles);
+            }
+
+            if (!scalingDataLoaded) {
+                scaler.loadScalingData(this);
+                scalingDataLoaded = true;
+            }
+        }
+
+        short[] data = new short[getNumComponents()];
+
+        scaler.scale(colorvalue, data, 0);
+
+        short[] converted =
+            converter.translateColor(toXYZTransform, data, null);
+
+        // unscale to XYZ
+        float[] res = new float[3];
+
+        res[0] = ((converted[0] & 0xFFFF)) * SHORT2XYZ_FACTOR;
+        res[1] = ((converted[1] & 0xFFFF)) * SHORT2XYZ_FACTOR;
+        res[2] = ((converted[2] & 0xFFFF)) * SHORT2XYZ_FACTOR;
+
+        return res;
+    }
+
+    @Override
+    public float[] fromRGB(float[] rgbvalue) {
+        if (fromRGBTransform == null) {
+            ICC_Profile sRGBProfile =
+                ((ICC_ColorSpace) ColorSpace.getInstance(CS_sRGB)).getProfile();
+            ICC_Profile[] profiles = {sRGBProfile, getProfile()};
+            fromRGBTransform = new ICC_Transform(profiles);
+            if (!scalingDataLoaded) {
+                scaler.loadScalingData(this);
+                scalingDataLoaded = true;
+            }
+        }
+
+        // scale rgb value to short
+        short[] scaledRGBValue = new short[3];
+        scaledRGBValue[0] = (short)(rgbvalue[0] * MAX_SHORT + 0.5f);
+        scaledRGBValue[1] = (short)(rgbvalue[1] * MAX_SHORT + 0.5f);
+        scaledRGBValue[2] = (short)(rgbvalue[2] * MAX_SHORT + 0.5f);
+
+        short[] converted =
+            converter.translateColor(fromRGBTransform, scaledRGBValue, null);
+
+        float[] res = new float[getNumComponents()];
+
+        scaler.unscale(res, converted, 0);
+
+        return res;
+    }
+
+    @Override
+    public float[] fromCIEXYZ(float[] xyzvalue) {
+        if (fromXYZTransform == null) {
+            ICC_Profile xyzProfile =
+                ((ICC_ColorSpace) ColorSpace.getInstance(CS_CIEXYZ)).getProfile();
+            ICC_Profile[] profiles = {xyzProfile, getProfile()};
+            try {
+                int[] intents = {
+                        ICC_Profile.icPerceptual,
+                        ICC_Profile.icRelativeColorimetric};
+                fromXYZTransform = new ICC_Transform(profiles, intents);
+            } catch (CMMException e) { // No such tag, use what we can
+                fromXYZTransform = new ICC_Transform(profiles);
+            }
+
+            if (!scalingDataLoaded) {
+                scaler.loadScalingData(this);
+                scalingDataLoaded = true;
+            }
+
+        }
+
+        // scale xyz value to short
+        short[] scaledXYZValue = new short[3];
+        scaledXYZValue[0] = (short)(xyzvalue[0] * XYZ2SHORT_FACTOR + 0.5f);
+        scaledXYZValue[1] = (short)(xyzvalue[1] * XYZ2SHORT_FACTOR + 0.5f);
+        scaledXYZValue[2] = (short)(xyzvalue[2] * XYZ2SHORT_FACTOR + 0.5f);
+
+        short[] converted =
+            converter.translateColor(fromXYZTransform, scaledXYZValue, null);
+
+        float[] res = new float[getNumComponents()];
+
+        scaler.unscale(res, converted, 0);
+
+        return res;
+    }
+
+    @Override
+    public float getMinValue(int component) {
+        if ((component < 0) || (component > this.getNumComponents() - 1)) {
+            // awt.169=Component index out of range
+            throw new IllegalArgumentException(Messages.getString("awt.169")); //$NON-NLS-1$
+        }
+
+        return minValues[component];
+    }
+
+    @Override
+    public float getMaxValue(int component) {
+        if ((component < 0) || (component > this.getNumComponents() - 1)) {
+            // awt.169=Component index out of range
+            throw new IllegalArgumentException(Messages.getString("awt.169")); //$NON-NLS-1$
+        }
+
+        return maxValues[component];
+    }
+
+    /**
+     * Fill min max values.
+     */
+    private void fillMinMaxValues() {
+        int n = getNumComponents();
+        maxValues = new float[n];
+        minValues = new float[n];
+        switch (getType()) {
+            case ColorSpace.TYPE_XYZ:
+                minValues[0] = 0;
+                minValues[1] = 0;
+                minValues[2] = 0;
+                maxValues[0] = MAX_XYZ;
+                maxValues[1] = MAX_XYZ;
+                maxValues[2] = MAX_XYZ;
+                break;
+            case ColorSpace.TYPE_Lab:
+                minValues[0] = 0;
+                minValues[1] = -128;
+                minValues[2] = -128;
+                maxValues[0] = 100;
+                maxValues[1] = 127;
+                maxValues[2] = 127;
+                break;
+            default:
+                for(int i=0; i<n; i++) {
+                    minValues[i] = 0;
+                    maxValues[i] = 1;
+                }
+        }
+    }
+
+    /**
+     * Write object.
+     * 
+     * @param out the out
+     * 
+     * @throws IOException Signals that an I/O exception has occurred.
+     */
+    private void writeObject(ObjectOutputStream out) throws IOException {
+        ObjectOutputStream.PutField fields = out.putFields();
+
+        fields.put("thisProfile", profile); //$NON-NLS-1$
+        fields.put("minVal", null); //$NON-NLS-1$
+        fields.put("maxVal", null); //$NON-NLS-1$
+        fields.put("diffMinMax", null); //$NON-NLS-1$
+        fields.put("invDiffMinMax", null); //$NON-NLS-1$
+        fields.put("needScaleInit", true); //$NON-NLS-1$
+
+        out.writeFields();
+    }
+
+    /**
+     * Read object.
+     * 
+     * @param in the in
+     * 
+     * @throws IOException Signals that an I/O exception has occurred.
+     * @throws ClassNotFoundException the class not found exception
+     */
+    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+        ObjectInputStream.GetField fields = in.readFields();
+        resolvedDeserializedInst =
+                new ICC_ColorSpace((ICC_Profile) fields.get("thisProfile", null)); //$NON-NLS-1$
+    }
+
+    /**
+     * Read resolve.
+     * 
+     * @return the object
+     * 
+     * @throws ObjectStreamException the object stream exception
+     */
+    Object readResolve() throws ObjectStreamException {
+        return resolvedDeserializedInst;
+    }
+}
+
diff --git a/awt/java/awt/color/ICC_Profile.java b/awt/java/awt/color/ICC_Profile.java
new file mode 100644
index 0000000..ad704e0
--- /dev/null
+++ b/awt/java/awt/color/ICC_Profile.java
@@ -0,0 +1,1231 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ */
+package java.awt.color;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamException;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.StringTokenizer;
+
+import org.apache.harmony.awt.gl.color.ICC_ProfileHelper;
+import org.apache.harmony.awt.gl.color.NativeCMM;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The ICC_Profile class represents a color profile data for color spaces 
+ * based on the International Color Consortium Specification ICC.1:2001-12, 
+ * File Format for Color Profiles.
+ */
+public class ICC_Profile implements Serializable {
+
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = -3938515861990936766L;
+
+    // NOTE: Constant field values are noted in 1.5 specification.
+
+    /**
+     * The Constant CLASS_INPUT indicates that profile class is input. 
+     */
+    public static final int CLASS_INPUT = 0;
+
+    /** 
+     * The Constant CLASS_DISPLAY indicates that profile class is display. 
+     */
+    public static final int CLASS_DISPLAY = 1;
+
+    /** 
+     * The Constant CLASS_OUTPUT indicates that profile class is output. 
+     */
+    public static final int CLASS_OUTPUT = 2;
+
+    /** 
+     * The Constant CLASS_DEVICELINK indicates that profile class 
+     * is device link. 
+     */
+    public static final int CLASS_DEVICELINK = 3;
+
+    /** 
+     * The Constant CLASS_COLORSPACECONVERSION indicates that profile class 
+     * is color space conversion.
+     */
+    public static final int CLASS_COLORSPACECONVERSION = 4;
+
+    /** The Constant CLASS_ABSTRACT indicates that profile class is abstract. */
+    public static final int CLASS_ABSTRACT = 5;
+
+    /** 
+     * The Constant CLASS_NAMEDCOLOR indicates that profile class 
+     * is named color. 
+     */
+    public static final int CLASS_NAMEDCOLOR = 6;
+
+    /** The Constant icSigXYZData - ICC Profile Color Space Type Signature. */
+    public static final int icSigXYZData = 1482250784;
+
+    /** The Constant icSigLabData - ICC Profile Color Space Type Signature. */
+    public static final int icSigLabData = 1281450528;
+
+    /** The Constant icSigLuvData - ICC Profile Color Space Type Signature. */
+    public static final int icSigLuvData = 1282766368;
+
+    /** The Constant icSigYCbCrData - ICC Profile Color Space Type Signature. */
+    public static final int icSigYCbCrData = 1497588338;
+
+    /** The Constant icSigYxyData - ICC Profile Color Space Type Signature. */
+    public static final int icSigYxyData = 1501067552;
+
+    /** The Constant icSigRgbData - ICC Profile Color Space Type Signature. */
+    public static final int icSigRgbData = 1380401696;
+
+    /** The Constant icSigGrayData - ICC Profile Color Space Type Signature. */
+    public static final int icSigGrayData = 1196573017;
+
+    /** The Constant icSigHsvData - ICC Profile Color Space Type Signature. */
+    public static final int icSigHsvData = 1213421088;
+
+    /** The Constant icSigHlsData - ICC Profile Color Space Type Signature. */
+    public static final int icSigHlsData = 1212961568;
+
+    /** The Constant icSigCmykData - ICC Profile Color Space Type Signature. */
+    public static final int icSigCmykData = 1129142603;
+
+    /** The Constant icSigCmyData - ICC Profile Color Space Type Signature. */
+    public static final int icSigCmyData = 1129142560;
+
+    /** The Constant icSigSpace2CLR - ICC Profile Color Space Type Signature. */
+    public static final int icSigSpace2CLR = 843271250;
+
+    /** The Constant icSigSpace3CLR - ICC Profile Color Space Type Signature. */
+    public static final int icSigSpace3CLR = 860048466;
+
+    /** The Constant icSigSpace4CLR - ICC Profile Color Space Type Signature. */
+    public static final int icSigSpace4CLR = 876825682;
+
+    /** The Constant icSigSpace5CLR - ICC Profile Color Space Type Signature. */
+    public static final int icSigSpace5CLR = 893602898;
+
+    /** The Constant icSigSpace6CLR - ICC Profile Color Space Type Signature. */
+    public static final int icSigSpace6CLR = 910380114;
+
+    /** The Constant icSigSpace7CLR - ICC Profile Color Space Type Signature. */
+    public static final int icSigSpace7CLR = 927157330;
+
+    /** The Constant icSigSpace8CLR - ICC Profile Color Space Type Signature. */
+    public static final int icSigSpace8CLR = 943934546;
+
+    /** The Constant icSigSpace9CLR - ICC Profile Color Space Type Signature. */
+    public static final int icSigSpace9CLR = 960711762;
+
+    /** The Constant icSigSpaceACLR - ICC Profile Color Space Type Signature. */
+    public static final int icSigSpaceACLR = 1094929490;
+
+    /** The Constant icSigSpaceBCLR - ICC Profile Color Space Type Signature. */
+    public static final int icSigSpaceBCLR = 1111706706;
+
+    /** The Constant icSigSpaceCCLR - ICC Profile Color Space Type Signature. */
+    public static final int icSigSpaceCCLR = 1128483922;
+
+    /** The Constant icSigSpaceDCLR - ICC Profile Color Space Type Signature. */
+    public static final int icSigSpaceDCLR = 1145261138;
+
+    /** The Constant icSigSpaceECLR - ICC Profile Color Space Type Signature. */
+    public static final int icSigSpaceECLR = 1162038354;
+
+    /** The Constant icSigSpaceFCLR - ICC Profile Color Space Type Signature. */
+    public static final int icSigSpaceFCLR = 1178815570;
+
+    /** The Constant icSigInputClass - ICC Profile Class Signature. */
+    public static final int icSigInputClass = 1935896178;
+
+    /** The Constant icSigDisplayClass - ICC Profile Class Signature. */
+    public static final int icSigDisplayClass = 1835955314;
+
+    /** The Constant icSigOutputClass - ICC Profile Class Signature. */
+    public static final int icSigOutputClass = 1886549106;
+
+    /** The Constant icSigLinkClass - ICC Profile Class Signature. */
+    public static final int icSigLinkClass = 1818848875;
+
+    /** The Constant icSigAbstractClass - ICC Profile Class Signature. */
+    public static final int icSigAbstractClass = 1633842036;
+
+    /** The Constant icSigColorantOrderTag - ICC Profile Tag Signature. */
+    public static final int icSigColorantOrderTag = 1668051567;
+
+    /** The Constant icSigColorantTableTag - ICC Profile Tag Signature. */
+    public static final int icSigColorantTableTag = 1668051572;
+
+    /** The Constant icSigColorSpaceClass - ICC Profile Tag Signature. */
+    public static final int icSigColorSpaceClass = 1936744803;
+
+    /** The Constant icSigNamedColorClass - ICC Profile Tag Signature. */
+    public static final int icSigNamedColorClass = 1852662636;
+
+    /** The Constant icPerceptual - ICC Profile Rendering Intent. */
+    public static final int icPerceptual = 0;
+
+    /** The Constant icRelativeColorimetric - ICC Profile Rendering Intent. */
+    public static final int icRelativeColorimetric = 1;
+
+    /** The Constant icSaturation - ICC Profile Rendering Intent. */
+    public static final int icSaturation = 2;
+
+    /** The Constant icAbsoluteColorimetric - ICC Profile Rendering Intent. */
+    public static final int icAbsoluteColorimetric = 3;
+
+    /** The Constant icSigHead - ICC Profile Tag Signature. */
+    public static final int icSigHead = 1751474532;
+
+    /** The Constant icSigAToB0Tag - ICC Profile Tag Signature. */
+    public static final int icSigAToB0Tag = 1093812784;
+
+    /** The Constant icSigAToB1Tag - ICC Profile Tag Signature. */
+    public static final int icSigAToB1Tag = 1093812785;
+
+    /** The Constant icSigAToB2Tag - ICC Profile Tag Signature. */
+    public static final int icSigAToB2Tag = 1093812786;
+
+    /** The Constant icSigBlueColorantTag - ICC Profile Tag Signature. */
+    public static final int icSigBlueColorantTag = 1649957210;
+
+    /** The Constant icSigBlueMatrixColumnTag - ICC Profile Tag Signature. */
+    public static final int icSigBlueMatrixColumnTag = 1649957210;
+
+    /** The Constant icSigBlueTRCTag - ICC Profile Tag Signature. */
+    public static final int icSigBlueTRCTag = 1649693251;
+
+    /** The Constant icSigBToA0Tag - ICC Profile Tag Signature. */
+    public static final int icSigBToA0Tag = 1110589744;
+
+    /** The Constant icSigBToA1Tag - ICC Profile Tag Signature. */
+    public static final int icSigBToA1Tag = 1110589745;
+
+    /** The Constant icSigBToA2Tag - ICC Profile Tag Signature. */
+    public static final int icSigBToA2Tag = 1110589746;
+
+    /** The Constant icSigCalibrationDateTimeTag - ICC Profile Tag Signature. */
+    public static final int icSigCalibrationDateTimeTag = 1667329140;
+
+    /** The Constant icSigCharTargetTag - ICC Profile Tag Signature. */
+    public static final int icSigCharTargetTag = 1952543335;
+
+    /** The Constant icSigCopyrightTag - ICC Profile Tag Signature. */
+    public static final int icSigCopyrightTag = 1668313716;
+
+    /** The Constant icSigCrdInfoTag - ICC Profile Tag Signature. */
+    public static final int icSigCrdInfoTag = 1668441193;
+
+    /** The Constant icSigDeviceMfgDescTag - ICC Profile Tag Signature. */
+    public static final int icSigDeviceMfgDescTag = 1684893284;
+
+    /** The Constant icSigDeviceModelDescTag - ICC Profile Tag Signature. */
+    public static final int icSigDeviceModelDescTag = 1684890724;
+
+    /** The Constant icSigDeviceSettingsTag - ICC Profile Tag Signature. */
+    public static final int icSigDeviceSettingsTag = 1684371059;
+
+    /** The Constant icSigGamutTag - ICC Profile Tag Signature. */
+    public static final int icSigGamutTag = 1734438260;
+
+    /** The Constant icSigGrayTRCTag - ICC Profile Tag Signature. */
+    public static final int icSigGrayTRCTag = 1800688195;
+
+    /** The Constant icSigGreenColorantTag - ICC Profile Tag Signature. */
+    public static final int icSigGreenColorantTag = 1733843290;
+
+    /** The Constant icSigGreenMatrixColumnTag - ICC Profile Tag Signature. */
+    public static final int icSigGreenMatrixColumnTag = 1733843290;
+
+    /** The Constant icSigGreenTRCTag - ICC Profile Tag Signature. */
+    public static final int icSigGreenTRCTag = 1733579331;
+
+    /** The Constant icSigLuminanceTag - ICC Profile Tag Signature. */
+    public static final int icSigLuminanceTag = 1819635049;
+
+    /** The Constant icSigMeasurementTag - ICC Profile Tag Signature. */
+    public static final int icSigMeasurementTag = 1835360627;
+
+    /** The Constant icSigMediaBlackPointTag - ICC Profile Tag Signature. */
+    public static final int icSigMediaBlackPointTag = 1651208308;
+
+    /** The Constant icSigMediaWhitePointTag - ICC Profile Tag Signature. */
+    public static final int icSigMediaWhitePointTag = 2004119668;
+
+    /** The Constant icSigNamedColor2Tag - ICC Profile Tag Signature. */
+    public static final int icSigNamedColor2Tag = 1852009522;
+
+    /** The Constant icSigOutputResponseTag - ICC Profile Tag Signature. */
+    public static final int icSigOutputResponseTag = 1919251312;
+
+    /** The Constant icSigPreview0Tag - ICC Profile Tag Signature. */
+    public static final int icSigPreview0Tag = 1886545200;
+
+    /** The Constant icSigPreview1Tag - ICC Profile Tag Signature. */
+    public static final int icSigPreview1Tag = 1886545201;
+
+    /** The Constant icSigPreview2Tag - ICC Profile Tag Signature. */
+    public static final int icSigPreview2Tag = 1886545202;
+
+    /** The Constant icSigProfileDescriptionTag - ICC Profile Tag Signature. */
+    public static final int icSigProfileDescriptionTag = 1684370275;
+
+    /** The Constant icSigProfileSequenceDescTag - ICC Profile Tag Signature. */
+    public static final int icSigProfileSequenceDescTag = 1886610801;
+
+    /** The Constant icSigPs2CRD0Tag - ICC Profile Tag Signature. */
+    public static final int icSigPs2CRD0Tag = 1886610480;
+
+    /** The Constant icSigPs2CRD1Tag - ICC Profile Tag Signature. */
+    public static final int icSigPs2CRD1Tag = 1886610481;
+
+    /** The Constant icSigPs2CRD2Tag - ICC Profile Tag Signature. */
+    public static final int icSigPs2CRD2Tag = 1886610482;
+
+    /** The Constant icSigPs2CRD3Tag - ICC Profile Tag Signature. */
+    public static final int icSigPs2CRD3Tag = 1886610483;
+
+    /** The Constant icSigPs2CSATag - ICC Profile Tag Signature. */
+    public static final int icSigPs2CSATag = 1886597747;
+
+    /** The Constant icSigPs2RenderingIntentTag - ICC Profile Tag Signature. */
+    public static final int icSigPs2RenderingIntentTag = 1886597737;
+
+    /** The Constant icSigRedColorantTag - ICC Profile Tag Signature. */
+    public static final int icSigRedColorantTag = 1918392666;
+
+    /** The Constant icSigRedMatrixColumnTag - ICC Profile Tag Signature. */
+    public static final int icSigRedMatrixColumnTag = 1918392666;
+
+    /** The Constant icSigRedTRCTag - ICC Profile Tag Signature. */
+    public static final int icSigRedTRCTag = 1918128707;
+
+    /** The Constant icSigScreeningDescTag - ICC Profile Tag Signature. */
+    public static final int icSigScreeningDescTag = 1935897188;
+
+    /** The Constant icSigScreeningTag - ICC Profile Tag Signature. */
+    public static final int icSigScreeningTag = 1935897198;
+
+    /** The Constant icSigTechnologyTag - ICC Profile Tag Signature. */
+    public static final int icSigTechnologyTag = 1952801640;
+
+    /** The Constant icSigUcrBgTag - ICC Profile Tag Signature. */
+    public static final int icSigUcrBgTag = 1650877472;
+
+    /** The Constant icSigViewingCondDescTag - ICC Profile Tag Signature. */
+    public static final int icSigViewingCondDescTag = 1987405156;
+
+    /** The Constant icSigViewingConditionsTag - ICC Profile Tag Signature. */
+    public static final int icSigViewingConditionsTag = 1986618743;
+
+    /** The Constant icSigChromaticAdaptationTag - ICC Profile Tag Signature. */
+    public static final int icSigChromaticAdaptationTag = 1667785060;
+
+    /** The Constant icSigChromaticityTag - ICC Profile Tag Signature. */
+    public static final int icSigChromaticityTag = 1667789421;
+
+    /** The Constant icHdrSize - ICC Profile Header Location. */
+    public static final int icHdrSize = 0;
+
+    /** The Constant icHdrCmmId - ICC Profile Header Location. */
+    public static final int icHdrCmmId = 4;
+
+    /** The Constant icHdrVersion - ICC Profile Header Location. */
+    public static final int icHdrVersion = 8;
+
+    /** The Constant icHdrDeviceClass - ICC Profile Header Location. */
+    public static final int icHdrDeviceClass = 12;
+
+    /** The Constant icHdrColorSpace - ICC Profile Header Location. */
+    public static final int icHdrColorSpace = 16;
+
+    /** The Constant icHdrPcs - ICC Profile Header Location. */
+    public static final int icHdrPcs = 20;
+
+    /** The Constant icHdrDate - ICC Profile Header Location. */
+    public static final int icHdrDate = 24;
+
+    /** The Constant icHdrMagic - ICC Profile Header Location. */
+    public static final int icHdrMagic = 36;
+
+    /** The Constant icHdrPlatform - ICC Profile Header Location. */
+    public static final int icHdrPlatform = 40;
+
+    /** The Constant icHdrProfileID - ICC Profile Header Location. */
+    public static final int icHdrProfileID = 84;
+
+    /** The Constant icHdrFlags - ICC Profile Header Location. */
+    public static final int icHdrFlags = 44;
+
+    /** The Constant icHdrManufacturer - ICC Profile Header Location. */
+    public static final int icHdrManufacturer = 48;
+
+    /** The Constant icHdrModel - ICC Profile Header Location. */
+    public static final int icHdrModel = 52;
+
+    /** The Constant icHdrAttributes - ICC Profile Header Location. */
+    public static final int icHdrAttributes = 56;
+
+    /** The Constant icHdrRenderingIntent - ICC Profile Header Location. */
+    public static final int icHdrRenderingIntent = 64;
+
+    /** The Constant icHdrIlluminant - ICC Profile Header Location. */
+    public static final int icHdrIlluminant = 68;
+
+    /** The Constant icHdrCreator - ICC Profile Header Location. */
+    public static final int icHdrCreator = 80;
+
+    /** The Constant icICCAbsoluteColorimetric - ICC Profile Rendering Intent. */
+    public static final int icICCAbsoluteColorimetric = 3;
+
+    /** The Constant icMediaRelativeColorimetric - ICC Profile Rendering Intent. */
+    public static final int icMediaRelativeColorimetric = 1;
+
+    /** The Constant icTagType - ICC Profile Constant. */
+    public static final int icTagType = 0;
+
+    /** The Constant icTagReserved - ICC Profile Constant. */
+    public static final int icTagReserved = 4;
+
+    /** The Constant icCurveCount - ICC Profile Constant. */
+    public static final int icCurveCount = 8;
+
+    /** The Constant icCurveData - ICC Profile Constant. */
+    public static final int icCurveData = 12;
+
+    /** The Constant icXYZNumberX - ICC Profile Constant. */
+    public static final int icXYZNumberX = 8;
+
+    /** Size of a profile header. */
+    private static final int headerSize = 128;
+
+    /** header magic number. */
+    private static final int headerMagicNumber = 0x61637370;
+
+    // Cache of predefined profiles
+    /** The s rgb profile. */
+    private static ICC_Profile sRGBProfile;
+    
+    /** The xyz profile. */
+    private static ICC_Profile xyzProfile;
+    
+    /** The gray profile. */
+    private static ICC_Profile grayProfile;
+    
+    /** The pycc profile. */
+    private static ICC_Profile pyccProfile;
+    
+    /** The linear rgb profile. */
+    private static ICC_Profile linearRGBProfile;
+
+    /** Handle to the current profile. */
+    private transient long profileHandle = 0;
+
+    /** If handle is used by another class this object is not responsible for closing profile. */
+    private transient boolean handleStolen = false;
+
+    /** Cached header data. */
+    private transient byte[] headerData = null;
+
+    /** Serialization support. */
+    private transient ICC_Profile openedProfileObject;
+
+    /**
+     * Instantiates a new iC c_ profile.
+     * 
+     * @param data the data
+     */
+    private ICC_Profile(byte[] data) {
+        profileHandle = NativeCMM.cmmOpenProfile(data);
+        NativeCMM.addHandle(this, profileHandle);
+    }
+
+    /**
+     * Used to instantiate dummy ICC_ProfileStub objects.
+     */
+    ICC_Profile() {
+    }
+
+    /**
+     * Used to instantiate subclasses (ICC_ProfileGrey and ICC_ProfileRGB).
+     * 
+     * @param profileHandle - should be valid handle to opened color profile
+     */
+    ICC_Profile(long profileHandle) {
+        this.profileHandle = profileHandle;
+        // A new object reference, need to add it.
+        NativeCMM.addHandle(this, profileHandle);
+    }
+
+    /**
+     * Writes the ICC_Profile to a file with the specified name.
+     * 
+     * @param fileName the file name.
+     * 
+     * @throws IOException signals that an I/O exception has occurred during
+     * writing or opening the file.
+     */
+    public void write(String fileName) throws IOException {
+        FileOutputStream oStream = new FileOutputStream(fileName);
+        oStream.write(getData());
+        oStream.close();
+    }
+
+    /**
+     * Serializable implementation.
+     * 
+     * @param s the s
+     * 
+     * @throws IOException Signals that an I/O exception has occurred.
+     */
+    private void writeObject(ObjectOutputStream s) throws IOException {
+        s.defaultWriteObject();
+        s.writeObject(null);
+        s.writeObject(getData());
+    }
+
+    /**
+     * Serializable implementation.
+     * 
+     * @param s the s
+     * 
+     * @throws IOException Signals that an I/O exception has occurred.
+     * @throws ClassNotFoundException the class not found exception
+     */
+    private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
+        s.defaultReadObject();
+        String colorSpaceStr = (String)s.readObject();
+        byte[] data = (byte[])s.readObject();
+
+        if (colorSpaceStr != null) {
+            if (colorSpaceStr.equals("CS_sRGB")) { //$NON-NLS-1$
+                openedProfileObject = getInstance(ColorSpace.CS_sRGB);
+            } else if (colorSpaceStr.equals("CS_GRAY")) { //$NON-NLS-1$
+                openedProfileObject = getInstance(ColorSpace.CS_GRAY);
+            } else if (colorSpaceStr.equals("CS_LINEAR_RGB")) { //$NON-NLS-1$
+                openedProfileObject = getInstance(ColorSpace.CS_LINEAR_RGB);
+            } else if (colorSpaceStr.equals("CS_CIEXYZ")) { //$NON-NLS-1$
+                openedProfileObject = getInstance(ColorSpace.CS_CIEXYZ);
+            } else if (colorSpaceStr.equals("CS_PYCC")) { //$NON-NLS-1$
+                openedProfileObject = getInstance(ColorSpace.CS_PYCC);
+            } else {
+                openedProfileObject = ICC_Profile.getInstance(data);
+            }
+        } else {
+            openedProfileObject = ICC_Profile.getInstance(data);
+        }
+    }
+
+    /**
+     * Resolves instances being deserialized into instances registered with CMM.
+     * 
+     * @return ICC_Profile object for profile registered with CMM.
+     * 
+     * @throws ObjectStreamException if there is an error in the serialized 
+     * files or during the process of reading them.
+     */
+    protected Object readResolve() throws ObjectStreamException {
+        return openedProfileObject;
+    }
+
+    /**
+     * Writes the ICC_Profile to an OutputStream.
+     * 
+     * @param s the OutputStream.
+     * 
+     * @throws IOException signals that an I/O exception has occurred during
+     * writing or opening OutputStream.
+     */
+    public void write(OutputStream s) throws IOException {
+        s.write(getData());
+    }
+
+    /**
+     * Sets a tagged data element in the profile from a byte array. 
+     * 
+     * @param tagSignature the ICC tag signature for the data element to be set. 
+     * @param tagData the data to be set for the specified tag signature.
+     */
+    public void setData(int tagSignature, byte[] tagData) {
+        NativeCMM.cmmSetProfileElement(profileHandle, tagSignature, tagData);
+        // Remove cached header data if header is modified
+        if (tagSignature == icSigHead) {
+            headerData = null;
+        }
+    }
+
+    /**
+     * Gets a tagged data element from the profile as a byte array. 
+     * Elements are identified by tag signatures as defined in 
+     * the ICC specification. 
+     * 
+     * @param tagSignature the ICC tag signature for the data element to get.
+     * 
+     * @return a byte array that contains the tagged data element.
+     */
+    public byte[] getData(int tagSignature) {
+        int tagSize = 0;
+        try {
+            tagSize = NativeCMM.cmmGetProfileElementSize(
+                    profileHandle,
+                    tagSignature
+                );
+        } catch (CMMException e) {
+            // We'll get this exception if there's no element with
+            // the specified tag signature
+            return null;
+        }
+
+        byte[] data = new byte[tagSize];
+        NativeCMM.cmmGetProfileElement(profileHandle, tagSignature, data);
+        return data;
+    }
+
+    /**
+     * Gets a data byte array of this ICC_Profile.
+     * 
+     * @return a byte array that contains the ICC Profile data.
+     */
+    public byte[] getData() {
+        int profileSize = NativeCMM.cmmGetProfileSize(profileHandle);
+        byte[] data = new byte[profileSize];
+        NativeCMM.cmmGetProfile(profileHandle, data);
+        return data;
+    }
+
+    /**
+     * Frees the resources associated with an ICC_Profile object.
+     */
+    @Override
+    protected void finalize() {
+        if (profileHandle!=0 && !handleStolen) {
+            NativeCMM.cmmCloseProfile(profileHandle);
+        }
+
+        // Always remove because key no more exist
+        // when object is destroyed
+        NativeCMM.removeHandle(this);
+    }
+
+    /**
+     * Gets the profile class.
+     * 
+     * @return the profile class constant.
+     */
+    public int getProfileClass() {
+        int deviceClassSignature = getIntFromHeader(icHdrDeviceClass);
+
+        switch (deviceClassSignature) {
+            case icSigColorSpaceClass:
+                return CLASS_COLORSPACECONVERSION;
+            case icSigDisplayClass:
+                return CLASS_DISPLAY;
+            case icSigOutputClass:
+                return CLASS_OUTPUT;
+            case icSigInputClass:
+                return CLASS_INPUT;
+            case icSigLinkClass:
+                return CLASS_DEVICELINK;
+            case icSigAbstractClass:
+                return CLASS_ABSTRACT;
+            case icSigNamedColorClass:
+                return CLASS_NAMEDCOLOR;
+            default:
+        }
+
+        // Not an ICC profile class
+        // awt.15F=Profile class does not comply with ICC specification
+        throw new IllegalArgumentException(Messages.getString("awt.15F")); //$NON-NLS-1$
+        
+    }
+
+    /**
+     * Returns the color space type of the Profile Connection Space (PCS).
+     * 
+     * @return the PCS type.
+     */
+    public int getPCSType() {
+         return csFromSignature(getIntFromHeader(icHdrPcs));
+    }
+
+    /**
+     * Gets the number of components of this ICC Profile.
+     * 
+     * @return the number of components of this ICC Profile.
+     */
+    public int getNumComponents() {
+        switch (getIntFromHeader(icHdrColorSpace)) {
+            // The most common cases go first to increase speed
+            case icSigRgbData:
+            case icSigXYZData:
+            case icSigLabData:
+                return 3;
+            case icSigCmykData:
+                return 4;
+                // Then all other
+            case icSigGrayData:
+                return 1;
+            case icSigSpace2CLR:
+                return 2;
+            case icSigYCbCrData:
+            case icSigLuvData:
+            case icSigYxyData:
+            case icSigHlsData:
+            case icSigHsvData:
+            case icSigCmyData:
+            case icSigSpace3CLR:
+                return 3;
+            case icSigSpace4CLR:
+                return 4;
+            case icSigSpace5CLR:
+                return 5;
+            case icSigSpace6CLR:
+                return 6;
+            case icSigSpace7CLR:
+                return 7;
+            case icSigSpace8CLR:
+                return 8;
+            case icSigSpace9CLR:
+                return 9;
+            case icSigSpaceACLR:
+                return 10;
+            case icSigSpaceBCLR:
+                return 11;
+            case icSigSpaceCCLR:
+                return 12;
+            case icSigSpaceDCLR:
+                return 13;
+            case icSigSpaceECLR:
+                return 14;
+            case icSigSpaceFCLR:
+                return 15;
+            default:
+        }
+
+        // awt.160=Color space doesn't comply with ICC specification
+        throw new ProfileDataException(Messages.getString("awt.160") //$NON-NLS-1$
+        );
+    }
+
+    /**
+     * Gets the minor version of this ICC profile.
+     * 
+     * @return the minor version of this ICC profile.
+     */
+    public int getMinorVersion() {
+        return getByteFromHeader(icHdrVersion+1);
+    }
+
+    /**
+     * Gets the major version of this ICC profile.
+     * 
+     * @return the major version of this ICC profile.
+     */
+    public int getMajorVersion() {
+        return getByteFromHeader(icHdrVersion);
+    }
+
+    /**
+     * Gets the color space type of this ICC_Profile.
+     * 
+     * @return the color space type.
+     */
+    public int getColorSpaceType() {
+        return csFromSignature(getIntFromHeader(icHdrColorSpace));
+    }
+
+    /**
+     * Tries to open file at the specified path. Path entries can be 
+     * divided by a separator character.
+     * 
+     * @param path the path
+     * @param fileName the file name
+     * 
+     * @return the file input stream
+     */
+    private static FileInputStream tryPath(String path, String fileName) {
+        FileInputStream fiStream = null;
+
+        if (path == null) {
+            return null;
+        }
+
+        StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
+
+        while (st.hasMoreTokens()) {
+            String pathEntry = st.nextToken();
+            try {
+                fiStream = new FileInputStream(pathEntry + File.separatorChar + fileName);
+                if (fiStream != null) {
+                    return fiStream;
+                }
+            } catch (FileNotFoundException e) {}
+        }
+
+        return fiStream;
+    }
+
+    /**
+     * Gets the single instance of ICC_Profile from data in the specified file.
+     * 
+     * @param fileName the specified name of file with ICC profile data.
+     * 
+     * @return single instance of ICC_Profile.
+     * 
+     * @throws IOException signals that an I/O error occured while reading the file
+     * or the file doesn't exist.
+     */
+    public static ICC_Profile getInstance(String fileName) throws IOException {
+        final String fName = fileName; // to use in the privileged block
+
+        FileInputStream fiStream = (FileInputStream) AccessController.doPrivileged(
+                new PrivilegedAction<FileInputStream>() {
+                    public FileInputStream run() {
+                        FileInputStream fiStream = null;
+
+                        // Open absolute path
+                        try {
+                            fiStream = new FileInputStream(fName);
+                            if (fiStream != null) {
+                                return fiStream;
+                            }
+                        } catch (FileNotFoundException e) {}
+
+                        // Check java.iccprofile.path entries
+                        fiStream = tryPath(System.getProperty("java.iccprofile.path"), fName); //$NON-NLS-1$
+                        if (fiStream != null) {
+                            return fiStream;
+                        }
+
+                        // Check java.class.path entries
+                        fiStream = tryPath(System.getProperty("java.class.path"), fName); //$NON-NLS-1$
+                        if (fiStream != null) {
+                            return fiStream;
+                        }
+
+                        // Check directory with java sample profiles
+                        String home = System.getProperty("java.home"); //$NON-NLS-1$
+                        if (home != null) {
+                            fiStream = tryPath(
+                                    home + File.separatorChar +
+                                    "lib" + File.separatorChar + "cmm", fName //$NON-NLS-1$ //$NON-NLS-2$
+                            );
+                        }
+
+                        return fiStream;
+                    }
+                });
+
+        if (fiStream == null) {
+            // awt.161=Unable to open file {0}
+            throw new IOException(Messages.getString("awt.161", fileName)); //$NON-NLS-1$
+        }
+
+        ICC_Profile pf = getInstance(fiStream);
+        fiStream.close();
+        return pf;
+    }
+
+    /**
+     * Gets the single instance of ICC_Profile with data in
+     * the specified InputStream.
+     * 
+     * @param s the InputStream with ICC profile data.
+     * 
+     * @return single instance of ICC_Profile.
+     * 
+     * @throws IOException if an I/O exception has occurred during reading 
+     * from InputStream.
+     * @throws IllegalArgumentException if the file does not contain valid 
+     * ICC Profile data.
+     */
+    public static ICC_Profile getInstance(InputStream s) throws IOException {
+        byte[] header = new byte[headerSize];
+        // awt.162=Invalid ICC Profile Data
+        String invalidDataMessage = Messages.getString("awt.162"); //$NON-NLS-1$
+
+        // Get header from the input stream
+        if (s.read(header) != headerSize) {
+            throw new IllegalArgumentException(invalidDataMessage);
+        }
+
+        // Check the profile data for consistency
+        if (
+                ICC_ProfileHelper.getBigEndianFromByteArray(header, icHdrMagic) !=
+                headerMagicNumber
+        ) {
+            throw new IllegalArgumentException(invalidDataMessage);
+        }
+
+        // Get profile size from header, create an array for profile data
+        int profileSize = ICC_ProfileHelper.getBigEndianFromByteArray(header, icHdrSize);
+        byte[] profileData = new byte[profileSize];
+
+        // Copy header into it
+        System.arraycopy(header, 0, profileData, 0, headerSize);
+
+        // Read the profile itself
+        if (
+                s.read(profileData, headerSize, profileSize - headerSize) !=
+                profileSize - headerSize
+        ) {
+            throw new IllegalArgumentException(invalidDataMessage);
+        }
+
+        return getInstance(profileData);
+    }
+
+    /**
+     * Gets the single instance of ICC_Profile from the specified data in 
+     * a byte array.
+     * 
+     * @param data the byte array of ICC profile.
+     * 
+     * @return single instance of ICC_Profile from the specified data in 
+     * a byte array.
+     * 
+     * @throws IllegalArgumentException if the file does not contain valid 
+     * ICC Profile data.
+     */
+    public static ICC_Profile getInstance(byte[] data) {
+        ICC_Profile res = null;
+
+        try {
+            res = new ICC_Profile(data);
+        } catch (CMMException e) {
+            // awt.162=Invalid ICC Profile Data
+            throw new IllegalArgumentException(Messages.getString("awt.162")); //$NON-NLS-1$
+        }
+
+      if (System.getProperty("os.name").toLowerCase().indexOf("windows") >= 0) { //$NON-NLS-1$ //$NON-NLS-2$
+        try {
+            if ( res.getColorSpaceType () == ColorSpace.TYPE_RGB &&
+                 res.getDataSize(icSigMediaWhitePointTag) > 0 &&
+                 res.getDataSize(icSigRedColorantTag) > 0 &&
+                 res.getDataSize(icSigGreenColorantTag) > 0 &&
+                 res.getDataSize(icSigBlueColorantTag) > 0 &&
+                 res.getDataSize(icSigRedTRCTag) > 0 &&
+                 res.getDataSize(icSigGreenTRCTag) > 0 &&
+                 res.getDataSize(icSigBlueTRCTag) > 0
+                ) {
+                res = new ICC_ProfileRGB(res.getProfileHandle());
+            } else if ( res.getColorSpaceType () == ColorSpace.TYPE_GRAY &&
+                        res.getDataSize(icSigMediaWhitePointTag) > 0 &&
+                        res.getDataSize(icSigGrayTRCTag) > 0
+                ) {
+                res = new ICC_ProfileGray (res.getProfileHandle());
+            }
+
+        } catch (CMMException e) { /* return res in this case */ }
+      }
+
+      return res;
+    }
+
+    /**
+     * Gets the single instance of ICC_Profile with the specific color space
+     * defined by the ColorSpace class: CS_sRGB, CS_LINEAR_RGB, CS_CIEXYZ,
+     * CS_PYCC, CS_GRAY.
+     * 
+     * @param cspace the type of color space defined in the ColorSpace class.
+     * 
+     * @return single instance of ICC_Profile.
+     * 
+     * @throws IllegalArgumentException is not one of the defined color 
+     * space types.
+     */
+    public static ICC_Profile getInstance(int cspace) {
+    try {
+      switch (cspace) {
+
+      case ColorSpace.CS_sRGB:
+        if (sRGBProfile == null) {
+            sRGBProfile = getInstance("sRGB.pf"); //$NON-NLS-1$
+        }
+        return sRGBProfile;
+
+      case ColorSpace.CS_CIEXYZ:
+        if (xyzProfile == null) {
+            xyzProfile = getInstance("CIEXYZ.pf"); //$NON-NLS-1$
+        }
+        return xyzProfile;
+
+      case ColorSpace.CS_GRAY:
+        if (grayProfile == null) {
+            grayProfile = getInstance("GRAY.pf"); //$NON-NLS-1$
+        }
+        return grayProfile;
+
+      case ColorSpace.CS_PYCC:
+        if (pyccProfile == null) {
+            pyccProfile = getInstance("PYCC.pf"); //$NON-NLS-1$
+        }
+        return pyccProfile;
+
+      case ColorSpace.CS_LINEAR_RGB:
+        if (linearRGBProfile == null) {
+            linearRGBProfile = getInstance("LINEAR_RGB.pf"); //$NON-NLS-1$
+        }
+        return linearRGBProfile;
+      }
+
+    } catch (IOException e) {
+        // awt.163=Can't open color profile 
+        throw new IllegalArgumentException(Messages.getString("Can't open color profile")); //$NON-NLS-1$
+    }
+
+    // awt.164=Not a predefined color space
+    throw new IllegalArgumentException(Messages.getString("Not a predefined color space")); //$NON-NLS-1$
+  }
+
+    /**
+     * Reads an integer from the profile header at the specified position.
+     * 
+     * @param idx - offset in bytes from the beginning of the header
+     * 
+     * @return the int from header
+     */
+    private int getIntFromHeader(int idx) {
+        if (headerData == null) {
+            headerData = getData(icSigHead);
+        }
+
+        return  ((headerData[idx]   & 0xFF) << 24)|
+                  ((headerData[idx+1] & 0xFF) << 16)|
+                  ((headerData[idx+2] & 0xFF) << 8) |
+                  ((headerData[idx+3] & 0xFF));
+    }
+
+    /**
+     * Reads byte from the profile header at the specified position.
+     * 
+     * @param idx - offset in bytes from the beginning of the header
+     * 
+     * @return the byte from header
+     */
+    private byte getByteFromHeader(int idx) {
+        if (headerData == null) {
+            headerData = getData(icSigHead);
+        }
+
+        return headerData[idx];
+    }
+
+    /**
+     * Converts ICC color space signature to the java predefined
+     * color space type.
+     * 
+     * @param signature the signature
+     * 
+     * @return the int
+     */
+    private int csFromSignature(int signature) {
+        switch (signature) {
+            case icSigRgbData:
+                return ColorSpace.TYPE_RGB;
+            case icSigXYZData:
+                return ColorSpace.TYPE_XYZ;
+            case icSigCmykData:
+                return ColorSpace.TYPE_CMYK;
+            case icSigLabData:
+                return ColorSpace.TYPE_Lab;
+            case icSigGrayData:
+                return ColorSpace.TYPE_GRAY;
+            case icSigHlsData:
+                return ColorSpace.TYPE_HLS;
+            case icSigLuvData:
+                return ColorSpace.TYPE_Luv;
+            case icSigYCbCrData:
+                return ColorSpace.TYPE_YCbCr;
+            case icSigYxyData:
+                return ColorSpace.TYPE_Yxy;
+            case icSigHsvData:
+                return ColorSpace.TYPE_HSV;
+            case icSigCmyData:
+                return ColorSpace.TYPE_CMY;
+            case icSigSpace2CLR:
+                return ColorSpace.TYPE_2CLR;
+            case icSigSpace3CLR:
+                return ColorSpace.TYPE_3CLR;
+            case icSigSpace4CLR:
+                return ColorSpace.TYPE_4CLR;
+            case icSigSpace5CLR:
+                return ColorSpace.TYPE_5CLR;
+            case icSigSpace6CLR:
+                return ColorSpace.TYPE_6CLR;
+            case icSigSpace7CLR:
+                return ColorSpace.TYPE_7CLR;
+            case icSigSpace8CLR:
+                return ColorSpace.TYPE_8CLR;
+            case icSigSpace9CLR:
+                return ColorSpace.TYPE_9CLR;
+            case icSigSpaceACLR:
+                return ColorSpace.TYPE_ACLR;
+            case icSigSpaceBCLR:
+                return ColorSpace.TYPE_BCLR;
+            case icSigSpaceCCLR:
+                return ColorSpace.TYPE_CCLR;
+            case icSigSpaceDCLR:
+                return ColorSpace.TYPE_DCLR;
+            case icSigSpaceECLR:
+                return ColorSpace.TYPE_ECLR;
+            case icSigSpaceFCLR:
+                return ColorSpace.TYPE_FCLR;
+            default:
+        }
+
+        // awt.165=Color space doesn't comply with ICC specification
+        throw new IllegalArgumentException (Messages.getString("awt.165")); //$NON-NLS-1$
+    }
+
+    /**
+     * Gets the profile handle.
+     * 
+     * @return the profile handle
+     */
+    private long getProfileHandle() {
+        handleStolen = true;
+        return profileHandle;
+    }
+
+    /**
+     * Gets the data size.
+     * 
+     * @param tagSignature the tag signature
+     * 
+     * @return the data size
+     */
+    private int getDataSize(int tagSignature) {
+        return NativeCMM.cmmGetProfileElementSize(
+                profileHandle,
+                tagSignature
+            );
+    }
+
+    /**
+     * Reads XYZ value from the tag data.
+     * 
+     * @param tagSignature the tag signature
+     * 
+     * @return the XYZ value
+     */
+    float[] getXYZValue(int tagSignature) {
+        float[] res = new float[3];
+        byte[] data = getData(tagSignature);
+
+        // Convert from ICC s15Fixed16Number type
+        // 1 (float) = 0x10000 (s15Fixed16Number),
+        // hence dividing by 0x10000
+        res[0] = ICC_ProfileHelper.getIntFromByteArray(data, 0) / 65536.f;
+        res[1] = ICC_ProfileHelper.getIntFromByteArray(data, 4) / 65536.f;
+        res[2] = ICC_ProfileHelper.getIntFromByteArray(data, 8) / 65536.f;
+
+        return res;
+    }
+
+    /**
+     * Gets the media white point.
+     * 
+     * @return the media white point
+     */
+    float[] getMediaWhitePoint() {
+        return getXYZValue(icSigMediaWhitePointTag);
+    }
+
+    /**
+     * If TRC is not a table returns gamma via return value
+     * and sets dataTRC to null. If TRC is a table returns 0
+     * and fills dataTRC with values.
+     * 
+     * @param tagSignature the tag signature
+     * @param dataTRC the data trc
+     * 
+     * @return - gamma or zero if TRC is a table
+     */
+    private float getGammaOrTRC(int tagSignature, short[] dataTRC) {
+        byte[] data = getData(tagSignature);
+        int trcSize = ICC_ProfileHelper.getIntFromByteArray(data, icCurveCount);
+
+        dataTRC = null;
+
+        if (trcSize == 0) {
+            return 1.0f;
+        }
+
+        if (trcSize == 1) {
+            // Cast from ICC u8Fixed8Number to float
+            return ICC_ProfileHelper.getShortFromByteArray(data, icCurveData) / 256.f;
+        }
+
+        // TRC is a table
+        dataTRC = new short[trcSize];
+        for (int i = 0, pos = icCurveData; i < trcSize; i++, pos += 2) {
+            dataTRC[i] = ICC_ProfileHelper.getShortFromByteArray(data, pos);
+        }
+        return 0;
+    }
+
+    /**
+     * Gets the gamma.
+     * 
+     * @param tagSignature the tag signature
+     * 
+     * @return the gamma
+     */
+    float getGamma(int tagSignature) {
+        short[] dataTRC = null;
+        float gamma = getGammaOrTRC(tagSignature, dataTRC);
+
+        if (dataTRC == null) {
+            return gamma;
+        }
+        // awt.166=TRC is not a simple gamma value.
+        throw new ProfileDataException(Messages.getString("awt.166")); //$NON-NLS-1$
+    }
+
+    /**
+     * Gets the tRC.
+     * 
+     * @param tagSignature the tag signature
+     * 
+     * @return the tRC
+     */
+    short[] getTRC(int tagSignature) {
+        short[] dataTRC = null;
+        getGammaOrTRC(tagSignature, dataTRC);
+
+        if (dataTRC == null) {
+            // awt.167=TRC is a gamma value, not a table.
+            throw new ProfileDataException(Messages.getString("awt.167")); //$NON-NLS-1$
+        }
+        return dataTRC;
+    }
+}
+
diff --git a/awt/java/awt/color/ICC_ProfileGray.java b/awt/java/awt/color/ICC_ProfileGray.java
new file mode 100644
index 0000000..f009b18
--- /dev/null
+++ b/awt/java/awt/color/ICC_ProfileGray.java
@@ -0,0 +1,68 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ */
+package java.awt.color;
+
+/**
+ * The ICC_ProfileGray class represent profiles with TYPE_GRAY color space type,
+ * and includes the grayTRCTag and mediaWhitePointTag tags. 
+ * 
+ * The gray component can be transformed from a GRAY device profile color space 
+ * to the CIEXYZ Profile through the tone reproduction curve (TRC): 
+ * <p>PCSY = grayTRC[deviceGray]
+ */
+public class ICC_ProfileGray extends ICC_Profile {
+    
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = -1124721290732002649L;
+
+    /**
+     * Instantiates a new iC c_ profile gray.
+     * 
+     * @param profileHandle the profile handle
+     */
+    ICC_ProfileGray(long profileHandle) {
+        super(profileHandle);
+    }
+
+    /**
+     * Gets the TRC as an array of shorts.
+     * 
+     * @return a short array of the TRC.
+     */
+    public short[] getTRC() {
+        return super.getTRC(icSigGrayTRCTag);
+    }
+
+    @Override
+    public float[] getMediaWhitePoint() {
+        return super.getMediaWhitePoint();
+    }
+
+    /**
+     * Gets a gamma value representing the tone reproduction curve (TRC).
+     * 
+     * @return the gamma value representing the tone reproduction curve (TRC).
+     */
+    public float getGamma() {
+        return super.getGamma(icSigGrayTRCTag);
+    }
+}
+
diff --git a/awt/java/awt/color/ICC_ProfileRGB.java b/awt/java/awt/color/ICC_ProfileRGB.java
new file mode 100644
index 0000000..beb1a0c
--- /dev/null
+++ b/awt/java/awt/color/ICC_ProfileRGB.java
@@ -0,0 +1,122 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ */
+package java.awt.color;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The ICC_ProfileRGB class represents profiles with RGB color space type and 
+ * contains the redColorantTag, greenColorantTag, blueColorantTag, redTRCTag, 
+ * greenTRCTag, blueTRCTag, and mediaWhitePointTag tags.
+ */
+public class ICC_ProfileRGB extends ICC_Profile {
+    
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = 8505067385152579334L;
+
+    /**
+     * Instantiates a new iC c_ profile rgb.
+     * 
+     * @param profileHandle the profile handle
+     */
+    ICC_ProfileRGB(long profileHandle) {
+        super(profileHandle);
+    }
+
+    /** The Constant REDCOMPONENT indicates the red component. */
+    public static final int REDCOMPONENT = 0;
+
+    /** The Constant GREENCOMPONENT indicates the green component. */
+    public static final int GREENCOMPONENT = 1;
+
+    /** The Constant BLUECOMPONENT indicates the blue component. */
+    public static final int BLUECOMPONENT = 2;
+
+    // awt.15E=Unknown component. Must be REDCOMPONENT, GREENCOMPONENT or BLUECOMPONENT.
+    /** The Constant UNKNOWN_COMPONENT_MSG. */
+    private static final String UNKNOWN_COMPONENT_MSG = Messages
+            .getString("awt.15E"); //$NON-NLS-1$
+
+    @Override
+    public short[] getTRC(int component) {
+        switch (component) {
+            case REDCOMPONENT:
+                return super.getTRC(icSigRedTRCTag);
+            case GREENCOMPONENT:
+                return super.getTRC(icSigGreenTRCTag);
+            case BLUECOMPONENT:
+                return super.getTRC(icSigBlueTRCTag);
+            default:
+        }
+
+        throw new IllegalArgumentException(UNKNOWN_COMPONENT_MSG);
+    }
+
+    @Override
+    public float getGamma(int component) {
+        switch (component) {
+            case REDCOMPONENT:
+                return super.getGamma(icSigRedTRCTag);
+            case GREENCOMPONENT:
+                return super.getGamma(icSigGreenTRCTag);
+            case BLUECOMPONENT:
+                return super.getGamma(icSigBlueTRCTag);
+            default:
+        }
+
+        throw new IllegalArgumentException(UNKNOWN_COMPONENT_MSG);
+    }
+
+    /**
+     * Gets a float matrix which contains the X, Y, and Z components of 
+     * the profile's redColorantTag, greenColorantTag, and blueColorantTag.
+     * 
+     * @return a float matrix which contains the X, Y, and Z components of 
+     * the profile's redColorantTag, greenColorantTag, and blueColorantTag.
+     */
+    public float[][] getMatrix() {
+        float [][] m = new float[3][3]; // The matrix
+
+        float[] redXYZ = getXYZValue(icSigRedColorantTag);
+        float[] greenXYZ = getXYZValue(icSigGreenColorantTag);
+        float[] blueXYZ = getXYZValue(icSigBlueColorantTag);
+
+        m[0][0] = redXYZ[0];
+        m[1][0] = redXYZ[1];
+        m[2][0] = redXYZ[2];
+
+        m[0][1] = greenXYZ[0];
+        m[1][1] = greenXYZ[1];
+        m[2][1] = greenXYZ[2];
+
+        m[0][2] = blueXYZ[0];
+        m[1][2] = blueXYZ[1];
+        m[2][2] = blueXYZ[2];
+
+        return m;
+    }
+
+    @Override
+    public float[] getMediaWhitePoint() {
+        return super.getMediaWhitePoint();
+    }
+}
+
diff --git a/awt/java/awt/color/ICC_ProfileStub.java b/awt/java/awt/color/ICC_ProfileStub.java
new file mode 100644
index 0000000..bc04c8a
--- /dev/null
+++ b/awt/java/awt/color/ICC_ProfileStub.java
@@ -0,0 +1,173 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ */
+
+package java.awt.color;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectStreamException;
+import java.io.OutputStream;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+final class ICC_ProfileStub extends ICC_Profile {
+    private static final long serialVersionUID = 501389760875253507L;
+
+    transient int colorspace;
+
+    public ICC_ProfileStub(int csSpecifier) {
+        switch (csSpecifier) {
+            case ColorSpace.CS_sRGB:
+            case ColorSpace.CS_CIEXYZ:
+            case ColorSpace.CS_LINEAR_RGB:
+            case ColorSpace.CS_PYCC:
+            case ColorSpace.CS_GRAY:
+                break;
+            default:
+                // awt.15D=Invalid colorspace
+                throw new IllegalArgumentException(Messages.getString("awt.15D")); //$NON-NLS-1$
+        }
+        colorspace = csSpecifier;
+    }
+
+    @Override
+    public void write(String fileName) throws IOException {
+        throw new UnsupportedOperationException("Stub cannot perform this operation"); //$NON-NLS-1$
+    }
+
+    /**
+     * Serializable implementation
+     *
+     * @throws ObjectStreamException
+     */
+    private Object writeReplace() throws ObjectStreamException {
+        return loadProfile();
+    }
+
+    @Override
+    public void write(OutputStream s) throws IOException {
+        throw new UnsupportedOperationException("Stub cannot perform this operation"); //$NON-NLS-1$
+    }
+
+    @Override
+    public void setData(int tagSignature, byte[] tagData) {
+        throw new UnsupportedOperationException("Stub cannot perform this operation"); //$NON-NLS-1$
+    }
+
+    @Override
+    public byte[] getData(int tagSignature) {
+        throw new UnsupportedOperationException("Stub cannot perform this operation"); //$NON-NLS-1$
+    }
+
+    @Override
+    public byte[] getData() {
+        throw new UnsupportedOperationException("Stub cannot perform this operation"); //$NON-NLS-1$
+    }
+
+    @Override
+    protected void finalize() {
+    }
+
+    @Override
+    public int getProfileClass() {
+        return CLASS_COLORSPACECONVERSION;
+    }
+
+    @Override
+    public int getPCSType() {
+        throw new UnsupportedOperationException("Stub cannot perform this operation"); //$NON-NLS-1$
+    }
+
+    @Override
+    public int getNumComponents() {
+        switch (colorspace) {
+            case ColorSpace.CS_sRGB:
+            case ColorSpace.CS_CIEXYZ:
+            case ColorSpace.CS_LINEAR_RGB:
+            case ColorSpace.CS_PYCC:
+                return 3;
+            case ColorSpace.CS_GRAY:
+                return 1;
+            default:
+                throw new UnsupportedOperationException("Stub cannot perform this operation"); //$NON-NLS-1$
+        }
+    }
+
+    @Override
+    public int getMinorVersion() {
+        throw new UnsupportedOperationException("Stub cannot perform this operation"); //$NON-NLS-1$
+    }
+
+    @Override
+    public int getMajorVersion() {
+        throw new UnsupportedOperationException("Stub cannot perform this operation"); //$NON-NLS-1$
+    }
+
+    @Override
+    public int getColorSpaceType() {
+        switch (colorspace) {
+            case ColorSpace.CS_sRGB:
+            case ColorSpace.CS_LINEAR_RGB:
+                return ColorSpace.TYPE_RGB;
+            case ColorSpace.CS_CIEXYZ:
+                return ColorSpace.TYPE_XYZ;
+            case ColorSpace.CS_PYCC:
+                return ColorSpace.TYPE_3CLR;
+            case ColorSpace.CS_GRAY:
+                return ColorSpace.TYPE_GRAY;
+            default:
+                throw new UnsupportedOperationException("Stub cannot perform this operation"); //$NON-NLS-1$
+        }
+    }
+
+    public static ICC_Profile getInstance(String fileName) throws IOException {
+        throw new UnsupportedOperationException("Stub cannot perform this operation"); //$NON-NLS-1$
+    }
+
+    public static ICC_Profile getInstance(InputStream s) throws IOException {
+        throw new UnsupportedOperationException("Stub cannot perform this operation"); //$NON-NLS-1$
+    }
+
+    public static ICC_Profile getInstance(byte[] data) {
+        throw new UnsupportedOperationException("Stub cannot perform this operation"); //$NON-NLS-1$
+    }
+
+    public static ICC_Profile getInstance(int cspace) {
+        throw new UnsupportedOperationException("Stub cannot perform this operation"); //$NON-NLS-1$
+    }
+
+    public ICC_Profile loadProfile() {
+        switch (colorspace) {
+            case ColorSpace.CS_sRGB:
+                return ICC_Profile.getInstance(ColorSpace.CS_sRGB);
+            case ColorSpace.CS_GRAY:
+                return ICC_Profile.getInstance(ColorSpace.CS_GRAY);
+            case ColorSpace.CS_CIEXYZ:
+                return ICC_Profile.getInstance(ColorSpace.CS_CIEXYZ);
+            case ColorSpace.CS_LINEAR_RGB:
+                return ICC_Profile.getInstance(ColorSpace.CS_LINEAR_RGB);
+            case ColorSpace.CS_PYCC:
+                return ICC_Profile.getInstance(ColorSpace.CS_PYCC);
+            default:
+                throw new UnsupportedOperationException("Stub cannot perform this operation"); //$NON-NLS-1$
+        }
+    }
+}
\ No newline at end of file
diff --git a/awt/java/awt/color/ProfileDataException.java b/awt/java/awt/color/ProfileDataException.java
new file mode 100644
index 0000000..ca169fe
--- /dev/null
+++ b/awt/java/awt/color/ProfileDataException.java
@@ -0,0 +1,42 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ */
+package java.awt.color;
+
+/**
+ * The ProfileDataException class represents an error which occurs 
+ * while accessing or processing an ICC_Profile object.
+ */
+public class ProfileDataException extends RuntimeException {
+    
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = 7286140888240322498L;
+
+    /**
+     * Instantiates a new profile data exception with detailed message.
+     * 
+     * @param s the detailed message.
+     */
+    public ProfileDataException(String s) {
+        super(s);
+    }
+
+}
+
diff --git a/awt/java/awt/event/AWTEventListener.java b/awt/java/awt/event/AWTEventListener.java
new file mode 100644
index 0000000..f621c9b
--- /dev/null
+++ b/awt/java/awt/event/AWTEventListener.java
@@ -0,0 +1,30 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.awt.AWTEvent;
+import java.util.EventListener;
+
+public interface AWTEventListener extends EventListener {
+
+    public void eventDispatched(AWTEvent event);
+
+}
diff --git a/awt/java/awt/event/AWTEventListenerProxy.java b/awt/java/awt/event/AWTEventListenerProxy.java
new file mode 100644
index 0000000..5ee5e59
--- /dev/null
+++ b/awt/java/awt/event/AWTEventListenerProxy.java
@@ -0,0 +1,52 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.awt.AWTEvent;
+
+import java.util.EventListenerProxy;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+public class AWTEventListenerProxy extends EventListenerProxy implements AWTEventListener {
+
+    private AWTEventListener listener;
+    private long eventMask;
+
+    public AWTEventListenerProxy(long eventMask, AWTEventListener listener) {
+        super(listener);
+
+        // awt.193=Listener can't be zero
+        assert listener != null : Messages.getString("awt.193"); //$NON-NLS-1$
+
+        this.listener = listener;
+        this.eventMask = eventMask;
+    }
+
+    public void eventDispatched(AWTEvent evt) {
+        listener.eventDispatched(evt);
+    }
+
+    public long getEventMask() {
+        return eventMask;
+    }
+
+}
diff --git a/awt/java/awt/event/ActionEvent.java b/awt/java/awt/event/ActionEvent.java
new file mode 100644
index 0000000..c32fc4b
--- /dev/null
+++ b/awt/java/awt/event/ActionEvent.java
@@ -0,0 +1,108 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.awt.AWTEvent;
+
+public class ActionEvent extends AWTEvent {
+
+    private static final long serialVersionUID = -7671078796273832149L;
+
+    public static final int SHIFT_MASK = 1;
+
+    public static final int CTRL_MASK = 2;
+
+    public static final int META_MASK = 4;
+
+    public static final int ALT_MASK = 8;
+
+    public static final int ACTION_FIRST = 1001;
+
+    public static final int ACTION_LAST = 1001;
+
+    public static final int ACTION_PERFORMED = 1001;
+
+    private long when;
+    private int modifiers;
+    private String command;
+
+    public ActionEvent(Object source, int id, String command) {
+        this(source, id, command, 0);
+    }
+
+    public ActionEvent(Object source, int id, String command, int modifiers) {
+        this(source, id, command, 0l, modifiers);
+    }
+
+    public ActionEvent(Object source, int id, String command, long when, int modifiers) {
+        super(source, id);
+
+        this.command = command;
+        this.when = when;
+        this.modifiers = modifiers;
+    }
+
+    public int getModifiers() {
+        return modifiers;
+    }
+
+    public String getActionCommand() {
+        return command;
+    }
+
+    public long getWhen() {
+        return when;
+    }
+
+    @Override
+    public String paramString() {
+        /* The format is based on 1.5 release behavior 
+         * which can be revealed by the following code:
+         * 
+         * ActionEvent e = new ActionEvent(new Component(){},
+         *       ActionEvent.ACTION_PERFORMED, "Command",
+         *       ActionEvent.SHIFT_MASK|ActionEvent.CTRL_MASK|
+         *       ActionEvent.META_MASK|ActionEvent.ALT_MASK);
+         * System.out.println(e);
+         */
+
+        String idString = (id == ACTION_PERFORMED) ? 
+                          "ACTION_PERFORMED" : "unknown type"; //$NON-NLS-1$ //$NON-NLS-2$
+        String modifiersString = ""; //$NON-NLS-1$
+
+        if ((modifiers & SHIFT_MASK) > 0) {
+            modifiersString += "Shift"; //$NON-NLS-1$
+        }
+        if ((modifiers & CTRL_MASK) > 0) {
+            modifiersString += modifiersString.length() == 0 ? "Ctrl" : "+Ctrl"; //$NON-NLS-1$ //$NON-NLS-2$
+        }
+        if ((modifiers & META_MASK) > 0) {
+            modifiersString += modifiersString.length() == 0 ? "Meta" : "+Meta"; //$NON-NLS-1$ //$NON-NLS-2$
+        }
+        if ((modifiers & ALT_MASK) > 0) {
+            modifiersString += modifiersString.length() == 0 ? "Alt" : "+Alt"; //$NON-NLS-1$ //$NON-NLS-2$
+        }
+
+        return (idString + ",cmd=" + command + ",when=" + when +  //$NON-NLS-1$ //$NON-NLS-2$
+                ",modifiers=" + modifiersString); //$NON-NLS-1$
+    }
+
+}
diff --git a/awt/java/awt/event/ActionListener.java b/awt/java/awt/event/ActionListener.java
new file mode 100644
index 0000000..473d2b6
--- /dev/null
+++ b/awt/java/awt/event/ActionListener.java
@@ -0,0 +1,29 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.util.EventListener;
+
+public interface ActionListener extends EventListener {
+
+    public void actionPerformed(ActionEvent e);
+
+}
diff --git a/awt/java/awt/event/AdjustmentEvent.java b/awt/java/awt/event/AdjustmentEvent.java
new file mode 100644
index 0000000..a2b11a8
--- /dev/null
+++ b/awt/java/awt/event/AdjustmentEvent.java
@@ -0,0 +1,117 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.awt.AWTEvent;
+import java.awt.Adjustable;
+
+public class AdjustmentEvent extends AWTEvent {
+
+    private static final long serialVersionUID = 5700290645205279921L;
+
+    public static final int ADJUSTMENT_FIRST = 601;
+
+    public static final int ADJUSTMENT_LAST = 601;
+
+    public static final int ADJUSTMENT_VALUE_CHANGED = 601;
+
+    public static final int UNIT_INCREMENT = 1;
+
+    public static final int UNIT_DECREMENT = 2;
+
+    public static final int BLOCK_DECREMENT = 3;
+
+    public static final int BLOCK_INCREMENT = 4;
+
+    public static final int TRACK = 5;
+
+    private int type;
+    private int value;
+    private boolean isAdjusting;
+
+    public AdjustmentEvent(Adjustable source, int id, int type, int value) {
+        this(source, id, type, value, false);
+    }
+
+    public AdjustmentEvent(Adjustable source, int id, int type, int value, 
+                           boolean isAdjusting) {
+        super(source, id);
+        this.type = type;
+        this.value = value;
+        this.isAdjusting = isAdjusting;
+    }
+
+    public int getValue() {
+        return value;
+    }
+
+    public int getAdjustmentType() {
+        return type;
+    }
+
+    public boolean getValueIsAdjusting() {
+        return isAdjusting;
+    }
+
+    public Adjustable getAdjustable() {
+        return (Adjustable) source;
+    }
+
+    @Override
+    public String paramString() {
+        /* The format is based on 1.5 release behavior 
+         * which can be revealed by the following code:
+         * 
+         * AdjustmentEvent e = new AdjustmentEvent(new Scrollbar(), 
+         *       AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED, 
+         *       AdjustmentEvent.UNIT_INCREMENT, 1);
+         * System.out.println(e);
+         */
+
+        String idString = (id == ADJUSTMENT_VALUE_CHANGED ?
+                "ADJUSTMENT_VALUE_CHANGED" : "unknown type"); //$NON-NLS-1$ //$NON-NLS-2$
+        String adjType = null;
+
+        switch (type) {
+        case UNIT_INCREMENT:
+            adjType = "UNIT_INCREMENT"; //$NON-NLS-1$
+            break;
+        case UNIT_DECREMENT:
+            adjType = "UNIT_DECREMENT"; //$NON-NLS-1$
+            break;
+        case BLOCK_INCREMENT:
+            adjType = "BLOCK_INCREMENT"; //$NON-NLS-1$
+            break;
+        case BLOCK_DECREMENT:
+            adjType = "BLOCK_DECREMENT"; //$NON-NLS-1$
+            break;
+        case TRACK:
+            adjType = "TRACK"; //$NON-NLS-1$
+            break;
+        default:
+            adjType = "unknown type"; //$NON-NLS-1$
+        }
+
+        return (idString + ",adjType=" + adjType + ",value=" + value + //$NON-NLS-1$ //$NON-NLS-2$
+                ",isAdjusting=" + isAdjusting); //$NON-NLS-1$
+    }
+
+}
diff --git a/awt/java/awt/event/AdjustmentListener.java b/awt/java/awt/event/AdjustmentListener.java
new file mode 100644
index 0000000..ef7c378
--- /dev/null
+++ b/awt/java/awt/event/AdjustmentListener.java
@@ -0,0 +1,29 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.util.EventListener;
+
+public interface AdjustmentListener extends EventListener {
+
+    public void adjustmentValueChanged(AdjustmentEvent e);
+
+}
diff --git a/awt/java/awt/event/ComponentAdapter.java b/awt/java/awt/event/ComponentAdapter.java
new file mode 100644
index 0000000..4f0bd90
--- /dev/null
+++ b/awt/java/awt/event/ComponentAdapter.java
@@ -0,0 +1,40 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+public abstract class ComponentAdapter implements ComponentListener {
+
+    public ComponentAdapter() {
+    }
+
+    public void componentHidden(ComponentEvent e) {
+    }
+
+    public void componentMoved(ComponentEvent e) {
+    }
+
+    public void componentResized(ComponentEvent e) {
+    }
+
+    public void componentShown(ComponentEvent e) {
+    }
+
+}
diff --git a/awt/java/awt/event/ComponentEvent.java b/awt/java/awt/event/ComponentEvent.java
new file mode 100644
index 0000000..d0bca54
--- /dev/null
+++ b/awt/java/awt/event/ComponentEvent.java
@@ -0,0 +1,82 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.awt.AWTEvent;
+import java.awt.Component;
+
+public class ComponentEvent extends AWTEvent {
+
+    private static final long serialVersionUID = 8101406823902992965L;
+
+    public static final int COMPONENT_FIRST = 100;
+
+    public static final int COMPONENT_LAST = 103;
+
+    public static final int COMPONENT_MOVED = 100;
+
+    public static final int COMPONENT_RESIZED = 101;
+
+    public static final int COMPONENT_SHOWN = 102;
+
+    public static final int COMPONENT_HIDDEN = 103;
+
+    public ComponentEvent(Component source, int id) {
+        super(source, id);
+    }
+
+    public Component getComponent() {
+        return (Component) source;
+    }
+    
+    @Override
+    public String paramString() {
+        /* The format is based on 1.5 release behavior 
+         * which can be revealed by the following code:
+         * 
+         * ComponentEvent e = new ComponentEvent(new Button("Button"), 
+         *          ComponentEvent.COMPONENT_SHOWN);
+         * System.out.println(e);
+         */
+
+        String idString = null;
+        Component c = getComponent();
+
+        switch (id) {
+        case COMPONENT_MOVED:
+            idString = "COMPONENT_MOVED"; //$NON-NLS-1$
+            break;
+        case COMPONENT_RESIZED:
+            idString = "COMPONENT_RESIZED"; //$NON-NLS-1$
+            break;
+        case COMPONENT_SHOWN:
+            return "COMPONENT_SHOWN"; //$NON-NLS-1$
+        case COMPONENT_HIDDEN:
+            return "COMPONENT_HIDDEN"; //$NON-NLS-1$
+        default:
+            return "unknown type"; //$NON-NLS-1$
+        }
+
+        return (idString + " (" + c.getX() + "," + c.getY() +  //$NON-NLS-1$ //$NON-NLS-2$
+                " " + c.getWidth()+ "x" + c.getHeight() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+    }
+
+}
diff --git a/awt/java/awt/event/ComponentListener.java b/awt/java/awt/event/ComponentListener.java
new file mode 100644
index 0000000..147e9e0
--- /dev/null
+++ b/awt/java/awt/event/ComponentListener.java
@@ -0,0 +1,35 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.util.EventListener;
+
+public interface ComponentListener extends EventListener {
+
+    public void componentHidden(ComponentEvent e);
+
+    public void componentMoved(ComponentEvent e);
+
+    public void componentResized(ComponentEvent e);
+
+    public void componentShown(ComponentEvent e);
+
+}
diff --git a/awt/java/awt/event/ContainerAdapter.java b/awt/java/awt/event/ContainerAdapter.java
new file mode 100644
index 0000000..12dc3de
--- /dev/null
+++ b/awt/java/awt/event/ContainerAdapter.java
@@ -0,0 +1,34 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+public abstract class ContainerAdapter implements ContainerListener {
+
+    public ContainerAdapter() {
+    }
+
+    public void componentAdded(ContainerEvent e) {
+    }
+
+    public void componentRemoved(ContainerEvent e) {
+    }
+
+}
diff --git a/awt/java/awt/event/ContainerEvent.java b/awt/java/awt/event/ContainerEvent.java
new file mode 100644
index 0000000..1a1055c
--- /dev/null
+++ b/awt/java/awt/event/ContainerEvent.java
@@ -0,0 +1,83 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.awt.Component;
+//???AWT: import java.awt.Container;
+
+public class ContainerEvent extends ComponentEvent {
+
+    private static final long serialVersionUID = -4114942250539772041L;
+
+    public static final int CONTAINER_FIRST = 300;
+
+    public static final int CONTAINER_LAST = 301;
+
+    public static final int COMPONENT_ADDED = 300;
+
+    public static final int COMPONENT_REMOVED = 301;
+
+    private Component child;
+
+    public ContainerEvent(Component src, int id, Component child) {
+        super(src, id);
+        this.child = child;
+    }
+
+    public Component getChild() {
+        return child;
+    }
+
+    //???AWT
+    /*
+    public Container getContainer() {
+        return (Container) source;
+    }
+    */
+
+    @Override
+    public String paramString() {
+        /* The format is based on 1.5 release behavior 
+         * which can be revealed by the following code:
+         * 
+         * ContainerEvent e = new ContainerEvent(new Panel(),
+         *          ContainerEvent.COMPONENT_ADDED,
+         *          new Button("Button"));
+         * System.out.println(e);
+         */
+
+        String idString = null;
+
+        switch (id) {
+        case COMPONENT_ADDED:
+            idString = "COMPONENT_ADDED"; //$NON-NLS-1$
+            break;
+        case COMPONENT_REMOVED:
+            idString = "COMPONENT_REMOVED"; //$NON-NLS-1$
+            break;
+        default:
+            idString = "unknown type"; //$NON-NLS-1$
+        }
+
+        return (idString + ",child=" + child.getName()); //$NON-NLS-1$
+    }
+
+}
diff --git a/awt/java/awt/event/ContainerListener.java b/awt/java/awt/event/ContainerListener.java
new file mode 100644
index 0000000..bf47664
--- /dev/null
+++ b/awt/java/awt/event/ContainerListener.java
@@ -0,0 +1,31 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.util.EventListener;
+
+public interface ContainerListener extends EventListener {
+
+    public void componentAdded(ContainerEvent e);
+
+    public void componentRemoved(ContainerEvent e);
+
+}
diff --git a/awt/java/awt/event/FocusAdapter.java b/awt/java/awt/event/FocusAdapter.java
new file mode 100644
index 0000000..3489e11
--- /dev/null
+++ b/awt/java/awt/event/FocusAdapter.java
@@ -0,0 +1,34 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+public abstract class FocusAdapter implements FocusListener {
+
+    public FocusAdapter() {
+    }
+
+    public void focusGained(FocusEvent e) {
+    }
+
+    public void focusLost(FocusEvent e) {
+    }
+
+}
diff --git a/awt/java/awt/event/FocusEvent.java b/awt/java/awt/event/FocusEvent.java
new file mode 100644
index 0000000..1db5263
--- /dev/null
+++ b/awt/java/awt/event/FocusEvent.java
@@ -0,0 +1,90 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.awt.Component;
+
+public class FocusEvent extends ComponentEvent {
+
+    private static final long serialVersionUID = 523753786457416396L;
+
+    public static final int FOCUS_FIRST = 1004;
+
+    public static final int FOCUS_LAST = 1005;
+
+    public static final int FOCUS_GAINED = 1004;
+
+    public static final int FOCUS_LOST = 1005;
+
+    private boolean temporary;
+    private Component opposite;
+
+    public FocusEvent(Component source, int id) {
+        this(source, id, false);
+    }
+
+    public FocusEvent(Component source, int id, boolean temporary) {
+        this(source, id, temporary, null);
+    }
+
+    public FocusEvent(Component source, int id, boolean temporary, Component opposite) {
+        super(source, id);
+        this.temporary = temporary;
+        this.opposite = opposite;
+    }
+
+    public Component getOppositeComponent() {
+        return opposite;
+    }
+
+    public boolean isTemporary() {
+        return temporary;
+    }
+
+    @Override
+    public String paramString() {
+        /* The format is based on 1.5 release behavior 
+         * which can be revealed by the following code:
+         * 
+         * FocusEvent e = new FocusEvent(new Button("Button0"),
+         *       FocusEvent.FOCUS_GAINED, false, new Button("Button1"));
+         * System.out.println(e);
+         */
+
+        String idString = null;
+
+        switch (id) {
+        case FOCUS_GAINED:
+            idString = "FOCUS_GAINED"; //$NON-NLS-1$
+            break;
+        case FOCUS_LOST:
+            idString = "FOCUS_LOST"; //$NON-NLS-1$
+            break;
+        default:
+            idString = "unknown type"; //$NON-NLS-1$
+        }
+
+        return (idString +
+                (temporary ? ",temporary" : ",permanent") + //$NON-NLS-1$ //$NON-NLS-2$
+                ",opposite=" + opposite); //$NON-NLS-1$
+    }
+
+}
diff --git a/awt/java/awt/event/FocusListener.java b/awt/java/awt/event/FocusListener.java
new file mode 100644
index 0000000..ee98d90
--- /dev/null
+++ b/awt/java/awt/event/FocusListener.java
@@ -0,0 +1,31 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.util.EventListener;
+
+public interface FocusListener extends EventListener {
+
+    public void focusGained(FocusEvent e);
+
+    public void focusLost(FocusEvent e);
+
+}
diff --git a/awt/java/awt/event/HierarchyBoundsAdapter.java b/awt/java/awt/event/HierarchyBoundsAdapter.java
new file mode 100644
index 0000000..24e3d9d
--- /dev/null
+++ b/awt/java/awt/event/HierarchyBoundsAdapter.java
@@ -0,0 +1,34 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+public abstract class HierarchyBoundsAdapter implements HierarchyBoundsListener {
+
+    public HierarchyBoundsAdapter() {
+    }
+
+    public void ancestorMoved(HierarchyEvent e) {
+    }
+
+    public void ancestorResized(HierarchyEvent e) {
+    }
+
+}
diff --git a/awt/java/awt/event/HierarchyBoundsListener.java b/awt/java/awt/event/HierarchyBoundsListener.java
new file mode 100644
index 0000000..4288f52
--- /dev/null
+++ b/awt/java/awt/event/HierarchyBoundsListener.java
@@ -0,0 +1,31 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.util.EventListener;
+
+public interface HierarchyBoundsListener extends EventListener {
+
+    public void ancestorMoved(HierarchyEvent e);
+
+    public void ancestorResized(HierarchyEvent e);
+
+}
diff --git a/awt/java/awt/event/HierarchyEvent.java b/awt/java/awt/event/HierarchyEvent.java
new file mode 100644
index 0000000..1881667
--- /dev/null
+++ b/awt/java/awt/event/HierarchyEvent.java
@@ -0,0 +1,148 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.awt.AWTEvent;
+import java.awt.Component;
+//???AWT: import java.awt.Container;
+
+public class HierarchyEvent extends AWTEvent {
+
+    private static final long serialVersionUID = -5337576970038043990L;
+
+    public static final int HIERARCHY_FIRST = 1400;
+
+    public static final int HIERARCHY_CHANGED = 1400;
+
+    public static final int ANCESTOR_MOVED = 1401;
+
+    public static final int ANCESTOR_RESIZED = 1402;
+
+    public static final int HIERARCHY_LAST = 1402;
+
+    public static final int PARENT_CHANGED = 1;
+
+    public static final int DISPLAYABILITY_CHANGED = 2;
+
+    public static final int SHOWING_CHANGED = 4;
+
+    //???AWT: private Container changedParent;
+    private Component changed;
+    private long changeFlag;
+
+    //???AWT
+    /*
+    public HierarchyEvent(Component source, int id, Component changed, 
+                          Container changedParent) {
+        this(source, id, changed, changedParent, 0l);
+    }
+    */
+
+    //???AWT
+    /*
+    public HierarchyEvent(Component source, int id, Component changed,
+            Container changedParent, long changeFlags) {
+        super(source, id);
+
+        this.changed = changed;
+        this.changedParent = changedParent;
+        this.changeFlag = changeFlags;
+    }
+    */
+    //???AWT: Fake constructor, should be as above.
+    public HierarchyEvent(Component source, int id, Component changed,
+            Object changedParent, long changeFlags) {
+        super(source, id);
+
+//        this.changed = changed;
+//        this.changedParent = changedParent;
+//        this.changeFlag = changeFlags;
+    }
+    
+    public Component getComponent() {
+        return (Component) source;
+    }
+
+    public long getChangeFlags() {
+        return changeFlag;
+    }
+
+    public Component getChanged() {
+        return changed;
+    }
+
+    //???AWT
+    /*
+    public Container getChangedParent() {
+        return changedParent;
+
+    }
+    */
+
+    @Override
+    public String paramString() {
+        /* The format is based on 1.5 release behavior 
+         * which can be revealed by the following code:
+         * 
+         * HierarchyEvent e = new HierarchyEvent(new Button("Button"),
+         *          HierarchyEvent.HIERARCHY_CHANGED,
+         *          new Panel(), new Container());
+         * System.out.println(e);
+         */
+        String paramString = null;
+
+        switch (id) {
+        case HIERARCHY_CHANGED:
+            paramString = "HIERARCHY_CHANGED"; //$NON-NLS-1$
+            break;
+        case ANCESTOR_MOVED:
+            paramString = "ANCESTOR_MOVED"; //$NON-NLS-1$
+            break;
+        case ANCESTOR_RESIZED:
+            paramString = "ANCESTOR_RESIZED"; //$NON-NLS-1$
+            break;
+        default:
+            paramString = "unknown type"; //$NON-NLS-1$
+        }
+
+        paramString += " ("; //$NON-NLS-1$
+
+        if (id == HIERARCHY_CHANGED) {
+            if ((changeFlag & PARENT_CHANGED) > 0) {
+                paramString += "PARENT_CHANGED,"; //$NON-NLS-1$
+            }
+            if ((changeFlag & DISPLAYABILITY_CHANGED) > 0) {
+                paramString += "DISPLAYABILITY_CHANGED,"; //$NON-NLS-1$
+            }
+            if ((changeFlag & SHOWING_CHANGED) > 0) {
+                paramString += "SHOWING_CHANGED,"; //$NON-NLS-1$
+            }
+        }
+
+        //???AWT
+        /*
+        return paramString + "changed=" + changed +  //$NON-NLS-1$
+                ",changedParent=" + changedParent + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+        */
+        return paramString;
+    }
+
+}
diff --git a/awt/java/awt/event/HierarchyListener.java b/awt/java/awt/event/HierarchyListener.java
new file mode 100644
index 0000000..e01ba11
--- /dev/null
+++ b/awt/java/awt/event/HierarchyListener.java
@@ -0,0 +1,29 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.util.EventListener;
+
+public interface HierarchyListener extends EventListener {
+
+    public void hierarchyChanged(HierarchyEvent e);
+
+}
diff --git a/awt/java/awt/event/InputEvent.java b/awt/java/awt/event/InputEvent.java
new file mode 100644
index 0000000..c98382d
--- /dev/null
+++ b/awt/java/awt/event/InputEvent.java
@@ -0,0 +1,184 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.awt.Component;
+
+public abstract class InputEvent extends ComponentEvent {
+
+    private static final long serialVersionUID = -2482525981698309786L;
+
+    public static final int SHIFT_MASK = 1;
+
+    public static final int CTRL_MASK = 2;
+
+    public static final int META_MASK = 4;
+
+    public static final int ALT_MASK = 8;
+
+    public static final int ALT_GRAPH_MASK = 32;
+
+    public static final int BUTTON1_MASK = 16;
+
+    public static final int BUTTON2_MASK = 8;
+
+    public static final int BUTTON3_MASK = 4;
+
+    public static final int SHIFT_DOWN_MASK = 64;
+
+    public static final int CTRL_DOWN_MASK = 128;
+
+    public static final int META_DOWN_MASK = 256;
+
+    public static final int ALT_DOWN_MASK = 512;
+
+    public static final int BUTTON1_DOWN_MASK = 1024;
+
+    public static final int BUTTON2_DOWN_MASK = 2048;
+
+    public static final int BUTTON3_DOWN_MASK = 4096;
+
+    public static final int ALT_GRAPH_DOWN_MASK = 8192;
+
+    private static final int DOWN_MASKS = SHIFT_DOWN_MASK | CTRL_DOWN_MASK |
+            META_DOWN_MASK | ALT_DOWN_MASK | BUTTON1_DOWN_MASK |
+            BUTTON2_DOWN_MASK | BUTTON3_DOWN_MASK | ALT_GRAPH_DOWN_MASK;
+
+    private long when;
+    private int modifiersEx;
+
+    public static String getModifiersExText(int modifiers/*Ex*/) {
+        return MouseEvent.addMouseModifiersExText(
+                KeyEvent.getKeyModifiersExText(modifiers), modifiers);
+    }
+
+    static int extractExFlags(int modifiers) {
+        int exFlags = modifiers & DOWN_MASKS;
+
+        if ((modifiers & SHIFT_MASK) != 0) {
+            exFlags |= SHIFT_DOWN_MASK;
+        }
+        if ((modifiers & CTRL_MASK) != 0) {
+            exFlags |= CTRL_DOWN_MASK;
+        }
+        if ((modifiers & META_MASK) != 0) {
+            exFlags |= META_DOWN_MASK;
+        }
+        if ((modifiers & ALT_MASK) != 0) {
+            exFlags |= ALT_DOWN_MASK;
+        }
+        if ((modifiers & ALT_GRAPH_MASK) != 0) {
+            exFlags |= ALT_GRAPH_DOWN_MASK;
+        }
+        if ((modifiers & BUTTON1_MASK) != 0) {
+            exFlags |= BUTTON1_DOWN_MASK;
+        }
+        if ((modifiers & BUTTON2_MASK) != 0) {
+            exFlags |= BUTTON2_DOWN_MASK;
+        }
+        if ((modifiers & BUTTON3_MASK) != 0) {
+            exFlags |= BUTTON3_DOWN_MASK;
+        }
+
+        return exFlags;
+    }
+
+    InputEvent(Component source, int id, long when, int modifiers) {
+        super(source, id);
+
+        this.when = when;
+        modifiersEx = extractExFlags(modifiers);
+    }
+
+    public int getModifiers() {
+        int modifiers = 0;
+
+        if ((modifiersEx & SHIFT_DOWN_MASK) != 0) {
+            modifiers |= SHIFT_MASK;
+        }
+        if ((modifiersEx & CTRL_DOWN_MASK) != 0) {
+            modifiers |= CTRL_MASK;
+        }
+        if ((modifiersEx & META_DOWN_MASK) != 0) {
+            modifiers |= META_MASK;
+        }
+        if ((modifiersEx & ALT_DOWN_MASK) != 0) {
+            modifiers |= ALT_MASK;
+        }
+        if ((modifiersEx & ALT_GRAPH_DOWN_MASK) != 0) {
+            modifiers |= ALT_GRAPH_MASK;
+        }
+        if ((modifiersEx & BUTTON1_DOWN_MASK) != 0) {
+            modifiers |= BUTTON1_MASK;
+        }
+        if ((modifiersEx & BUTTON2_DOWN_MASK) != 0) {
+            modifiers |= BUTTON2_MASK;
+        }
+        if ((modifiersEx & BUTTON3_DOWN_MASK) != 0) {
+            modifiers |= BUTTON3_MASK;
+        }
+
+        return modifiers;
+    }
+
+    public int getModifiersEx() {
+        return modifiersEx;
+    }
+
+    void setModifiers(int modifiers) {
+        modifiersEx = extractExFlags(modifiers);
+    }
+
+    public boolean isAltDown() {
+        return ((modifiersEx & ALT_DOWN_MASK) != 0);
+    }
+
+    public boolean isAltGraphDown() {
+        return ((modifiersEx & ALT_GRAPH_DOWN_MASK) != 0);
+    }
+
+    public boolean isControlDown() {
+        return ((modifiersEx & CTRL_DOWN_MASK) != 0);
+    }
+
+    public boolean isMetaDown() {
+        return ((modifiersEx & META_DOWN_MASK) != 0);
+    }
+
+    public boolean isShiftDown() {
+        return ((modifiersEx & SHIFT_DOWN_MASK) != 0);
+    }
+
+    public long getWhen() {
+        return when;
+    }
+
+    @Override
+    public void consume() {
+        super.consume();
+    }
+
+    @Override
+    public boolean isConsumed() {
+        return super.isConsumed();
+    }
+
+}
diff --git a/awt/java/awt/event/InputMethodEvent.java b/awt/java/awt/event/InputMethodEvent.java
new file mode 100644
index 0000000..a5cac4e
--- /dev/null
+++ b/awt/java/awt/event/InputMethodEvent.java
@@ -0,0 +1,150 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.awt.AWTEvent;
+import java.awt.Component;
+import java.awt.font.TextHitInfo;
+import java.text.AttributedCharacterIterator;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+public class InputMethodEvent extends AWTEvent {
+
+    private static final long serialVersionUID = 4727190874778922661L;
+
+    public static final int INPUT_METHOD_FIRST = 1100;
+
+    public static final int INPUT_METHOD_TEXT_CHANGED = 1100;
+
+    public static final int CARET_POSITION_CHANGED = 1101;
+
+    public static final int INPUT_METHOD_LAST = 1101;
+
+    private AttributedCharacterIterator text;
+    private TextHitInfo visiblePosition;
+    private TextHitInfo caret;
+    private int committedCharacterCount;
+    private long when;
+
+    public InputMethodEvent(Component src, int id,
+                            TextHitInfo caret, 
+                            TextHitInfo visiblePos) {
+        this(src, id, null, 0, caret, visiblePos);
+    }
+
+    public InputMethodEvent(Component src, int id, 
+                            AttributedCharacterIterator text,
+                            int commitedCharCount,
+                            TextHitInfo caret, 
+                            TextHitInfo visiblePos) {
+        this(src, id, 0l, text, commitedCharCount, caret, visiblePos);
+    }
+
+    public InputMethodEvent(Component src, int id, long when,
+                            AttributedCharacterIterator text, 
+                            int committedCharacterCount,
+                            TextHitInfo caret,
+                            TextHitInfo visiblePos) {
+        super(src, id);
+
+        if ((id < INPUT_METHOD_FIRST) || (id > INPUT_METHOD_LAST)) {
+            // awt.18E=Wrong event id
+            throw new IllegalArgumentException(Messages.getString("awt.18E")); //$NON-NLS-1$
+        }
+        if ((id == CARET_POSITION_CHANGED) && (text != null)) {
+            // awt.18F=Text must be null for CARET_POSITION_CHANGED
+            throw new IllegalArgumentException(Messages.getString("awt.18F")); //$NON-NLS-1$
+        }
+        if ((text != null) &&
+                ((committedCharacterCount < 0) ||
+                 (committedCharacterCount > 
+                        (text.getEndIndex() - text.getBeginIndex())))) {
+            // awt.190=Wrong committedCharacterCount
+            throw new IllegalArgumentException(Messages.getString("awt.190")); //$NON-NLS-1$
+        }
+
+        this.when = when;
+        this.text = text;
+        this.caret = caret;
+        this.visiblePosition = visiblePos;
+        this.committedCharacterCount = committedCharacterCount;
+    }
+
+    public TextHitInfo getCaret() {
+        return caret;
+    }
+
+    public int getCommittedCharacterCount() {
+        return committedCharacterCount;
+    }
+
+    public AttributedCharacterIterator getText() {
+        return text;
+    }
+
+    public TextHitInfo getVisiblePosition() {
+        return visiblePosition;
+    }
+
+    public long getWhen() {
+        return when;
+    }
+
+    @Override
+    public void consume() {
+        super.consume();
+    }
+
+    @Override
+    public boolean isConsumed() {
+        return super.isConsumed();
+    }
+
+    @Override
+    public String paramString() {
+        /* The format is based on 1.5 release behavior 
+         * which can be revealed by the following code:
+         * 
+         * InputMethodEvent e = new InputMethodEvent(new Component(){},
+         *          InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,
+         *          TextHitInfo.leading(1), TextHitInfo.trailing(2));
+         * System.out.println(e);
+         */
+        String typeString = null;
+
+        switch (id) {
+        case INPUT_METHOD_TEXT_CHANGED:
+            typeString = "INPUT_METHOD_TEXT_CHANGED"; //$NON-NLS-1$
+            break;
+        case CARET_POSITION_CHANGED:
+            typeString = "CARET_POSITION_CHANGED"; //$NON-NLS-1$
+            break;
+        default:
+            typeString = "unknown type"; //$NON-NLS-1$
+        }
+
+        return typeString + ",text=" + text +  //$NON-NLS-1$
+                ",commitedCharCount=" + committedCharacterCount + //$NON-NLS-1$
+                ",caret=" + caret + ",visiblePosition=" + visiblePosition; //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+}
diff --git a/awt/java/awt/event/InputMethodListener.java b/awt/java/awt/event/InputMethodListener.java
new file mode 100644
index 0000000..0ab6918
--- /dev/null
+++ b/awt/java/awt/event/InputMethodListener.java
@@ -0,0 +1,31 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.util.EventListener;
+
+public interface InputMethodListener extends EventListener {
+
+    public void caretPositionChanged(InputMethodEvent e);
+
+    public void inputMethodTextChanged(InputMethodEvent e);
+
+}
diff --git a/awt/java/awt/event/InvocationEvent.java b/awt/java/awt/event/InvocationEvent.java
new file mode 100644
index 0000000..59346ed
--- /dev/null
+++ b/awt/java/awt/event/InvocationEvent.java
@@ -0,0 +1,132 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.awt.AWTEvent;
+import java.awt.ActiveEvent;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+public class InvocationEvent extends AWTEvent implements ActiveEvent {
+
+    private static final long serialVersionUID = 436056344909459450L;
+
+    public static final int INVOCATION_FIRST = 1200;
+
+    public static final int INVOCATION_DEFAULT = 1200;
+
+    public static final int INVOCATION_LAST = 1200;
+
+    protected Runnable runnable;
+
+    protected Object notifier;
+
+    protected boolean catchExceptions;
+
+    private long when;
+    private Throwable throwable;
+
+    public InvocationEvent(Object source, Runnable runnable) {
+        this(source, runnable, null, false);
+    }
+
+    public InvocationEvent(Object source, Runnable runnable, 
+                           Object notifier, boolean catchExceptions) {
+        this(source, INVOCATION_DEFAULT, runnable, notifier, catchExceptions);
+    }
+
+    protected InvocationEvent(Object source, int id, Runnable runnable,
+            Object notifier, boolean catchExceptions)
+    {
+        super(source, id);
+
+        // awt.18C=Cannot invoke null runnable
+        assert runnable != null : Messages.getString("awt.18C"); //$NON-NLS-1$
+
+        if (source == null) {
+            // awt.18D=Source is null
+            throw new IllegalArgumentException(Messages.getString("awt.18D")); //$NON-NLS-1$
+        }
+        this.runnable = runnable;
+        this.notifier = notifier;
+        this.catchExceptions = catchExceptions;
+
+        throwable = null;
+        when = System.currentTimeMillis();
+    }
+
+    public void dispatch() {
+        if (!catchExceptions) {
+            runAndNotify();
+        } else {
+            try {
+                runAndNotify();
+            } catch (Throwable t) {
+                throwable = t;
+            }
+        }
+    }
+
+    private void runAndNotify() {
+        if (notifier != null) {
+            synchronized(notifier) {
+                try {
+                    runnable.run();
+                } finally {
+                    notifier.notifyAll();
+                }
+            }
+        } else {
+            runnable.run();
+        }
+    }
+
+    public Exception getException() {
+        return (throwable != null && throwable instanceof Exception) ?
+                (Exception)throwable : null;
+    }
+
+    public Throwable getThrowable() {
+        return throwable;
+    }
+
+    public long getWhen() {
+        return when;
+    }
+
+    @Override
+    public String paramString() {
+        /* The format is based on 1.5 release behavior 
+         * which can be revealed by the following code:
+         * 
+         * InvocationEvent e = new InvocationEvent(new Component(){},
+         *       new Runnable() { public void run(){} });
+         * System.out.println(e);
+         */
+
+        return ((id == INVOCATION_DEFAULT ? "INVOCATION_DEFAULT" : "unknown type") + //$NON-NLS-1$ //$NON-NLS-2$
+                ",runnable=" + runnable + //$NON-NLS-1$
+                ",notifier=" + notifier + //$NON-NLS-1$
+                ",catchExceptions=" + catchExceptions + //$NON-NLS-1$
+                ",when=" + when); //$NON-NLS-1$
+    }
+
+}
diff --git a/awt/java/awt/event/ItemEvent.java b/awt/java/awt/event/ItemEvent.java
new file mode 100644
index 0000000..842da14
--- /dev/null
+++ b/awt/java/awt/event/ItemEvent.java
@@ -0,0 +1,90 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.awt.AWTEvent;
+import java.awt.ItemSelectable;
+
+public class ItemEvent extends AWTEvent {
+
+    private static final long serialVersionUID = -608708132447206933L;
+
+    public static final int ITEM_FIRST = 701;
+
+    public static final int ITEM_LAST = 701;
+
+    public static final int ITEM_STATE_CHANGED = 701;
+
+    public static final int SELECTED = 1;
+
+    public static final int DESELECTED = 2;
+
+    private Object item;
+    private int stateChange;
+
+    public ItemEvent(ItemSelectable source, int id, Object item, int stateChange) {
+        super(source, id);
+
+        this.item = item;
+        this.stateChange = stateChange;
+    }
+
+    public Object getItem() {
+        return item;
+    }
+
+    public int getStateChange() {
+        return stateChange;
+    }
+
+    public ItemSelectable getItemSelectable() {
+        return (ItemSelectable) source;
+    }
+
+    @Override
+    public String paramString() {
+        /* The format is based on 1.5 release behavior 
+         * which can be revealed by the following code:
+         * 
+         * Checkbox c = new Checkbox("Checkbox", true);
+         * ItemEvent e = new ItemEvent(c, ItemEvent.ITEM_STATE_CHANGED, 
+         *                             c, ItemEvent.SELECTED);
+         * System.out.println(e);
+         */
+
+        String stateString = null;
+
+        switch (stateChange) {
+        case SELECTED:
+            stateString = "SELECTED"; //$NON-NLS-1$
+            break;
+        case DESELECTED:
+            stateString = "DESELECTED"; //$NON-NLS-1$
+            break;
+        default:
+            stateString = "unknown type"; //$NON-NLS-1$
+        }
+
+        return ((id == ITEM_STATE_CHANGED ? "ITEM_STATE_CHANGED" : "unknown type") + //$NON-NLS-1$ //$NON-NLS-2$
+                ",item=" + item + ",stateChange=" + stateString); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+}
diff --git a/awt/java/awt/event/ItemListener.java b/awt/java/awt/event/ItemListener.java
new file mode 100644
index 0000000..33633be
--- /dev/null
+++ b/awt/java/awt/event/ItemListener.java
@@ -0,0 +1,29 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.util.EventListener;
+
+public interface ItemListener extends EventListener {
+
+    public void itemStateChanged(ItemEvent e);
+
+}
diff --git a/awt/java/awt/event/KeyAdapter.java b/awt/java/awt/event/KeyAdapter.java
new file mode 100644
index 0000000..423b5c9
--- /dev/null
+++ b/awt/java/awt/event/KeyAdapter.java
@@ -0,0 +1,37 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+public abstract class KeyAdapter implements KeyListener {
+
+    public KeyAdapter() {
+    }
+
+    public void keyPressed(KeyEvent e) {
+    }
+
+    public void keyReleased(KeyEvent e) {
+    }
+
+    public void keyTyped(KeyEvent e) {
+    }
+
+}
diff --git a/awt/java/awt/event/KeyEvent.java b/awt/java/awt/event/KeyEvent.java
new file mode 100644
index 0000000..056c64c
--- /dev/null
+++ b/awt/java/awt/event/KeyEvent.java
@@ -0,0 +1,681 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.awt.Component;
+import java.awt.Toolkit;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+public class KeyEvent extends InputEvent {
+
+    private static final long serialVersionUID = -2352130953028126954L;
+
+    public static final int KEY_FIRST = 400;
+
+    public static final int KEY_LAST = 402;
+
+    public static final int KEY_TYPED = 400;
+
+    public static final int KEY_PRESSED = 401;
+
+    public static final int KEY_RELEASED = 402;
+
+    public static final int VK_ENTER = 10;
+
+    public static final int VK_BACK_SPACE = 8;
+
+    public static final int VK_TAB = 9;
+
+    public static final int VK_CANCEL = 3;
+
+    public static final int VK_CLEAR = 12;
+
+    public static final int VK_SHIFT = 16;
+
+    public static final int VK_CONTROL = 17;
+
+    public static final int VK_ALT = 18;
+
+    public static final int VK_PAUSE = 19;
+
+    public static final int VK_CAPS_LOCK = 20;
+
+    public static final int VK_ESCAPE = 27;
+
+    public static final int VK_SPACE = 32;
+
+    public static final int VK_PAGE_UP = 33;
+
+    public static final int VK_PAGE_DOWN = 34;
+
+    public static final int VK_END = 35;
+
+    public static final int VK_HOME = 36;
+
+    public static final int VK_LEFT = 37;
+
+    public static final int VK_UP = 38;
+
+    public static final int VK_RIGHT = 39;
+
+    public static final int VK_DOWN = 40;
+
+    public static final int VK_COMMA = 44;
+
+    public static final int VK_MINUS = 45;
+
+    public static final int VK_PERIOD = 46;
+
+    public static final int VK_SLASH = 47;
+
+    public static final int VK_0 = 48;
+
+    public static final int VK_1 = 49;
+
+    public static final int VK_2 = 50;
+
+    public static final int VK_3 = 51;
+
+    public static final int VK_4 = 52;
+
+    public static final int VK_5 = 53;
+
+    public static final int VK_6 = 54;
+
+    public static final int VK_7 = 55;
+
+    public static final int VK_8 = 56;
+
+    public static final int VK_9 = 57;
+
+    public static final int VK_SEMICOLON = 59;
+
+    public static final int VK_EQUALS = 61;
+
+    public static final int VK_A = 65;
+
+    public static final int VK_B = 66;
+
+    public static final int VK_C = 67;
+
+    public static final int VK_D = 68;
+
+    public static final int VK_E = 69;
+
+    public static final int VK_F = 70;
+
+    public static final int VK_G = 71;
+
+    public static final int VK_H = 72;
+
+    public static final int VK_I = 73;
+
+    public static final int VK_J = 74;
+
+    public static final int VK_K = 75;
+
+    public static final int VK_L = 76;
+
+    public static final int VK_M = 77;
+
+    public static final int VK_N = 78;
+
+    public static final int VK_O = 79;
+
+    public static final int VK_P = 80;
+
+    public static final int VK_Q = 81;
+
+    public static final int VK_R = 82;
+
+    public static final int VK_S = 83;
+
+    public static final int VK_T = 84;
+
+    public static final int VK_U = 85;
+
+    public static final int VK_V = 86;
+
+    public static final int VK_W = 87;
+
+    public static final int VK_X = 88;
+
+    public static final int VK_Y = 89;
+
+    public static final int VK_Z = 90;
+
+    public static final int VK_OPEN_BRACKET = 91;
+
+    public static final int VK_BACK_SLASH = 92;
+
+    public static final int VK_CLOSE_BRACKET = 93;
+
+    public static final int VK_NUMPAD0 = 96;
+
+    public static final int VK_NUMPAD1 = 97;
+
+    public static final int VK_NUMPAD2 = 98;
+
+    public static final int VK_NUMPAD3 = 99;
+
+    public static final int VK_NUMPAD4 = 100;
+
+    public static final int VK_NUMPAD5 = 101;
+
+    public static final int VK_NUMPAD6 = 102;
+
+    public static final int VK_NUMPAD7 = 103;
+
+    public static final int VK_NUMPAD8 = 104;
+
+    public static final int VK_NUMPAD9 = 105;
+
+    public static final int VK_MULTIPLY = 106;
+
+    public static final int VK_ADD = 107;
+
+    public static final int VK_SEPARATER = 108;
+
+    public static final int VK_SEPARATOR = 108;
+
+    public static final int VK_SUBTRACT = 109;
+
+    public static final int VK_DECIMAL = 110;
+
+    public static final int VK_DIVIDE = 111;
+
+    public static final int VK_DELETE = 127;
+
+    public static final int VK_NUM_LOCK = 144;
+
+    public static final int VK_SCROLL_LOCK = 145;
+
+    public static final int VK_F1 = 112;
+
+    public static final int VK_F2 = 113;
+
+    public static final int VK_F3 = 114;
+
+    public static final int VK_F4 = 115;
+
+    public static final int VK_F5 = 116;
+
+    public static final int VK_F6 = 117;
+
+    public static final int VK_F7 = 118;
+
+    public static final int VK_F8 = 119;
+
+    public static final int VK_F9 = 120;
+
+    public static final int VK_F10 = 121;
+
+    public static final int VK_F11 = 122;
+
+    public static final int VK_F12 = 123;
+
+    public static final int VK_F13 = 61440;
+
+    public static final int VK_F14 = 61441;
+
+    public static final int VK_F15 = 61442;
+
+    public static final int VK_F16 = 61443;
+
+    public static final int VK_F17 = 61444;
+
+    public static final int VK_F18 = 61445;
+
+    public static final int VK_F19 = 61446;
+
+    public static final int VK_F20 = 61447;
+
+    public static final int VK_F21 = 61448;
+
+    public static final int VK_F22 = 61449;
+
+    public static final int VK_F23 = 61450;
+
+    public static final int VK_F24 = 61451;
+
+    public static final int VK_PRINTSCREEN = 154;
+
+    public static final int VK_INSERT = 155;
+
+    public static final int VK_HELP = 156;
+
+    public static final int VK_META = 157;
+
+    public static final int VK_BACK_QUOTE = 192;
+
+    public static final int VK_QUOTE = 222;
+
+    public static final int VK_KP_UP = 224;
+
+    public static final int VK_KP_DOWN = 225;
+
+    public static final int VK_KP_LEFT = 226;
+
+    public static final int VK_KP_RIGHT = 227;
+
+    public static final int VK_DEAD_GRAVE = 128;
+
+    public static final int VK_DEAD_ACUTE = 129;
+
+    public static final int VK_DEAD_CIRCUMFLEX = 130;
+
+    public static final int VK_DEAD_TILDE = 131;
+
+    public static final int VK_DEAD_MACRON = 132;
+
+    public static final int VK_DEAD_BREVE = 133;
+
+    public static final int VK_DEAD_ABOVEDOT = 134;
+
+    public static final int VK_DEAD_DIAERESIS = 135;
+
+    public static final int VK_DEAD_ABOVERING = 136;
+
+    public static final int VK_DEAD_DOUBLEACUTE = 137;
+
+    public static final int VK_DEAD_CARON = 138;
+
+    public static final int VK_DEAD_CEDILLA = 139;
+
+    public static final int VK_DEAD_OGONEK = 140;
+
+    public static final int VK_DEAD_IOTA = 141;
+
+    public static final int VK_DEAD_VOICED_SOUND = 142;
+
+    public static final int VK_DEAD_SEMIVOICED_SOUND = 143;
+
+    public static final int VK_AMPERSAND = 150;
+
+    public static final int VK_ASTERISK = 151;
+
+    public static final int VK_QUOTEDBL = 152;
+
+    public static final int VK_LESS = 153;
+
+    public static final int VK_GREATER = 160;
+
+    public static final int VK_BRACELEFT = 161;
+
+    public static final int VK_BRACERIGHT = 162;
+
+    public static final int VK_AT = 512;
+
+    public static final int VK_COLON = 513;
+
+    public static final int VK_CIRCUMFLEX = 514;
+
+    public static final int VK_DOLLAR = 515;
+
+    public static final int VK_EURO_SIGN = 516;
+
+    public static final int VK_EXCLAMATION_MARK = 517;
+
+    public static final int VK_INVERTED_EXCLAMATION_MARK = 518;
+
+    public static final int VK_LEFT_PARENTHESIS = 519;
+
+    public static final int VK_NUMBER_SIGN = 520;
+
+    public static final int VK_PLUS = 521;
+
+    public static final int VK_RIGHT_PARENTHESIS = 522;
+
+    public static final int VK_UNDERSCORE = 523;
+
+    public static final int VK_FINAL = 24;
+
+    public static final int VK_WINDOWS = 524; 
+
+    public static final int VK_CONTEXT_MENU = 525;
+
+    public static final int VK_CONVERT = 28;
+
+    public static final int VK_NONCONVERT = 29;
+
+    public static final int VK_ACCEPT = 30;
+
+    public static final int VK_MODECHANGE = 31;
+
+    public static final int VK_KANA = 21;
+
+    public static final int VK_KANJI = 25;
+
+    public static final int VK_ALPHANUMERIC = 240;
+
+    public static final int VK_KATAKANA = 241;
+
+    public static final int VK_HIRAGANA = 242;
+
+    public static final int VK_FULL_WIDTH = 243;
+
+    public static final int VK_HALF_WIDTH = 244;
+
+    public static final int VK_ROMAN_CHARACTERS = 245;
+
+    public static final int VK_ALL_CANDIDATES = 256;
+
+    public static final int VK_PREVIOUS_CANDIDATE = 257;
+
+    public static final int VK_CODE_INPUT = 258;
+
+    public static final int VK_JAPANESE_KATAKANA = 259;
+
+    public static final int VK_JAPANESE_HIRAGANA = 260;
+
+    public static final int VK_JAPANESE_ROMAN = 261;
+
+    public static final int VK_KANA_LOCK = 262;
+
+    public static final int VK_INPUT_METHOD_ON_OFF = 263;
+
+    public static final int VK_CUT = 65489;
+
+    public static final int VK_COPY = 65485;
+
+    public static final int VK_PASTE = 65487;
+
+    public static final int VK_UNDO = 65483;
+
+    public static final int VK_AGAIN = 65481;
+
+    public static final int VK_FIND = 65488;
+
+    public static final int VK_PROPS = 65482;
+
+    public static final int VK_STOP = 65480;
+
+    public static final int VK_COMPOSE = 65312;
+
+    public static final int VK_ALT_GRAPH = 65406;
+
+    public static final int VK_BEGIN = 65368;
+
+    public static final int VK_UNDEFINED = 0;
+
+    public static final char CHAR_UNDEFINED = (char)(-1);
+
+    public static final int KEY_LOCATION_UNKNOWN = 0;
+
+    public static final int KEY_LOCATION_STANDARD = 1;
+
+    public static final int KEY_LOCATION_LEFT = 2;
+
+    public static final int KEY_LOCATION_RIGHT = 3;
+
+    public static final int KEY_LOCATION_NUMPAD = 4;
+
+    private int keyCode;
+    private char keyChar;
+    private int keyLocation;
+
+    public static String getKeyModifiersText(int modifiers) {
+        return getKeyModifiersExText(extractExFlags(modifiers));
+    }
+
+    static String getKeyModifiersExText(int modifiersEx) {
+        String text = ""; //$NON-NLS-1$
+
+        if ((modifiersEx & InputEvent.META_DOWN_MASK) != 0) {
+            text += Toolkit.getProperty("AWT.meta", "Meta"); //$NON-NLS-1$ //$NON-NLS-2$
+        }
+        if ((modifiersEx & InputEvent.CTRL_DOWN_MASK) != 0) {
+            text += ((text.length() > 0) ? "+" : "") + //$NON-NLS-1$ //$NON-NLS-2$
+                    Toolkit.getProperty("AWT.control", "Ctrl"); //$NON-NLS-1$ //$NON-NLS-2$
+        }
+        if ((modifiersEx & InputEvent.ALT_DOWN_MASK) != 0) {
+            text += ((text.length() > 0) ? "+" : "") + //$NON-NLS-1$ //$NON-NLS-2$
+                    Toolkit.getProperty("AWT.alt", "Alt"); //$NON-NLS-1$ //$NON-NLS-2$
+        }
+        if ((modifiersEx & InputEvent.SHIFT_DOWN_MASK) != 0) {
+            text += ((text.length() > 0) ? "+" : "") + //$NON-NLS-1$ //$NON-NLS-2$
+                    Toolkit.getProperty("AWT.shift", "Shift"); //$NON-NLS-1$ //$NON-NLS-2$
+        }
+        if ((modifiersEx & InputEvent.ALT_GRAPH_DOWN_MASK) != 0) {
+            text += ((text.length() > 0) ? "+" : "") + //$NON-NLS-1$ //$NON-NLS-2$
+                    Toolkit.getProperty("AWT.altGraph", "Alt Graph"); //$NON-NLS-1$ //$NON-NLS-2$
+        }
+
+        return text;
+    }
+
+    public static String getKeyText(int keyCode) {
+        String[] rawName = getPublicStaticFinalIntFieldName(keyCode); //$NON-NLS-1$
+
+        if ((rawName == null) || (rawName.length == 0)) {
+            return ("Unknown keyCode: " + (keyCode >= 0 ? "0x" : "-0x") + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+                    Integer.toHexString(Math.abs(keyCode)));
+        }
+
+        String propertyName = getPropertyName(rawName);
+        String defaultName = getDefaultName(rawName);
+
+        return Toolkit.getProperty(propertyName, defaultName);
+    }
+
+    private static String getDefaultName(String[] rawName) {
+        String name = ""; //$NON-NLS-1$
+
+        for (int i = 0; true; i++) {
+            String part = rawName[i];
+
+            name += new String(new char[] {part.charAt(0)}).toUpperCase() +
+                    part.substring(1).toLowerCase();
+
+            if (i == (rawName.length - 1)) {
+                break;
+            }
+            name += " "; //$NON-NLS-1$
+        }
+
+        return name;
+    }
+
+    private static String getPropertyName(String[] rawName) {
+        String name = rawName[0].toLowerCase();
+
+        for (int i = 1; i < rawName.length; i++) {
+            String part = rawName[i];
+
+            name += new String(new char[] {part.charAt(0)}).toUpperCase() +
+                    part.substring(1).toLowerCase();
+        }
+
+        return ("AWT." + name); //$NON-NLS-1$
+    }
+
+    private static String[] getPublicStaticFinalIntFieldName(int value) {
+        Field[] allFields = KeyEvent.class.getDeclaredFields();
+
+        try {
+            for (Field field : allFields) {
+                Class<?> ssalc = field.getType();
+                int modifiers = field.getModifiers();
+
+                if (ssalc.isPrimitive() && ssalc.getName().equals("int") && //$NON-NLS-1$
+                        Modifier.isFinal(modifiers) && Modifier.isPublic(modifiers) &&
+                        Modifier.isStatic(modifiers))
+                {
+                    if (field.getInt(null) == value){
+                        final String name = field.getName();
+                        final int prefixLength = name.indexOf("_") + 1;
+                        return name.substring(prefixLength).split("_"); //$NON-NLS-1$
+                    }
+                }
+            }
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+
+        return null;
+    }
+
+    @Deprecated
+    public KeyEvent(Component src, int id,
+                    long when, int modifiers,
+                    int keyCode) {
+        this(src, id, when, modifiers, keyCode,
+                (keyCode > (2 << 7) - 1) ? CHAR_UNDEFINED : (char) keyCode);
+    }
+
+    public KeyEvent(Component src, int id,
+                    long when, int modifiers,
+                    int keyCode, char keyChar) {
+        this(src, id, when, modifiers, keyCode, keyChar, KEY_LOCATION_UNKNOWN);
+    }
+
+    public KeyEvent(Component src, int id,
+                    long when, int modifiers,
+                    int keyCode, char keyChar,
+                    int keyLocation) {
+        super(src, id, when, modifiers);
+
+        if (id == KEY_TYPED) {
+            if (keyCode != VK_UNDEFINED) {
+                // awt.191=Invalid keyCode for KEY_TYPED event, must be VK_UNDEFINED
+                throw new IllegalArgumentException(Messages.getString("awt.191")); //$NON-NLS-1$
+            }
+            if (keyChar == CHAR_UNDEFINED) {
+                // awt.192=Invalid keyChar for KEY_TYPED event, can't be CHAR_UNDEFINED
+                throw new IllegalArgumentException(Messages.getString("awt.192")); //$NON-NLS-1$
+            }
+        }
+        
+        if ((keyLocation < KEY_LOCATION_UNKNOWN)
+                || (keyLocation > KEY_LOCATION_NUMPAD)) {
+            // awt.297=Invalid keyLocation
+            throw new IllegalArgumentException(Messages.getString("awt.297")); //$NON-NLS-1$
+        }
+
+        this.keyChar = keyChar;
+        this.keyLocation = keyLocation;
+        this.keyCode = keyCode;
+    }
+
+    public int getKeyCode() {
+        return keyCode;
+    }
+
+    public void setKeyCode(int keyCode) {
+        this.keyCode = keyCode;
+    }
+
+    public char getKeyChar() {
+        return keyChar;
+    }
+
+    public void setKeyChar(char keyChar) {
+        this.keyChar = keyChar;
+    }
+
+    public int getKeyLocation() {
+        return keyLocation;
+    }
+
+    @Override
+    @Deprecated
+    public void setModifiers(int modifiers) {
+        super.setModifiers(modifiers);
+    }
+
+    public boolean isActionKey() {
+        return ((keyChar == CHAR_UNDEFINED) && (keyCode != VK_UNDEFINED) &&
+                !((keyCode == VK_ALT) || (keyCode == VK_ALT_GRAPH) ||
+                    (keyCode == VK_CONTROL) || (keyCode == VK_META) || (keyCode == VK_SHIFT)));
+    }
+
+    @Override
+    public String paramString() {
+        /*
+         * The format is based on 1.5 release behavior
+         * which can be revealed by the following code:
+         *
+         * KeyEvent e = new KeyEvent(new Component() {}, 
+         *       KeyEvent.KEY_PRESSED, 0, 
+         *       KeyEvent.CTRL_DOWN_MASK|KeyEvent.SHIFT_DOWN_MASK, 
+         *       KeyEvent.VK_A, 'A', KeyEvent.KEY_LOCATION_STANDARD);
+         * System.out.println(e);
+         */
+
+        String idString = null;
+        String locString = null;
+        String paramString = null;
+        String keyCharString = (keyChar == '\n') ?
+                keyCharString = getKeyText(VK_ENTER) : "'" + keyChar + "'"; //$NON-NLS-1$ //$NON-NLS-2$
+
+        switch (id) {
+        case KEY_PRESSED:
+            idString = "KEY_PRESSED"; //$NON-NLS-1$
+            break;
+        case KEY_RELEASED:
+            idString = "KEY_RELEASED"; //$NON-NLS-1$
+            break;
+        case KEY_TYPED:
+            idString = "KEY_TYPED"; //$NON-NLS-1$
+            break;
+        default:
+            idString = "unknown type"; //$NON-NLS-1$
+        }
+
+        switch(keyLocation){
+        case KEY_LOCATION_STANDARD:
+            locString = "KEY_LOCATION_STANDARD"; //$NON-NLS-1$
+            break;
+        case KEY_LOCATION_LEFT:
+            locString = "KEY_LOCATION_LEFT"; //$NON-NLS-1$
+            break;
+        case KEY_LOCATION_RIGHT:
+            locString = "KEY_LOCATION_RIGHT"; //$NON-NLS-1$
+            break;
+        case KEY_LOCATION_NUMPAD:
+            locString = "KEY_LOCATION_NUMPAD"; //$NON-NLS-1$
+            break;
+        case KEY_LOCATION_UNKNOWN:
+            locString = "KEY_LOCATION_UNKNOWN"; //$NON-NLS-1$
+            break;
+        default:
+            locString = "unknown type"; //$NON-NLS-1$
+        }
+
+        paramString = idString + ",keyCode=" + keyCode; //$NON-NLS-1$
+        if (isActionKey()) {
+            paramString += "," + getKeyText(keyCode); //$NON-NLS-1$
+        } else {
+            paramString += ",keyChar=" + keyCharString; //$NON-NLS-1$
+        }
+        if (getModifiersEx() > 0) {
+            paramString += ",modifiers=" + getModifiersExText(getModifiersEx()) + //$NON-NLS-1$
+                    ",extModifiers=" + getModifiersExText(getModifiersEx()); //$NON-NLS-1$
+        }
+        paramString += ",keyLocation=" + locString; //$NON-NLS-1$
+
+        return paramString;
+    }
+
+}
diff --git a/awt/java/awt/event/KeyListener.java b/awt/java/awt/event/KeyListener.java
new file mode 100644
index 0000000..f20fc90
--- /dev/null
+++ b/awt/java/awt/event/KeyListener.java
@@ -0,0 +1,33 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.util.EventListener;
+
+public interface KeyListener extends EventListener {
+
+    public void keyPressed(KeyEvent e);
+
+    public void keyReleased(KeyEvent e);
+
+    public void keyTyped(KeyEvent e);
+
+}
diff --git a/awt/java/awt/event/MouseAdapter.java b/awt/java/awt/event/MouseAdapter.java
new file mode 100644
index 0000000..4973956
--- /dev/null
+++ b/awt/java/awt/event/MouseAdapter.java
@@ -0,0 +1,43 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+public abstract class MouseAdapter implements MouseListener {
+
+    public MouseAdapter() {
+    }
+
+    public void mouseClicked(MouseEvent e) {
+    }
+
+    public void mouseEntered(MouseEvent e) {
+    }
+
+    public void mouseExited(MouseEvent e) {
+    }
+
+    public void mousePressed(MouseEvent e) {
+    }
+
+    public void mouseReleased(MouseEvent e) {
+    }
+
+}
diff --git a/awt/java/awt/event/MouseEvent.java b/awt/java/awt/event/MouseEvent.java
new file mode 100644
index 0000000..0b776f9
--- /dev/null
+++ b/awt/java/awt/event/MouseEvent.java
@@ -0,0 +1,226 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.awt.Component;
+import java.awt.Point;
+import java.awt.Toolkit;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+public class MouseEvent extends InputEvent {
+
+    private static final long serialVersionUID = -991214153494842848L;
+
+    public static final int MOUSE_FIRST = 500;
+
+    public static final int MOUSE_LAST = 507;
+
+    public static final int MOUSE_CLICKED = 500;
+
+    public static final int MOUSE_PRESSED = 501;
+
+    public static final int MOUSE_RELEASED = 502;
+
+    public static final int MOUSE_MOVED = 503;
+
+    public static final int MOUSE_ENTERED = 504;
+
+    public static final int MOUSE_EXITED = 505;
+
+    public static final int MOUSE_DRAGGED = 506;
+
+    public static final int MOUSE_WHEEL = 507;
+
+    public static final int NOBUTTON = 0;
+
+    public static final int BUTTON1 = 1;
+
+    public static final int BUTTON2 = 2;
+
+    public static final int BUTTON3 = 3;
+
+    private boolean popupTrigger;
+    private int clickCount;
+    private int button;
+    private int x;
+    private int y;
+
+    public static String getMouseModifiersText(int modifiers) {
+        final StringBuffer text = new StringBuffer();
+
+        if ((modifiers & META_MASK) != 0) {
+            text.append(Toolkit.getProperty("AWT.meta", "Meta")).append("+"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+        }
+        if ((modifiers & SHIFT_MASK) != 0) {
+            text.append(Toolkit.getProperty("AWT.shift", "Shift")).append("+"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+        }
+        if ((modifiers & CTRL_MASK) != 0) {
+            text.append(Toolkit.getProperty("AWT.control", "Ctrl")).append("+"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+        }
+        if ((modifiers & ALT_MASK) != 0) {
+            text.append(Toolkit.getProperty("AWT.alt", "Alt")).append("+"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+        }
+        if ((modifiers & ALT_GRAPH_MASK) != 0) {
+            text.append(Toolkit.getProperty("AWT.altGraph", "Alt Graph")).append("+"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+        }
+        if ((modifiers & BUTTON1_MASK) != 0) {
+            text.append(Toolkit.getProperty("AWT.button1", "Button1")).append("+"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+        }
+        if ((modifiers & BUTTON2_MASK) != 0) {
+            text.append(Toolkit.getProperty("AWT.button2", "Button2")).append("+"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+        }
+        if ((modifiers & BUTTON3_MASK) != 0) {
+            text.append(Toolkit.getProperty("AWT.button3", "Button3")).append("+"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+        }
+
+        return text.length() == 0 ? text.toString() : text.substring(0, text
+                .length() - 1);
+    }
+
+    static String addMouseModifiersExText(String text, int modifiersEx) {
+        if ((modifiersEx & InputEvent.BUTTON1_DOWN_MASK) != 0) {
+            text += ((text.length() > 0) ? "+" : "") + //$NON-NLS-1$ //$NON-NLS-2$
+                    Toolkit.getProperty("AWT.button1", "Button1"); //$NON-NLS-1$ //$NON-NLS-2$
+        }
+        if ((modifiersEx & InputEvent.BUTTON2_DOWN_MASK) != 0) {
+            text += ((text.length() > 0) ? "+" : "") + //$NON-NLS-1$ //$NON-NLS-2$
+                    Toolkit.getProperty("AWT.button2", "Button2"); //$NON-NLS-1$ //$NON-NLS-2$
+        }
+        if ((modifiersEx & InputEvent.BUTTON3_DOWN_MASK) != 0) {
+            text += ((text.length() > 0) ? "+" : "") + //$NON-NLS-1$ //$NON-NLS-2$
+                    Toolkit.getProperty("AWT.button3", "Button3"); //$NON-NLS-1$ //$NON-NLS-2$
+        }
+
+        return text;
+    }
+
+    public MouseEvent(Component source, int id, long when,
+                      int modifiers, int x, int y,
+                      int clickCount, boolean popupTrigger) {
+        this(source, id, when, modifiers, x, y,
+             clickCount, popupTrigger, NOBUTTON);
+    }
+
+    public MouseEvent(Component source, int id, long when,
+                      int modifiers, int x, int y,
+                      int clickCount, boolean popupTrigger, int button) {
+        super(source, id, when, modifiers);
+
+        if ((button != NOBUTTON) && (button != BUTTON1) &&
+                (button != BUTTON2) && (button != BUTTON3)) {
+            // awt.18B=Invalid button value
+            throw new IllegalArgumentException(Messages.getString("awt.18B")); //$NON-NLS-1$
+        }
+
+        this.popupTrigger = popupTrigger;
+        this.clickCount = clickCount;
+        this.button = button;
+        this.x = x;
+        this.y = y;
+    }
+
+    public int getButton() {
+        return button;
+    }
+
+    public int getClickCount() {
+        return clickCount;
+    }
+
+    public Point getPoint() {
+        return new Point(x, y);
+    }
+
+    public int getX() {
+        return x;
+    }
+
+    public int getY() {
+        return y;
+    }
+
+    public boolean isPopupTrigger() {
+        return popupTrigger;
+    }
+
+    public void translatePoint(int x, int y) {
+        this.x += x;
+        this.y += y;
+    }
+
+    @Override
+    public String paramString() {
+        /* The format is based on 1.5 release behavior 
+         * which can be revealed by the following code:
+         * 
+         * MouseEvent e = new MouseEvent(new Component(){}, 
+         *          MouseEvent.MOUSE_PRESSED, 0, 
+         *          MouseEvent.BUTTON1_DOWN_MASK|MouseEvent.CTRL_DOWN_MASK,
+         *          10, 20, 1, false, MouseEvent.BUTTON1);
+         * System.out.println(e);
+         */
+
+        String idString = null;
+        String paramString = null;
+
+        switch (id) {
+        case MOUSE_MOVED:
+            idString = "MOUSE_MOVED"; //$NON-NLS-1$
+            break;
+        case MOUSE_CLICKED:
+            idString = "MOUSE_CLICKED"; //$NON-NLS-1$
+            break;
+        case MOUSE_PRESSED:
+            idString = "MOUSE_PRESSED"; //$NON-NLS-1$
+            break;
+        case MOUSE_RELEASED:
+            idString = "MOUSE_RELEASED"; //$NON-NLS-1$
+            break;
+        case MOUSE_DRAGGED:
+            idString = "MOUSE_DRAGGED"; //$NON-NLS-1$
+            break;
+        case MOUSE_ENTERED:
+            idString = "MOUSE_ENTERED"; //$NON-NLS-1$
+            break;
+        case MOUSE_EXITED:
+            idString = "MOUSE_EXITED"; //$NON-NLS-1$
+            break;
+        case MOUSE_WHEEL:
+            idString = "MOUSE_WHEEL"; //$NON-NLS-1$
+            break;
+        default:
+            idString = "unknown type"; //$NON-NLS-1$
+        }
+
+        paramString = idString + ",(" + getX() + "," + getY() + ")" + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+                ",button=" + button; //$NON-NLS-1$
+        if (getModifiersEx() > 0) {
+            paramString += 
+                    ",modifiers=" + getModifiersExText(getModifiersEx()) + //$NON-NLS-1$
+                    ",extModifiers=" + getModifiersExText(getModifiersEx()); //$NON-NLS-1$
+        }
+        paramString += ",clickCount=" + getClickCount(); //$NON-NLS-1$
+
+        return paramString;
+    }
+
+}
diff --git a/awt/java/awt/event/MouseListener.java b/awt/java/awt/event/MouseListener.java
new file mode 100644
index 0000000..5d32b0f
--- /dev/null
+++ b/awt/java/awt/event/MouseListener.java
@@ -0,0 +1,37 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.util.EventListener;
+
+public interface MouseListener extends EventListener {
+
+    public void mouseClicked(MouseEvent e);
+
+    public void mouseEntered(MouseEvent e);
+
+    public void mouseExited(MouseEvent e);
+
+    public void mousePressed(MouseEvent e);
+
+    public void mouseReleased(MouseEvent e);
+
+}
diff --git a/awt/java/awt/event/MouseMotionAdapter.java b/awt/java/awt/event/MouseMotionAdapter.java
new file mode 100644
index 0000000..a4bebcc
--- /dev/null
+++ b/awt/java/awt/event/MouseMotionAdapter.java
@@ -0,0 +1,34 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+public abstract class MouseMotionAdapter implements MouseMotionListener {
+
+    public MouseMotionAdapter() {
+    }
+
+    public void mouseDragged(MouseEvent e) {
+    }
+
+    public void mouseMoved(MouseEvent e) {
+    }
+
+}
diff --git a/awt/java/awt/event/MouseMotionListener.java b/awt/java/awt/event/MouseMotionListener.java
new file mode 100644
index 0000000..a5c11da
--- /dev/null
+++ b/awt/java/awt/event/MouseMotionListener.java
@@ -0,0 +1,31 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.util.EventListener;
+
+public interface MouseMotionListener extends EventListener {
+
+    public void mouseDragged(MouseEvent e);
+
+    public void mouseMoved(MouseEvent e);
+
+}
diff --git a/awt/java/awt/event/MouseWheelEvent.java b/awt/java/awt/event/MouseWheelEvent.java
new file mode 100644
index 0000000..d3ac9d8
--- /dev/null
+++ b/awt/java/awt/event/MouseWheelEvent.java
@@ -0,0 +1,97 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.awt.Component;
+
+public class MouseWheelEvent extends MouseEvent {
+
+    private static final long serialVersionUID = -9187413581993563929L;
+
+    public static final int WHEEL_UNIT_SCROLL = 0;
+
+    public static final int WHEEL_BLOCK_SCROLL = 1;
+
+    private int wheelRotation;
+    private int scrollAmount;
+    private int scrollType;
+
+    public MouseWheelEvent(Component source, int id, long when, int modifiers,
+            int x, int y, int clickCount, boolean popupTrigger, int scrollType,
+            int scrollAmount, int wheelRotation) {
+        super(source, id, when, modifiers, x, y, clickCount, popupTrigger);
+
+        this.scrollType = scrollType;
+        this.scrollAmount = scrollAmount;
+        this.wheelRotation = wheelRotation;
+    }
+
+    public int getScrollAmount() {
+        return scrollAmount;
+    }
+
+    public int getScrollType() {
+        return scrollType;
+    }
+
+    public int getWheelRotation() {
+        return wheelRotation;
+    }
+
+    public int getUnitsToScroll() {
+        return (scrollAmount * wheelRotation);
+    }
+
+    @Override
+    public String paramString() {
+        /* The format is based on 1.5 release behavior 
+         * which can be revealed by the following code:
+         * 
+         * MouseWheelEvent e = new MouseWheelEvent(new Component(){}, 
+         *          MouseWheelEvent.MOUSE_WHEEL, 0, 
+         *          MouseEvent.BUTTON1_DOWN_MASK|MouseEvent.CTRL_DOWN_MASK,
+         *          10, 20, 1, false, MouseWheelEvent.WHEEL_UNIT_SCROLL,
+         *          1, 3);
+         * System.out.println(e);
+         */
+
+        String paramString = super.paramString();
+        String typeString = null;
+
+        switch (scrollType) {
+        case WHEEL_UNIT_SCROLL:
+            typeString = "WHEEL_UNIT_SCROLL"; //$NON-NLS-1$
+            break;
+        case WHEEL_BLOCK_SCROLL:
+            typeString = "WHEEL_BLOCK_SCROLL"; //$NON-NLS-1$
+            break;
+        default:
+            typeString = "unknown type"; //$NON-NLS-1$
+        }
+
+        paramString += ",scrollType=" + typeString + //$NON-NLS-1$
+                ",scrollAmount=" + scrollAmount +  //$NON-NLS-1$
+                ",wheelRotation=" + wheelRotation; //$NON-NLS-1$
+
+        return paramString;
+    }
+
+}
diff --git a/awt/java/awt/event/MouseWheelListener.java b/awt/java/awt/event/MouseWheelListener.java
new file mode 100644
index 0000000..8ca1c8b
--- /dev/null
+++ b/awt/java/awt/event/MouseWheelListener.java
@@ -0,0 +1,29 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.util.EventListener;
+
+public interface MouseWheelListener extends EventListener {
+
+    public void mouseWheelMoved(MouseWheelEvent e);
+
+}
diff --git a/awt/java/awt/event/PaintEvent.java b/awt/java/awt/event/PaintEvent.java
new file mode 100644
index 0000000..d0573e1
--- /dev/null
+++ b/awt/java/awt/event/PaintEvent.java
@@ -0,0 +1,80 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.awt.Component;
+import java.awt.Rectangle;
+
+public class PaintEvent extends ComponentEvent {
+
+    private static final long serialVersionUID = 1267492026433337593L;
+
+    public static final int PAINT_FIRST = 800;
+
+    public static final int PAINT_LAST = 801;
+
+    public static final int PAINT = 800;
+
+    public static final int UPDATE = 801;
+
+    private Rectangle updateRect;
+
+    public PaintEvent(Component source, int id, Rectangle updateRect) {
+        super(source, id);
+
+        this.updateRect = updateRect;
+    }
+
+    public Rectangle getUpdateRect() {
+        return updateRect;
+    }
+
+    public void setUpdateRect(Rectangle updateRect) {
+        this.updateRect = updateRect;
+    }
+
+    @Override
+    public String paramString() {
+        /* The format is based on 1.5 release behavior 
+         * which can be revealed by the following code:
+         * 
+         * PaintEvent e = new PaintEvent(new Component(){}, 
+         *          PaintEvent.PAINT, new Rectangle(0, 0, 10, 20)); 
+         * System.out.println(e);
+         */
+
+        String typeString = null;
+
+        switch (id) {
+        case PAINT:
+            typeString = "PAINT"; //$NON-NLS-1$
+            break;
+        case UPDATE:
+            typeString = "UPDATE"; //$NON-NLS-1$
+            break;
+        default:
+            typeString = "unknown type"; //$NON-NLS-1$
+        }
+
+        return typeString + ",updateRect=" + updateRect; //$NON-NLS-1$
+    }
+
+}
diff --git a/awt/java/awt/event/TextEvent.java b/awt/java/awt/event/TextEvent.java
new file mode 100644
index 0000000..e2bfd96
--- /dev/null
+++ b/awt/java/awt/event/TextEvent.java
@@ -0,0 +1,53 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.awt.AWTEvent;
+
+public class TextEvent extends AWTEvent {
+
+    private static final long serialVersionUID = 6269902291250941179L;
+
+    public static final int TEXT_FIRST = 900;
+
+    public static final int TEXT_LAST = 900;
+
+    public static final int TEXT_VALUE_CHANGED = 900;
+
+    public TextEvent(Object src, int id) {
+        super(src, id);
+    }
+
+    @Override
+    public String paramString() {
+        /* The format is based on 1.5 release behavior 
+         * which can be revealed by the following code:
+         * 
+         * TextEvent e = new TextEvent(new Component(){}, 
+         *          TextEvent.TEXT_VALUE_CHANGED); 
+         * System.out.println(e);
+         */
+
+        return (id == TEXT_VALUE_CHANGED) ? 
+                "TEXT_VALUE_CHANGED" : "unknown type"; //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+}
diff --git a/awt/java/awt/event/TextListener.java b/awt/java/awt/event/TextListener.java
new file mode 100644
index 0000000..6c5a671
--- /dev/null
+++ b/awt/java/awt/event/TextListener.java
@@ -0,0 +1,30 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.util.EventListener;
+
+public interface TextListener extends EventListener {
+
+    public void textValueChanged(TextEvent e);
+
+}
+
diff --git a/awt/java/awt/event/WindowAdapter.java b/awt/java/awt/event/WindowAdapter.java
new file mode 100644
index 0000000..9d4b377
--- /dev/null
+++ b/awt/java/awt/event/WindowAdapter.java
@@ -0,0 +1,58 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+public abstract class WindowAdapter implements WindowListener, WindowStateListener, WindowFocusListener {
+
+    public WindowAdapter() {
+    }
+
+    public void windowActivated(WindowEvent e) {
+    }
+
+    public void windowClosed(WindowEvent e) {
+    }
+
+    public void windowClosing(WindowEvent e) {
+    }
+
+    public void windowDeactivated(WindowEvent e) {
+    }
+
+    public void windowDeiconified(WindowEvent e) {
+    }
+
+    public void windowGainedFocus(WindowEvent e) {
+    }
+
+    public void windowIconified(WindowEvent e) {
+    }
+
+    public void windowLostFocus(WindowEvent e) {
+    }
+
+    public void windowOpened(WindowEvent e) {
+    }
+
+    public void windowStateChanged(WindowEvent e) {
+    }
+
+}
diff --git a/awt/java/awt/event/WindowEvent.java b/awt/java/awt/event/WindowEvent.java
new file mode 100644
index 0000000..65a30e4
--- /dev/null
+++ b/awt/java/awt/event/WindowEvent.java
@@ -0,0 +1,162 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+
+//???AWT
+//import java.awt.Window;
+//import java.awt.Frame;
+
+public class WindowEvent extends ComponentEvent {
+
+    private static final long serialVersionUID = -1567959133147912127L;
+
+    public static final int WINDOW_FIRST = 200;
+
+    public static final int WINDOW_OPENED = 200;
+
+    public static final int WINDOW_CLOSING = 201;
+
+    public static final int WINDOW_CLOSED = 202;
+
+    public static final int WINDOW_ICONIFIED = 203;
+
+    public static final int WINDOW_DEICONIFIED = 204;
+
+    public static final int WINDOW_ACTIVATED = 205;
+
+    public static final int WINDOW_DEACTIVATED = 206;
+
+    public static final int WINDOW_GAINED_FOCUS = 207;
+
+    public static final int WINDOW_LOST_FOCUS = 208;
+
+    public static final int WINDOW_STATE_CHANGED = 209;
+
+    public static final int WINDOW_LAST = 209;
+
+    //???AWT: private Window oppositeWindow;
+    private int oldState;
+    private int newState;
+
+    //???AWT
+    /*
+    public WindowEvent(Window source, int id) {
+        this(source, id, null);
+    }
+
+    public WindowEvent(Window source, int id, Window opposite) {
+        this(source, id, opposite, Frame.NORMAL, Frame.NORMAL);
+    }
+
+    public WindowEvent(Window source, int id, int oldState, int newState) {
+        this(source, id, null, oldState, newState);
+    }
+
+    public WindowEvent(Window source, int id, Window opposite, 
+                       int oldState, int newState) {
+        super(source, id);
+
+        oppositeWindow = opposite;
+        this.oldState = oldState;
+        this.newState = newState;
+    }
+    */
+    //???AWT: Fake constructor
+    public WindowEvent() {
+        super(null, 0);
+    }
+    
+    public int getNewState() {
+        return newState;
+    }
+
+    public int getOldState() {
+        return oldState;
+    }
+
+    //???AWT
+    /*
+    public Window getOppositeWindow() {
+        return oppositeWindow;
+    }
+
+    public Window getWindow() {
+        return (Window) source;
+    }
+    */
+
+    @Override
+    public String paramString() {
+        /* The format is based on 1.5 release behavior 
+         * which can be revealed by the following code:
+         * 
+         * WindowEvent e = new WindowEvent(new Frame(), 
+         *          WindowEvent.WINDOW_OPENED); 
+         * System.out.println(e);
+         */
+
+        String typeString = null;
+
+        switch (id) {
+        case WINDOW_OPENED:
+            typeString = "WINDOW_OPENED"; //$NON-NLS-1$
+            break;
+        case WINDOW_CLOSING:
+            typeString = "WINDOW_CLOSING"; //$NON-NLS-1$
+            break;
+        case WINDOW_CLOSED:
+            typeString = "WINDOW_CLOSED"; //$NON-NLS-1$
+            break;
+        case WINDOW_ICONIFIED:
+            typeString = "WINDOW_ICONIFIED"; //$NON-NLS-1$
+            break;
+        case WINDOW_DEICONIFIED:
+            typeString = "WINDOW_DEICONIFIED"; //$NON-NLS-1$
+            break;
+        case WINDOW_ACTIVATED:
+            typeString = "WINDOW_ACTIVATED"; //$NON-NLS-1$
+            break;
+        case WINDOW_DEACTIVATED:
+            typeString = "WINDOW_DEACTIVATED"; //$NON-NLS-1$
+            break;
+        case WINDOW_GAINED_FOCUS:
+            typeString = "WINDOW_GAINED_FOCUS"; //$NON-NLS-1$
+            break;
+        case WINDOW_LOST_FOCUS:
+            typeString = "WINDOW_LOST_FOCUS"; //$NON-NLS-1$
+            break;
+        case WINDOW_STATE_CHANGED:
+            typeString = "WINDOW_STATE_CHANGED"; //$NON-NLS-1$
+            break;
+        default:
+            typeString = "unknown type"; //$NON-NLS-1$
+        }
+
+        //???AWT
+        /*
+        return typeString + ",opposite=" + oppositeWindow + //$NON-NLS-1$
+                ",oldState=" + oldState + ",newState=" + newState; //$NON-NLS-1$ //$NON-NLS-2$
+        */
+        return typeString;
+    }
+
+}
diff --git a/awt/java/awt/event/WindowFocusListener.java b/awt/java/awt/event/WindowFocusListener.java
new file mode 100644
index 0000000..e0200f2
--- /dev/null
+++ b/awt/java/awt/event/WindowFocusListener.java
@@ -0,0 +1,31 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.util.EventListener;
+
+public interface WindowFocusListener extends EventListener {
+
+    public void windowGainedFocus(WindowEvent e);
+
+    public void windowLostFocus(WindowEvent e);
+
+}
diff --git a/awt/java/awt/event/WindowListener.java b/awt/java/awt/event/WindowListener.java
new file mode 100644
index 0000000..20a2b08
--- /dev/null
+++ b/awt/java/awt/event/WindowListener.java
@@ -0,0 +1,41 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.util.EventListener;
+
+public interface WindowListener extends EventListener {
+
+    public void windowActivated(WindowEvent e);
+
+    public void windowClosed(WindowEvent e);
+
+    public void windowClosing(WindowEvent e);
+
+    public void windowDeactivated(WindowEvent e);
+
+    public void windowDeiconified(WindowEvent e);
+
+    public void windowIconified(WindowEvent e);
+
+    public void windowOpened(WindowEvent e);
+
+}
diff --git a/awt/java/awt/event/WindowStateListener.java b/awt/java/awt/event/WindowStateListener.java
new file mode 100644
index 0000000..12dbc20
--- /dev/null
+++ b/awt/java/awt/event/WindowStateListener.java
@@ -0,0 +1,30 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Michael Danilov
+ * @version $Revision$
+ */
+package java.awt.event;
+
+import java.util.EventListener;
+
+public interface WindowStateListener extends EventListener {
+
+    public void windowStateChanged(WindowEvent e);
+
+}
+
diff --git a/awt/java/awt/font/FontRenderContext.java b/awt/java/awt/font/FontRenderContext.java
new file mode 100644
index 0000000..766300d
--- /dev/null
+++ b/awt/java/awt/font/FontRenderContext.java
@@ -0,0 +1,168 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Ilya S. Okomin
+ * @version $Revision$
+ */
+package java.awt.font;
+
+import java.awt.geom.AffineTransform;
+
+/**
+ * The FontRenderContext class contains the information 
+ * about text measurement. Anti-aliasing and fractional-metrics
+ * modes are defined by an application and affect the size of
+ * a character.
+ */
+public class FontRenderContext {
+
+    // Affine transform of this mode
+    /** The transform. */
+    private AffineTransform transform;
+
+    // Is the anti-aliased mode used
+    /** The anti aliased. */
+    private boolean fAntiAliased;
+
+    // Is the fractional metrics used
+    /** The fractional metrics. */
+    private boolean fFractionalMetrics;
+
+
+    /**
+     * Instantiates a new FontRenderContext object with the specified
+     * AffineTransform, anti-aliasing and fractional metrics flags.
+     * 
+     * @param trans the AffineTransform.
+     * @param antiAliased the anti-aliasing flag.
+     * @param usesFractionalMetrics the fractional metrics flag.
+     */
+    public FontRenderContext(AffineTransform trans, boolean antiAliased, 
+            boolean usesFractionalMetrics) {
+        if (trans != null){
+            transform = new AffineTransform(trans);
+        }
+        fAntiAliased = antiAliased;
+        fFractionalMetrics = usesFractionalMetrics;
+    }
+
+    /**
+     * Instantiates a new FontRenderContext object.
+     */
+    protected FontRenderContext() {
+    }
+
+    /**
+     * Compares the specified Object with current FontRenderContext object. 
+     * 
+     * @param obj the Object to be compared.
+     * 
+     * @return true, if the specified Object is equal to current
+     * FontRenderContext object.
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+
+        if (obj != null) {
+            try {
+                return equals((FontRenderContext) obj);
+            } catch (ClassCastException e) {
+                return false;
+            }
+        }
+        return false;
+
+    }
+
+    /**
+     * Gets the transform which is used for scaling typographical points 
+     * to pixels in this FontRenderContext.
+     * 
+     * @return the AffineTransform which is used for scaling typographical 
+     * points to pixels in this FontRenderContext.
+     */
+    public AffineTransform getTransform() {
+        if (transform != null){
+            return new AffineTransform(transform);
+        }
+        return new AffineTransform();
+    }
+
+    /**
+     * Compares the specified FontRenderContext object with current 
+     * FontRenderContext.
+     * 
+     * @param frc the FontRenderContext object to be compared.
+     * 
+     * @return true, if the specified FontRenderContext object is
+     * equal to current FontRenderContext.
+     */
+    public boolean equals(FontRenderContext frc) {
+        if (this == frc){
+            return true;
+        }
+
+        if (frc == null){
+            return false;
+        }
+
+        if (!frc.getTransform().equals(this.getTransform()) &&
+            !frc.isAntiAliased() == this.fAntiAliased &&
+            !frc.usesFractionalMetrics() == this.fFractionalMetrics){
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Returns true if the text fractional metrics are used in 
+     * this FontRenderContext.
+     * 
+     * @return true, if the text fractional metrics are used in 
+     * this FontRenderContext, false otherwise.
+     */
+    public boolean usesFractionalMetrics() {
+        return this.fFractionalMetrics;
+    }
+
+    /**
+     * Returns true if anti-aliasing is used in this FontRenderContext.
+     * 
+     * @return true, if is anti-aliasing is used in this FontRenderContext,
+     * false otherwise.
+     */
+    public boolean isAntiAliased() {
+        return this.fAntiAliased;
+    }
+
+    /**
+     * Returns hash code of the FontRenderContext object.
+     * 
+     * @return the hash code of the FontRenderContext object.
+     */
+    @Override
+    public int hashCode() {
+        return this.getTransform().hashCode() ^
+                new Boolean(this.fFractionalMetrics).hashCode() ^
+                new Boolean(this.fAntiAliased).hashCode();
+    }
+
+}
+
diff --git a/awt/java/awt/font/GlyphJustificationInfo.java b/awt/java/awt/font/GlyphJustificationInfo.java
new file mode 100644
index 0000000..4c3e02e
--- /dev/null
+++ b/awt/java/awt/font/GlyphJustificationInfo.java
@@ -0,0 +1,185 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Ilya S. Okomin
+ * @version $Revision$
+ */
+package java.awt.font;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The GlyphJustificationInfo class provides information about 
+ * the glyph's justification properties. There are four justification 
+ * properties: weight, priority, absorb, and limit.
+ * <p>
+ * There are two sets of metrics: growing and shrinking. 
+ * Growing metrics are used when the glyphs are to be spread apart 
+ * to fit a larger width. Shrinking metrics are used when the glyphs 
+ * are to be moved together to fit a smaller width.
+ */
+public final class GlyphJustificationInfo {
+
+    /** 
+     * The Constant PRIORITY_KASHIDA indicates the highest 
+     * justification priority.
+     */
+    public static final int PRIORITY_KASHIDA = 0;
+
+    /**
+     * The Constant PRIORITY_WHITESPACE indicates the second highest 
+     * justification priority. 
+     */
+    public static final int PRIORITY_WHITESPACE = 1;
+
+    /** 
+     * The Constant PRIORITY_INTERCHAR indicates the second lowest 
+     * justification priority. 
+     */
+    public static final int PRIORITY_INTERCHAR = 2;
+
+    /**
+     * The Constant PRIORITY_NONE indicates the lowest justification 
+     * priority.
+     */
+    public static final int PRIORITY_NONE = 3;
+
+    /** 
+     * The grow absorb flag indicates if this glyph absorbs all extra 
+     * space at this and lower priority levels when it grows.
+     */
+    public final boolean growAbsorb;
+
+    /** 
+     * The grow left limit value represents the maximum value by which 
+     * the left side of this glyph grows. 
+     */
+    public final float growLeftLimit;
+
+    /** 
+     * The grow right limit value repesents the maximum value by which 
+     * the right side of this glyph grows.
+     */
+    public final float growRightLimit;
+
+    /** 
+     * The grow priority value represents the priority level of this 
+     * glyph as it is growing. 
+     */
+    public final int growPriority;
+
+    /** 
+     * The shrink absorb fleg indicates this glyph absorbs all remaining 
+     * shrinkage at this and lower priority levels as it shrinks. 
+     */
+    public final boolean shrinkAbsorb;
+
+    /** 
+     * The shrink left limit value represents the maximum value by which 
+     * the left side of this glyph shrinks. 
+     */
+    public final float shrinkLeftLimit;
+
+    /** 
+     * The shrink right limit value represents the maximum value by which 
+     * the right side of this glyph shrinks. 
+     */
+    public final float shrinkRightLimit;
+
+    /**
+     * The shrink priority represents the glyth's priority level 
+     * as it is shrinking.
+     */
+    public final int shrinkPriority;
+
+    /** 
+     * The weight of the glyph. 
+     */
+    public final float weight;
+
+    /**
+     * Instantiates a new GlyphJustificationInfo object which contains
+     * glyph's justification properties.
+     * 
+     * @param weight the weight of glyph.
+     * @param growAbsorb indicates if this glyph contais all space 
+     * at this priority and lower priority levels when it grows.
+     * @param growPriority indicates the priority level of this glyph 
+     * when it grows.
+     * @param growLeftLimit indicates the maximum value of which the 
+     * left side of this glyph can grow.
+     * @param growRightLimit the maximum value of which the right side of 
+     * this glyph can grow.
+     * @param shrinkAbsorb indicates if this glyph contains all remaining
+     * shrinkage at this and lower priority levels when it shrinks.
+     * @param shrinkPriority indicates the glyph's priority level when 
+     * it shrinks.
+     * @param shrinkLeftLimit indicates the maximum value of which 
+     * the left side of this glyph can shrink. 
+     * @param shrinkRightLimit indicates the maximum amount by which 
+     * the right side of this glyph can shrink.
+     */
+    public GlyphJustificationInfo(float weight, boolean growAbsorb, int growPriority,
+            float growLeftLimit, float growRightLimit, boolean shrinkAbsorb,
+            int shrinkPriority, float shrinkLeftLimit, float shrinkRightLimit) {
+
+        if (weight < 0) {
+            // awt.19C=weight must be a positive number
+            throw new IllegalArgumentException(Messages.getString("awt.19C")); //$NON-NLS-1$
+        }
+        this.weight = weight;
+
+        if (growLeftLimit < 0) {
+            // awt.19D=growLeftLimit must be a positive number
+            throw new IllegalArgumentException(Messages.getString("awt.19D")); //$NON-NLS-1$
+        }
+        this.growLeftLimit = growLeftLimit;
+
+        if (growRightLimit < 0) {
+            // awt.19E=growRightLimit must be a positive number
+            throw new IllegalArgumentException(Messages.getString("awt.19E")); //$NON-NLS-1$
+        }
+        this.growRightLimit = growRightLimit;
+
+        if ((shrinkPriority < 0) || (shrinkPriority > PRIORITY_NONE)) {
+            // awt.19F=incorrect value for shrinkPriority, more than PRIORITY_NONE or less than PRIORITY_KASHIDA value
+            throw new IllegalArgumentException(Messages.getString("awt.19F")); //$NON-NLS-1$
+        }
+        this.shrinkPriority = shrinkPriority;
+
+        if ((growPriority < 0) || (growPriority > PRIORITY_NONE)) {
+            // awt.200=incorrect value for growPriority, more than PRIORITY_NONE or less than PRIORITY_KASHIDA value
+            throw new IllegalArgumentException(Messages.getString("awt.200")); //$NON-NLS-1$
+        }
+        this.growPriority = growPriority;
+
+        if (shrinkLeftLimit < 0) {
+            // awt.201=shrinkLeftLimit must be a positive number
+            throw new IllegalArgumentException(Messages.getString("awt.201")); //$NON-NLS-1$
+        }
+        this.shrinkLeftLimit = shrinkLeftLimit;
+
+        if (shrinkRightLimit < 0) {
+            // awt.202=shrinkRightLimit must be a positive number
+            throw new IllegalArgumentException(Messages.getString("awt.202")); //$NON-NLS-1$
+        }
+        this.shrinkRightLimit = shrinkRightLimit;
+
+        this.shrinkAbsorb = shrinkAbsorb;
+        this.growAbsorb = growAbsorb;
+    }
+}
diff --git a/awt/java/awt/font/GlyphMetrics.java b/awt/java/awt/font/GlyphMetrics.java
new file mode 100644
index 0000000..d96ef18
--- /dev/null
+++ b/awt/java/awt/font/GlyphMetrics.java
@@ -0,0 +1,248 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Ilya S. Okomin
+ * @version $Revision$
+ */
+package java.awt.font;
+
+import java.awt.geom.Rectangle2D;
+
+/**
+ * The GlyphMetrics class provides information about the size and shape 
+ * of a single glyph. 
+ * Each glyph has information to specify whether its baseline is horizontal 
+ * or vertical as well as information on how it interacts with 
+ * other characters in a text, given as one of the
+ * following types: STANDARD, LIGATURE, COMBINING, or COMPONENT.
+ */
+public final class GlyphMetrics {
+
+    // advance width of the glyph character cell
+    /** The advance x. */
+    private float advanceX;
+    
+    // advance height of the glyph character cell
+    /** The advance y. */
+    private float advanceY;
+
+    // flag if the glyph horizontal
+    /** The horizontal. */
+    private boolean horizontal;
+
+    // glyph type code 
+    /** The glyph type. */
+    private byte glyphType;
+    
+    // bounding box for outline of the glyph
+    /** The bounds. */
+    private Rectangle2D.Float bounds;
+
+    /** 
+     * The Constant STANDARD indicates a glyph that represents a single 
+     * character. 
+     */
+    public static final byte STANDARD = 0;
+
+    /** 
+     * The Constant LIGATURE indicates a glyph that represents multiple 
+     * characters as a ligature. 
+     */
+    public static final byte LIGATURE = 1;
+
+    /** 
+     * The Constant COMBINING indicates a glyph which has no caret position 
+     * between glyphs (for example umlaut).
+     */
+    public static final byte COMBINING = 2;
+
+    /** 
+     * The Constant COMPONENT indicates a glyph with no corresponding character 
+     * in the backing store.
+     */
+    public static final byte COMPONENT = 3;
+
+    /** 
+     * The Constant WHITESPACE indicates a glyph without visual 
+     * representation. 
+     */
+    public static final byte WHITESPACE = 4;
+
+    /**
+     * Instantiates a new GlyphMetrics object with the specified parameters.
+     * 
+     * @param horizontal specifies if metrics are for a horizontal baseline 
+     * (true value), or a vertical baseline (false value).
+     * @param advanceX the X component of the glyph's advance.
+     * @param advanceY the Y component of the glyph's advance.
+     * @param bounds the glyph's bounds.
+     * @param glyphType the glyph's type.
+     */
+    public GlyphMetrics(boolean horizontal, float advanceX, float advanceY, 
+            Rectangle2D bounds, byte glyphType) {
+        this.horizontal = horizontal;
+        this.advanceX = advanceX;
+        this.advanceY = advanceY;
+
+        this.bounds = new Rectangle2D.Float();
+        this.bounds.setRect(bounds);
+
+        this.glyphType = glyphType;
+    }
+
+    /**
+     * Instantiates a new horizontal GlyphMetrics with the specified parameters.
+     * 
+     * @param advanceX the X component of the glyph's advance.
+     * @param bounds the glyph's bounds.
+     * @param glyphType the glyph's type.
+     */
+    public GlyphMetrics(float advanceX, Rectangle2D bounds, byte glyphType) {
+        this.advanceX = advanceX;
+        this.advanceY = 0;
+
+        this.horizontal = true;
+
+        this.bounds = new Rectangle2D.Float();
+        this.bounds.setRect(bounds);
+
+        this.glyphType = glyphType;
+    }
+
+    /**
+     * Gets the glyph's bounds.
+     * 
+     * @return glyph's bounds.
+     */
+    public Rectangle2D getBounds2D() {
+        return (Rectangle2D.Float) this.bounds.clone();
+    }
+
+    /**
+     * Checks if this glyph is whitespace or not.
+     * 
+     * @return true, if this glyph is whitespace, false otherwise.
+     */
+    public boolean isWhitespace() {
+        return ((this.glyphType & 4) == WHITESPACE);
+    }
+
+    /**
+     * Checks if this glyph is standard or not.
+     * 
+     * @return true, if this glyph is standard, false otherwise.
+     */
+    public boolean isStandard() {
+        return ((this.glyphType & 3) == STANDARD);
+    }
+
+    /**
+     * Checks if this glyph is ligature or not.
+     * 
+     * @return true, if this glyph is ligature, false otherwise.
+     */
+    public boolean isLigature() {
+        return ((this.glyphType & 3) == LIGATURE);
+    }
+
+    /**
+     * Checks if this glyph is component or not.
+     * 
+     * @return true, if this glyph is component, false otherwise.
+     */
+    public boolean isComponent() {
+        return ((this.glyphType & 3) == COMPONENT);
+    }
+
+    /**
+     * Checks if this glyph is combining or not.
+     * 
+     * @return true, if this glyph is combining, false otherwise.
+     */
+    public boolean isCombining() {
+        return ((this.glyphType & 3) == COMBINING);
+    }
+
+    /**
+     * Gets the glyph's type.
+     * 
+     * @return the glyph's type.
+     */
+    public int getType() {
+        return this.glyphType;
+    }
+
+    /**
+     * Gets the distance from the right (for horizontal) or 
+     * bottom (for vertical) of the glyph bounds to the advance.
+     * 
+     * @return the distance from the right (for horizontal) or 
+     * bottom (for vertical) of the glyph bounds to the advance.
+     */
+    public float getRSB() {
+        if (this.horizontal) {
+            return this.advanceX - this.bounds.x - (float)this.bounds.getWidth();
+        }
+        return this.advanceY - this.bounds.y - (float)this.bounds.getHeight();
+    }
+
+    /**
+     * Gets the distance from 0, 0 to the left (for horizontal) 
+     * or top (for vertical) of the glyph bounds.
+     * 
+     * @return the distance from 0, 0 to the left (for horizontal) 
+     * or top (for vertical) of the glyph bounds.
+     */
+    public float getLSB() {
+        if (this.horizontal) {
+            return this.bounds.x;
+        }
+        return this.bounds.y;
+    }
+
+    /**
+     * Gets the Y component of the glyph's advance.
+     * 
+     * @return the Y component of the glyph's advance.
+     */
+    public float getAdvanceY() {
+        return this.advanceY;
+    }
+
+    /**
+     * Gets the X component of the glyph's advance.
+     * 
+     * @return the X component of the glyph's advance.
+     */
+    public float getAdvanceX() {
+        return this.advanceX;
+    }
+
+    /**
+     * Gets the glyph's advance along the baseline.
+     * 
+     * @return the glyph's advance.
+     */
+    public float getAdvance() {
+        if (this.horizontal) {
+            return this.advanceX;
+        }
+        return this.advanceY;
+    }
+
+}
+
diff --git a/awt/java/awt/font/GlyphVector.java b/awt/java/awt/font/GlyphVector.java
new file mode 100644
index 0000000..b3c9406
--- /dev/null
+++ b/awt/java/awt/font/GlyphVector.java
@@ -0,0 +1,394 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Ilya S. Okomin
+ * @version $Revision$
+ */
+package java.awt.font;
+
+import java.awt.Font;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphJustificationInfo;
+import java.awt.font.GlyphMetrics;
+
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * The GlyphVector class contains a collection of glyphs with geometric 
+ * information and each glyph's location. Each GlyphVector can be associated 
+ * with only one Font. GlyphVector contains the following properties for 
+ * each glyph:
+ * <ul>
+ * <li>the glyph position;</li>
+ * <li>the transform of the glyph;</li>
+ * <li>the metrics of the glyph in the context of the GlyphVector.</li>
+ * </ul>
+ */
+public abstract class GlyphVector implements Cloneable {
+
+    /** 
+     * The Constant FLAG_HAS_TRANSFORMS indicates that this GlyphVector 
+     * has per-glyph transforms.
+     */
+    public static final int FLAG_HAS_TRANSFORMS = 1;
+
+    /** 
+     * The Constant FLAG_HAS_POSITION_ADJUSTMENTS indicates that 
+     * the GlyphVector has per-glyph position adjustments. 
+     */
+    public static final int FLAG_HAS_POSITION_ADJUSTMENTS = 2;
+
+    /** 
+     * The Constant FLAG_RUN_RTL indicates that this GlyphVector has a 
+     * right to left run direction.
+     */
+    public static final int FLAG_RUN_RTL = 4;
+
+    /** 
+     * The Constant FLAG_COMPLEX_GLYPHS indicates that this GlyphVector 
+     * has a complex glyph to char mapping.
+     */
+    public static final int FLAG_COMPLEX_GLYPHS = 8;
+
+    /** 
+     * The Constant FLAG_MASK indicates a mask for supported flags 
+     * from getLayoutFlags.
+     */
+    public static final int FLAG_MASK = 15; // (|) mask of other flags
+
+    /**
+     * Instantiates a new GlyphVector.
+     */
+    public GlyphVector() {
+    }
+
+    /**
+     * Gets the pixel bounds of the GlyphVector when rendered
+     * at the specified location with the specified FontRenderContext.
+     * 
+     * @param frc the FontRenderContext.
+     * @param x the X coordinate of the GlyphVector's location.
+     * @param y the Y coordinate of the GlyphVector's location.
+     * 
+     * @return the pixel bounds
+     */
+    public Rectangle getPixelBounds(FontRenderContext frc, float x, float y) {
+        // default implementation - integer Rectangle, that encloses visual 
+        // bounds rectangle
+        Rectangle2D visualRect = getVisualBounds();
+
+        int minX = (int)Math.floor(visualRect.getMinX() + x);
+        int minY = (int)Math.floor(visualRect.getMinY() + y);
+        int width = (int)Math.ceil(visualRect.getMaxX() + x) - minX;
+        int height = (int)Math.ceil(visualRect.getMaxY() + y) - minY;
+
+        return new Rectangle(minX, minY, width, height);
+    }
+
+    /**
+     * Gets the pixel bounds of the glyph with the specified index in
+     * this GlyphVector which is rendered with the specified
+     * FontRenderContext at the specified location.
+     * 
+     * @param index the glyph index in this GlyphVector.
+     * @param frc the FontRenderContext.
+     * @param x the X coordinate of the GlyphVector's location.
+     * @param y the Y coordinate of the GlyphVector's location.
+     * 
+     * @return a Rectangle bounds.
+     */
+    public Rectangle getGlyphPixelBounds(int index, FontRenderContext frc, 
+            float x, float y) {
+        Rectangle2D visualRect = getGlyphVisualBounds(index).getBounds2D();
+
+        int minX = (int)Math.floor(visualRect.getMinX() + x);
+        int minY = (int)Math.floor(visualRect.getMinY() + y);
+        int width = (int)Math.ceil(visualRect.getMaxX() + x) - minX;
+        int height = (int)Math.ceil(visualRect.getMaxY() + y) - minY;
+
+        return new Rectangle(minX, minY, width, height);
+    }
+
+    /**
+     * Gets the visual bounds of the GlyphVector. 
+     * 
+     * @return the visual bounds of the GlyphVector.
+     */
+    public abstract Rectangle2D getVisualBounds();
+
+    /**
+     * Gets the logical bounds of the GlyphVector. 
+     * 
+     * @return the logical bounds of the GlyphVector.
+     */
+    public abstract Rectangle2D getLogicalBounds();
+
+    /**
+     * Sets the position of the specified glyph in this GlyphVector.
+     * 
+     * @param glyphIndex the glyph index in this GlyphVector.
+     * @param newPos the new position of the glyph at the specified glyphIndex.
+     */
+    public abstract void setGlyphPosition(int glyphIndex, Point2D newPos);
+
+    /**
+     * Gets the position of the specified glyph in this GlyphVector.
+     * 
+     * @param glyphIndex the glyph index in this GlyphVector.
+     * 
+     * @return the position of the specified glyph in this GlyphVector.
+     */
+    public abstract Point2D getGlyphPosition(int glyphIndex);
+
+    /**
+     * Sets the affine transform to a glyph with the specified index
+     * in this GlyphVector.
+     * 
+     * @param glyphIndex the glyth index in this GlyphVector.
+     * @param trans the AffineTransform to be assigned to the
+     * specified glyph.
+     */
+    public abstract void setGlyphTransform(int glyphIndex, 
+            AffineTransform trans);
+
+    /**
+     * Gets the transform of the specified glyph in this GlyphVector.
+     * 
+     * @param glyphIndex the glyph index in this GlyphVector.
+     * 
+     * @return the new transform of the glyph.
+     */
+    public abstract AffineTransform getGlyphTransform(int glyphIndex);
+
+    /**
+     * Compares this GlyphVector with the specified GlyphVector objects.
+     * 
+     * @param glyphVector the GlyphVector object to be compared.
+     * 
+     * @return true, if this GlyphVector is equal to the specified GlyphVector
+     * object, false otherwise.
+     */
+    public abstract boolean equals(GlyphVector glyphVector);
+
+    /**
+     * Gets the metrics of the glyph with the specified index
+     * in this GlyphVector.
+     * 
+     * @param glyphIndex index in this GlyphVector.
+     * 
+     * @return the metrics of the glyph with the specified index
+     * in this GlyphVector.
+     */
+    public abstract GlyphMetrics getGlyphMetrics(int glyphIndex);
+
+    /**
+     * Gets the justification information of the glyph 
+     * whose index is specified.
+     * 
+     * @param glyphIndex the glyph index.
+     * 
+     * @return the GlyphJustificationInfo for the specified glyph. 
+     */
+    public abstract GlyphJustificationInfo getGlyphJustificationInfo(
+            int glyphIndex);
+
+    /**
+     * Gets the FontRenderContext of this GlyphVector.
+     * 
+     * @return the FontRenderContext of this GlyphVector.
+     */
+    public abstract FontRenderContext getFontRenderContext();
+
+    /**
+     * Gets a Shape object which defines the visual representation 
+     * of the specified glyph in this GlyphVector, translated a 
+     * distance of x in the X direction and y in the Y direction. 
+     * 
+     * @param glyphIndex the glyth index in this GlyphVector.
+     * @param x the distance in the X direction to translate the 
+     * shape object before returning it.
+     * @param y the distance in the Y direction to translate the 
+     * shape object before returning it.
+     * 
+     * @return a Shape object which represents the visual representation 
+     * of the specified glyph in this GlyphVector - glyph outline. 
+     */
+    public Shape getGlyphOutline(int glyphIndex, float x, float y) {
+        Shape initialShape = getGlyphOutline(glyphIndex);
+        AffineTransform trans = AffineTransform.getTranslateInstance(x, y);
+        return trans.createTransformedShape(initialShape);
+    }
+
+    /**
+     * Gets the visual bounds of the specified glyph in the GlyphVector.
+     * 
+     * @param glyphIndex the glyph index in this GlyphVector.
+     * 
+     * @return the glyph visual bounds of the glyph with the specified
+     * index in the GlyphVector.
+     */
+    public abstract Shape getGlyphVisualBounds(int glyphIndex);
+
+    /**
+     * Gets a Shape object which defines the visual representation 
+     * of the specified glyph in this GlyphVector. 
+     *  
+     * @param glyphIndex the glyth index in this GlyphVector.
+     * 
+     * @return a Shape object which represents the visual representation 
+     * of the specified glyph in this GlyphVector - glyph outline. 
+     */
+    public abstract Shape getGlyphOutline(int glyphIndex);
+
+    /**
+     * Gets the logical bounds of the specified glyph in 
+     * the GlyphVector. 
+     * 
+     * @param glyphIndex the index in this GlyphVector of the glyph from which 
+     * to retrieve its logical bounds
+     * 
+     * @return the logical bounds of the specified glyph in 
+     * the GlyphVector.
+     */
+    public abstract Shape getGlyphLogicalBounds(int glyphIndex);
+
+    /**
+     * Gets the visual representation of this GlyphVector rendered in
+     * x, y location as a Shape object.
+     * 
+     * @param x the x coordinate of the GlyphVector.
+     * @param y the y coordinate of the GlyphVector.
+     * 
+     * @return the visual representation of this GlyphVector as a Shape object.
+     */
+    public abstract Shape getOutline(float x, float y);
+
+    /**
+     * Gets the visual representation of this GlyphVector as a Shape object.
+     * 
+     * @return the visual representation of this GlyphVector as a Shape object.
+     */
+    public abstract Shape getOutline();
+
+    /**
+     * Gets the font of this GlyphVector.
+     * 
+     * @return the font of this GlyphVector.
+     */
+    public abstract Font getFont();
+
+    /**
+     * Gets an array of the glyph codes of the specified glyphs.
+     * 
+     * @param beginGlyphIndex the index into this GlyphVector at which 
+     * to start retrieving glyph codes.
+     * @param numEntries the number of glyph codes.
+     * @param codeReturn the array into which the resulting 
+     * glyphcodes will be written.
+     * 
+     * @return the array of the glyph codes.
+     */
+    public abstract int[] getGlyphCodes(int beginGlyphIndex, int numEntries, 
+            int[] codeReturn);
+
+    /**
+     * Gets an array of the character indices of 
+     * the specified glyphs.
+     * 
+     * @param beginGlyphIndex the index of the first glyph to return information for.
+     * @param numEntries the number of glyph indices to return.
+     * @param codeReturn the array into which the resulting character 
+     * indices will be written.
+     * 
+     * @return an array of character indices for the specifies glyphs.
+     */
+    public int[] getGlyphCharIndices(int beginGlyphIndex, int numEntries, 
+            int[] codeReturn) {
+        if (codeReturn == null) {
+            codeReturn = new int[numEntries];
+        }
+
+        for (int i = 0; i < numEntries; i++){
+            codeReturn[i] = getGlyphCharIndex(i+beginGlyphIndex);
+        }
+        return codeReturn;
+    }
+
+    /**
+     * Gets an array of the positions of the specified glyphs in 
+     * this GlyphVector.
+     * 
+     * @param beginGlyphIndex the index of the first glyph to return information for.
+     * @param numEntries the number of glyphs to return information for.
+     * @param positionReturn the array where the result will be stored. 
+     * 
+     * @return an array of glyph positions.
+     */
+    public abstract float[] getGlyphPositions(int beginGlyphIndex, 
+            int numEntries, float[] positionReturn);
+
+    /**
+     * Gets the glyph code of the specified glyph.
+     * 
+     * @param glyphIndex the index in this GlyphVector which corresponds 
+     * to the glyph from which to retrieve the glyphcode.
+     * 
+     * @return the glyphcode of the specified glyph.
+     */
+    public abstract int getGlyphCode(int glyphIndex);
+
+    /**
+     * Gets the first logical character's index of the specified glyph. 
+     *  
+     * @param glyphIndex the glyph index.
+     * 
+     * @return the the first logical character's index.
+     */
+    public int getGlyphCharIndex(int glyphIndex){
+        // default implemetation one-to-one
+        return glyphIndex;
+    }
+
+    /**
+     * Sets default layout to this GlyphVector. 
+     */
+    public abstract void performDefaultLayout();
+
+    /**
+     * Gets the number of glyphs in the GlyphVector.
+     * 
+     * @return the number of glyphs in the GlyphVector.
+     */
+    public abstract int getNumGlyphs();
+
+    /**
+     * Gets flags which describe the global state of the GlyphVector. 
+     * The default implementation returns 0.
+     * 
+     * @return the layout flags
+     */
+    public int getLayoutFlags(){
+        // default implementation - returned value is 0
+        return 0;
+    }
+
+}
+
diff --git a/awt/java/awt/font/GraphicAttribute.java b/awt/java/awt/font/GraphicAttribute.java
new file mode 100644
index 0000000..2f41951
--- /dev/null
+++ b/awt/java/awt/font/GraphicAttribute.java
@@ -0,0 +1,196 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Ilya S. Okomin
+ * @version $Revision$
+ */
+package java.awt.font;
+
+import java.awt.Graphics2D;
+import java.awt.geom.Rectangle2D;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The GraphicAttribute abstract class provides an opportunity to
+ * insert graphical elements in printed text.   
+ */
+public abstract class GraphicAttribute {
+
+    /** 
+     * The Constant TOP_ALIGNMENT indicates using the top line to 
+     * calculate placement of graphics.
+     */
+    public static final int TOP_ALIGNMENT = -1;
+
+    /** 
+     * The Constant BOTTOM_ALIGNMENT indicates using the bottom line to 
+     * calculate placement of graphics. 
+     */
+    public static final int BOTTOM_ALIGNMENT = -2;
+
+    /** 
+     * The Constant ROMAN_BASELINE indicates the placement of the roman 
+     * baseline with respect to the graphics origin.
+     */
+    public static final int ROMAN_BASELINE = 0;
+
+    /** 
+     * The Constant CENTER_BASELINE indicates the placement of the center 
+     * baseline with respect to the graphics origin.
+     */
+    public static final int CENTER_BASELINE = 1;
+
+    /** 
+     * The Constant HANGING_BASELINE indicates the placement of the hanging 
+     * baseline with respect to the graphics origin. 
+     */
+    public static final int HANGING_BASELINE = 2;
+
+    // the alignment of this GraphicAttribute
+    /** The alignment. */
+    private int alignment;
+
+    /**
+     * Instantiates a new graphic attribute with the specified alignment.
+     * 
+     * @param align the specified alignment.
+     */
+    protected GraphicAttribute(int align) {
+        if ((align < BOTTOM_ALIGNMENT) || (align > HANGING_BASELINE)) {
+            // awt.198=Illegal alignment argument
+            throw new IllegalArgumentException(Messages.getString("awt.198")); //$NON-NLS-1$
+        }
+        this.alignment = align;
+    }
+
+    /**
+     * Draws the GraphicAttribute at the specified location.
+     * 
+     * @param graphics the Graphics.
+     * @param x the X coordinate of GraphicAttribute location.
+     * @param y the Y coordinate of GraphicAttribute location.
+     */
+    public abstract void draw(Graphics2D graphics, float x, float y);
+
+    /**
+     * Gets the GraphicAttribute's advance. It's the distance from the point 
+     * at which the graphic is rendered and the point where the next character 
+     * or graphic is rendered.
+     * 
+     * @return the GraphicAttribute's advance.
+     */
+    public abstract float getAdvance();
+
+    /**
+     * Gets the alignment of this GraphicAttribute.
+     * 
+     * @return the alignment of this GraphicAttribute.
+     */
+    public final int getAlignment() {
+        return this.alignment;
+    }
+
+    /**
+     * Gets the ascent of this GraphicAttribute.
+     * 
+     * @return the ascent of this GraphicAttribute.
+     */
+    public abstract float getAscent();
+
+    /**
+     * Gets the bounds of this GraphicAttribute.
+     * 
+     * @return the bounds of this GraphicAttribute.
+     */
+    public Rectangle2D getBounds() {
+        float ascent = getAscent();
+        float advance = getAdvance();
+        float descent = getDescent();
+
+        // Default implementation - see API documentation.
+        return new Rectangle2D.Float(0, -ascent, advance, ascent + descent);
+    }
+
+    /**
+     * Gets the descent of this GraphicAttribute.
+     * 
+     * @return the descent of this GraphicAttribute.
+     */
+    public abstract float getDescent();
+
+    /**
+     * Gets the GlyphJustificationInfo of this GraphicAttribute.
+     * 
+     * @return the GlyphJustificationInfo of this GraphicAttribute.
+     */
+    public GlyphJustificationInfo getJustificationInfo() {
+        
+        /* Default implementation.
+         * Since documentation doesn't describe default values,
+         * they were calculated based on 1.5 release 
+         * behavior and can be obtained using next test sample:
+         * 
+         *    // Create GraphicAttribute class implementation
+         *    public class MyGraphicAttribute extends GraphicAttribute {
+         *        protected MyGraphicAttribute(int align) {
+         *            super(align);
+         *        }
+         *
+         *        public float getDescent() {
+         *           return 0;
+         *        }
+         *
+         *        public float getAdvance() {
+         *           return 1;
+         *        }
+         *
+         *        public void draw(Graphics2D g2, float x, float y) {
+         *        }
+         *
+         *        public float getAscent() {
+         *            return 0;
+         *        }
+         *    }
+         *
+         *    MyGraphicAttribute myGA = gat.new MyGraphicAttribute(0);
+         *    // print justification parameters
+         *    System.out.println(myGA.getJustificationInfo().growAbsorb);
+         *    System.out.println(myGA.getJustificationInfo().shrinkAbsorb);
+         *    System.out.println(myGA.getJustificationInfo().growLeftLimit);
+         *    System.out.println(myGA.getJustificationInfo().growPriority);
+         *    System.out.println(myGA.getJustificationInfo().growRightLimit);
+         *    System.out.println(myGA.getJustificationInfo().shrinkLeftLimit);
+         *    System.out.println(myGA.getJustificationInfo().shrinkPriority);
+         *    System.out.println(myGA.getJustificationInfo().shrinkRightLimit);
+         *    System.out.println(myGA.getJustificationInfo().weight);
+         */
+        float advance = getAdvance();
+        return new GlyphJustificationInfo(
+                                    advance,
+                                    false,
+                                    GlyphJustificationInfo.PRIORITY_INTERCHAR,
+                                    advance / 3,
+                                    advance / 3,
+                                    false,
+                                    GlyphJustificationInfo.PRIORITY_WHITESPACE,
+                                    0,
+                                    0);
+    }
+
+}
+
diff --git a/awt/java/awt/font/ImageGraphicAttribute.java b/awt/java/awt/font/ImageGraphicAttribute.java
new file mode 100644
index 0000000..41f90b8
--- /dev/null
+++ b/awt/java/awt/font/ImageGraphicAttribute.java
@@ -0,0 +1,179 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Ilya S. Okomin
+ * @version $Revision$
+ */
+package java.awt.font;
+
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.geom.Rectangle2D;
+
+import org.apache.harmony.misc.HashCode;
+
+/**
+ * The ImageGraphicAttribute class provides an opportunity to insert 
+ * images to a text.
+ */
+public final class ImageGraphicAttribute extends GraphicAttribute {
+
+    // Image object rendered by this ImageGraphicAttribute
+    /** The image. */
+    private Image fImage;
+
+    // X coordinate of the origin point
+    /** The origin x. */
+    private float fOriginX;
+
+    // Y coordinate of the origin point
+    /** The origin y. */
+    private float fOriginY;
+
+    // the width of the image object
+    /** The img width. */
+    private float fImgWidth;
+
+    // the height of the image object
+    /** The img height. */
+    private float fImgHeight;
+
+    /**
+     * Instantiates a new ImageGraphicAttribute with the specified image,
+     * alignment and origins.
+     * 
+     * @param image the Image to be rendered by ImageGraphicAttribute.
+     * @param alignment the alignment of the ImageGraphicAttribute.
+     * @param originX the origin X coordinate in the image of
+     * ImageGraphicAttribute.  
+     * @param originY the origin Y coordinate in the image of
+     * ImageGraphicAttribute.  
+     */
+    public ImageGraphicAttribute(Image image, int alignment, float originX, 
+            float originY) {
+        super(alignment);
+
+        this.fImage = image;
+        this.fOriginX = originX;
+        this.fOriginY = originY;
+
+        this.fImgWidth = fImage.getWidth(null);
+        this.fImgHeight = fImage.getHeight(null);
+
+    }
+
+    /**
+     * Instantiates a new ImageGraphicAttribute with the specified image and
+     * alignment.
+     * 
+     * @param image the Image to be rendered by ImageGraphicAttribute.
+     * @param alignment the alignment of the ImageGraphicAttribute.
+     */
+    public ImageGraphicAttribute(Image image, int alignment) {
+        this(image, alignment, 0, 0);
+    }
+
+    /**
+     * Returns a hash code of this ImageGraphicAttribute object.
+     * 
+     * @return the hash code of this ImageGraphicAttribute object.
+     */
+    @Override
+    public int hashCode() {
+        HashCode hash = new HashCode();
+
+        hash.append(fImage.hashCode());
+        hash.append(getAlignment());
+        return hash.hashCode();
+    }
+
+    /**
+     * Compares the specified ImageGraphicAttribute object with this
+     * ImageGraphicAttribute object.
+     * 
+     * @param iga the ImageGraphicAttribute object to be compared.
+     * 
+     * @return true, if the specified ImageGraphicAttribute object is equal to
+     * this ImageGraphicAttribute object, false otherwise.
+     */
+    public boolean equals(ImageGraphicAttribute iga) {
+        if (iga == null) {
+            return false;
+        }
+
+        if (iga == this) {
+            return true;
+        }
+
+        return (fOriginX == iga.fOriginX &&
+                fOriginY == iga.fOriginY &&
+                getAlignment() == iga.getAlignment() &&
+                fImage.equals(iga.fImage));
+    }
+
+    /**
+     * Compares the specified Object with this ImageGraphicAttribute object.
+     *  
+     * @param obj the Object to be compared.
+     * 
+     * @return true, if the specified Object is equal to this
+     * ImageGraphicAttribute object, false otherwise.
+     */
+    @Override
+    public boolean equals(Object obj) {
+        try {
+            return equals((ImageGraphicAttribute) obj);
+        }
+        catch(ClassCastException e) {
+            return false;
+        }
+
+    }
+
+    @Override
+    public void draw(Graphics2D g2, float x, float y) {
+        g2.drawImage(fImage, (int)(x - fOriginX), (int)(y - fOriginY), null);
+    }
+
+    /** 
+     * @see java.awt.font.GraphicAttribute#getAdvance()
+     */
+    @Override
+    public float getAdvance() {
+        return Math.max(0, fImgWidth - fOriginX);
+    }
+
+    @Override
+    public float getAscent() {
+        return Math.max(0, fOriginY);
+    }
+
+    @Override
+    public Rectangle2D getBounds() {
+        return new Rectangle2D.Float(-fOriginX, -fOriginY, fImgWidth, fImgHeight);
+    }
+
+    /** 
+     * @see java.awt.font.GraphicAttribute#getDescent()
+     */
+    @Override
+    public float getDescent() {
+        return Math.max(0, fImgHeight - fOriginY);
+    }
+
+}
+
diff --git a/awt/java/awt/font/LineBreakMeasurer.java b/awt/java/awt/font/LineBreakMeasurer.java
new file mode 100644
index 0000000..efce615
--- /dev/null
+++ b/awt/java/awt/font/LineBreakMeasurer.java
@@ -0,0 +1,231 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/*
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ */
+
+package java.awt.font;
+
+import java.text.AttributedCharacterIterator;
+//???AWT: import java.text.BreakIterator;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The class LineBreakMeasurer provides methods to measure the graphical 
+ * representation of a text in order to determine where to add line 
+ * breaks so the resulting line of text fits its wrapping width. 
+ * The wrapping width defines the visual width of the paragraph.
+ */
+public final class LineBreakMeasurer {
+    
+    /** The tm. */
+    private TextMeasurer tm = null;
+    //???AWT private BreakIterator bi = null;
+    /** The position. */
+    private int position = 0;
+    
+    /** The maxpos. */
+    int maxpos = 0;
+
+    /**
+     * Instantiates a new LineBreakMeasurer object for the specified text.
+     * 
+     * @param text the AttributedCharacterIterator object which contains
+     * text with at least one character.
+     * @param frc the FontRenderContext represented information
+     * about graphic device.
+     */
+    public LineBreakMeasurer(AttributedCharacterIterator text, FontRenderContext frc) {
+        //???AWT: this(text, BreakIterator.getLineInstance(), frc);
+    }
+
+    /* ???AWT
+    public LineBreakMeasurer(
+            AttributedCharacterIterator text,
+            BreakIterator bi,
+            FontRenderContext frc
+    ) {
+        tm = new TextMeasurer(text, frc);
+        this.bi = bi;
+        this.bi.setText(text);
+        position = text.getBeginIndex();
+        maxpos = tm.aci.getEndIndex();
+    }
+    */
+
+    /**
+     * Deletes a character from the specified position of the text, 
+     * updates this LineBreakMeasurer object.
+     * 
+     * @param newText the new text.
+     * @param pos the posion of the character which is deleted.
+     */
+    public void deleteChar(AttributedCharacterIterator newText, int pos) {
+        tm.deleteChar(newText, pos);
+        //???AWT: bi.setText(newText);
+
+        position = newText.getBeginIndex();
+
+        maxpos--;
+    }
+
+    /**
+     * Gets current position of this LineBreakMeasurer.
+     * 
+     * @return current position of this LineBreakMeasurer
+     */
+    public int getPosition() {
+        return position;
+    }
+
+    /**
+     * Insertes a character at the specified position in the text, 
+     * updates this LineBreakMeasurer object.
+     * 
+     * @param newText the new text.
+     * @param pos the posion of the character which is inserted.
+     */
+    public void insertChar(AttributedCharacterIterator newText, int pos) {
+        tm.insertChar(newText, pos);
+//      ???AWT: bi.setText(newText);
+
+        position = newText.getBeginIndex();
+
+        maxpos++;
+    }
+
+    /**
+     * Returns the next line of text, updates current position in this 
+     * LineBreakMeasurer.
+     * 
+     * @param wrappingWidth the maximum visible line width.
+     * @param offsetLimit the limit point withing the text indicating
+     * that no further text should be included on the line; the paragraph break.
+     * @param requireNextWord if true, null is returned (the entire word at the current 
+     * position does not fit within the wrapping width);  
+     * if false, a valid layout is returned that includes at least the 
+     * character at the current position.
+     * 
+     * @return the next TextLayout which begins at the current position and 
+     * represents the next line of text with width wrappingWidth, null is 
+     * returned if the entire word at the current position does not fit within 
+     * the wrapping width.
+     */
+    public TextLayout nextLayout(float wrappingWidth, int offsetLimit, boolean requireNextWord) {
+        if (position == maxpos) {
+            return null;
+        }
+
+        int nextPosition = nextOffset(wrappingWidth, offsetLimit, requireNextWord);
+
+        if (nextPosition == position) {
+            return null;
+        }
+        TextLayout layout = tm.getLayout(position, nextPosition);
+        position = nextPosition;
+        return layout;
+    }
+
+    /**
+     * Returns the next line of text.
+     * 
+     * @param wrappingWidth the maximum visible line width.
+     * 
+     * @return the next line of text.
+     */
+    public TextLayout nextLayout(float wrappingWidth) {
+        return nextLayout(wrappingWidth, maxpos, false);
+    }
+
+    /**
+     * Returns the end position of the next line of text.
+     * 
+     * @param wrappingWidth the maximum visible line width.
+     * 
+     * @return the end position of the next line of text.
+     */
+    public int nextOffset(float wrappingWidth) {
+        return nextOffset(wrappingWidth, maxpos, false);
+    }
+
+    /**
+     * Returns the end position of the next line of text.
+     * 
+     * @param wrappingWidth the maximum visible line width.
+     * @param offsetLimit the limit point withing the text indicating
+     * that no further text should be included on the line; the paragraph break.
+     * @param requireNextWord if true, the current position is returned 
+     * if the entire next word does not fit within wrappingWidth; 
+     * if false, the offset returned is at least one greater than the current
+     * position.
+     * 
+     * @return the end position of the next line of text.
+     * 
+     * @throws IllegalArgumentException if the offsetLimit is less than 
+     * the current position.
+     */
+    public int nextOffset(float wrappingWidth, int offsetLimit, boolean requireNextWord) {
+        if (offsetLimit <= position) {
+            // awt.203=Offset limit should be greater than current position. 
+            throw new IllegalArgumentException(Messages.getString("awt.203")); //$NON-NLS-1$
+        }
+
+        if (position == maxpos) {
+            return position;
+        }
+
+        int breakPos = tm.getLineBreakIndex(position, wrappingWidth);
+        int correctedPos = breakPos;
+
+        // This check is required because bi.preceding(maxpos) throws an exception
+        /* ???AWT
+        if (breakPos == maxpos) {
+            correctedPos = maxpos;
+        } else if (Character.isWhitespace(bi.getText().setIndex(breakPos))) {
+            correctedPos = bi.following(breakPos);
+        } else {
+            correctedPos = bi.preceding(breakPos);
+        }
+        */
+        
+        if (position >= correctedPos) {
+            if (requireNextWord) {
+                correctedPos = position;
+            } else {
+                correctedPos = Math.max(position+1, breakPos);
+            }
+        }
+
+        return Math.min(correctedPos, offsetLimit);
+    }
+
+    /**
+     * Sets the new position of this LineBreakMeasurer.
+     * 
+     * @param pos the new position of this LineBreakMeasurer.
+     */
+    public void setPosition(int pos) {
+        if (tm.aci.getBeginIndex() > pos || maxpos < pos) {
+            // awt.33=index is out of range
+            throw new IllegalArgumentException(Messages.getString("awt.33")); //$NON-NLS-1$
+        }
+        position = pos;
+    }
+}
+
diff --git a/awt/java/awt/font/LineMetrics.java b/awt/java/awt/font/LineMetrics.java
new file mode 100644
index 0000000..2857187
--- /dev/null
+++ b/awt/java/awt/font/LineMetrics.java
@@ -0,0 +1,115 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Ilya S. Okomin
+ * @version $Revision$
+ */
+package java.awt.font;
+
+/**
+ * The LineMetrics class provides information such as concerning how the text 
+ * is positioned with respect to the base line, such as ascent, descent, 
+ * and leading.
+ * 
+ */
+public abstract class LineMetrics {
+
+    /**
+     * Gets the baseline offsets of the text according to the 
+     * the baseline of this text.
+     * 
+     * @return the baseline offsets of the text according to the 
+     * the baseline of this text.
+     */
+    public abstract float[] getBaselineOffsets();
+
+    /**
+     * Gets the number of characters of the text.
+     * 
+     * @return the number of characters of the text.
+     */
+    public abstract int getNumChars();
+
+    /**
+     * Gets the baseline index, returns one of the following 
+     * index: ROMAN_BASELINE, CENTER_BASELINE, HANGING_BASELINE.
+     * 
+     * @return the baseline index: ROMAN_BASELINE, CENTER_BASELINE
+     * or HANGING_BASELINE.
+     */
+    public abstract int getBaselineIndex();
+
+    /**
+     * Gets the thickness of the underline.
+     * 
+     * @return the thickness of the underline.
+     */
+    public abstract float getUnderlineThickness();
+
+    /**
+     * Gets the offset of the underline.
+     * 
+     * @return the offset of the underline.
+     */
+    public abstract float getUnderlineOffset();
+
+    /**
+     * Gets the thickness of strike through line.
+     * 
+     * @return the thickness of strike through line.
+     */
+    public abstract float getStrikethroughThickness();
+
+    /**
+     * Gets the offset of the strike through line.
+     * 
+     * @return the offset of the strike through line.
+     */
+    public abstract float getStrikethroughOffset();
+
+    /**
+     * Gets the leading of the text.
+     * 
+     * @return the leading of the text.
+     */
+    public abstract float getLeading();
+
+    /**
+     * Gets the height of the text as a sum of the ascent, the descent 
+     * and the leading.
+     * 
+     * @return the height of the text as a sum of the ascent, the descent 
+     * and the leading.
+     */
+    public abstract float getHeight();
+
+    /**
+     * Gets the descent of the text.
+     * 
+     * @return the descent of the text.
+     */
+    public abstract float getDescent();
+
+    /**
+     * Gets the ascent of the text.
+     * 
+     * @return the ascent of the text.
+     */
+    public abstract float getAscent();
+
+}
+
diff --git a/awt/java/awt/font/MultipleMaster.java b/awt/java/awt/font/MultipleMaster.java
new file mode 100644
index 0000000..773bfcf
--- /dev/null
+++ b/awt/java/awt/font/MultipleMaster.java
@@ -0,0 +1,86 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Ilya S. Okomin
+ * @version $Revision$
+ */
+package java.awt.font;
+
+import java.awt.Font;
+
+/**
+ * The MultipleMaster interface provides methods to manipulate MultipleMaster 
+ * type fonts and retrieve graphical and design data from them.
+ */
+public interface MultipleMaster {
+
+    /**
+     * Derives a new multiple master font based on the specified 
+     * parameters.
+     * 
+     * @param glyphWidths float array which represents width of each glyph
+     * in font space.
+     * @param avgStemWidth the average stem width in font space.
+     * @param typicalCapHeight the typical upper case char height.
+     * @param typicalXHeight the typical lower case char height.
+     * @param italicAngle the slope angle for italics.
+     * 
+     * @return a MultipleMaster font.
+     */
+    public Font deriveMMFont(float[] glyphWidths, float avgStemWidth,
+            float typicalCapHeight, float typicalXHeight, float italicAngle);
+
+    /**
+     * Derives a new multiple master font based on the design axis values 
+     * contained in the specified array. 
+     * 
+     * @param axes an float array which contains axis values.
+     * 
+     * @return a MultipleMaster font.
+     */
+    public Font deriveMMFont(float[] axes);
+
+    /**
+     * Gets default design values for the axes.
+     * 
+     * @return the default design values for the axes.
+     */
+    public float[] getDesignAxisDefaults();
+
+    /**
+     * Gets the array of design axis names. 
+     * 
+     * @return the array of design axis names. 
+     */
+    public String[] getDesignAxisNames();
+
+    /**
+     * Gets the array of design axis ranges. 
+     * 
+     * @return the array of design axis ranges.
+     */
+    public float[] getDesignAxisRanges();
+
+    /**
+     * Gets the number of multiple master design controls. 
+     * 
+     * @return the number of multiple master design controls.
+     */
+    public int getNumDesignAxes();
+
+}
+
diff --git a/awt/java/awt/font/OpenType.java b/awt/java/awt/font/OpenType.java
new file mode 100644
index 0000000..53cb6c0
--- /dev/null
+++ b/awt/java/awt/font/OpenType.java
@@ -0,0 +1,410 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Ilya S. Okomin
+ * @version $Revision$
+ */
+package java.awt.font;
+
+/**
+ * The OpenType interface provides constants and methods for getting 
+ * instance data for fonts of type OpenType and TrueType. For more information,
+ * see the <a href="http://partners.adobe.com/public/developer/opentype/index_spec.html">OpenType specification</a>.
+ */
+public interface OpenType {
+
+    /** 
+     * The Constant TAG_ACNT indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_ACNT = 1633906292;
+
+    /** 
+     * The Constant TAG_AVAR indicates corresponding table tag 
+     * in the Open Type Specification. 
+     */
+    public static final int TAG_AVAR = 1635148146;
+
+    /** 
+     * The Constant TAG_BASE indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_BASE = 1111577413;
+
+    /** 
+     * The Constant TAG_BDAT indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_BDAT = 1650745716;
+
+    /** 
+     * The Constant TAG_BLOC indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_BLOC = 1651273571;
+
+    /** 
+     * The Constant TAG_BSLN indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_BSLN = 1651731566;
+
+    /** 
+     * The Constant TAG_CFF indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_CFF = 1128678944;
+
+    /** 
+     * The Constant TAG_CMAP indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_CMAP = 1668112752;
+
+    /** 
+     * The Constant TAG_CVAR indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_CVAR = 1668702578;
+
+    /** 
+     * The Constant TAG_CVT indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_CVT = 1668707360;
+
+    /** 
+     * The Constant TAG_DSIG indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_DSIG = 1146308935;
+
+    /** 
+     * The Constant TAG_EBDT indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_EBDT = 1161970772;
+
+    /** 
+     * The Constant TAG_EBLC indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_EBLC = 1161972803;
+
+    /** 
+     * The Constant TAG_EBSC  indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_EBSC = 1161974595;
+
+    /** 
+     * The Constant TAG_FDSC indicates corresponding table tag 
+     * in the Open Type Specification. 
+     */
+    public static final int TAG_FDSC = 1717859171;
+
+    /** 
+     * The Constant TAG_FEAT indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_FEAT = 1717920116;
+
+    /** 
+     * The Constant TAG_FMTX indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_FMTX = 1718449272;
+
+    /** 
+     * The Constant TAG_FPGM indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_FPGM = 1718642541;
+
+    /** 
+     * The Constant TAG_FVAR indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_FVAR = 1719034226;
+
+    /** 
+     * The Constant TAG_GASP indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_GASP = 1734439792;
+
+    /** 
+     * The Constant TAG_GDEF indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_GDEF = 1195656518;
+
+    /** 
+     * The Constant TAG_GLYF indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_GLYF = 1735162214;
+
+    /** 
+     * The Constant TAG_GPOS indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_GPOS = 1196445523;
+
+    /** 
+     * The Constant TAG_GSUB indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_GSUB = 1196643650;
+
+    /** 
+     * The Constant TAG_GVAR indicates corresponding table tag 
+     * in the Open Type Specification. 
+     */
+    public static final int TAG_GVAR = 1735811442;
+
+    /** 
+     * The Constant TAG_HDMX indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_HDMX = 1751412088;
+
+    /** 
+     * The Constant TAG_HEAD indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_HEAD = 1751474532;
+
+    /** 
+     * The Constant TAG_HHEA indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_HHEA = 1751672161;
+
+    /** 
+     * The Constant TAG_HMTX indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_HMTX = 1752003704;
+
+    /** 
+     * The Constant TAG_JSTF indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_JSTF = 1246975046;
+
+    /** 
+     * The Constant TAG_JUST indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_JUST = 1786082164;
+
+    /** 
+     * The Constant TAG_KERN indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_KERN = 1801810542;
+
+    /** 
+     * The Constant TAG_LCAR indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_LCAR = 1818452338;
+
+    /** 
+     * The Constant TAG_LOCA indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_LOCA = 1819239265;
+
+    /** 
+     * The Constant TAG_LTSH indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_LTSH = 1280594760;
+
+    /** 
+     * The Constant TAG_MAXP indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_MAXP = 1835104368;
+
+    /** 
+     * The Constant TAG_MMFX indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_MMFX = 1296909912;
+
+    /** 
+     * The Constant TAG_MMSD indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_MMSD = 1296913220;
+
+    /** 
+     * The Constant TAG_MORT indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_MORT = 1836020340;
+
+    /** 
+     * The Constant TAG_NAME indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_NAME = 1851878757;
+
+    /** 
+     * The Constant TAG_OPBD indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_OPBD = 1836020340;
+
+    /** 
+     * The Constant TAG_OS2 indicates corresponding table tag 
+     * in the Open Type Specification. 
+     */
+    public static final int TAG_OS2 = 1330851634;
+
+    /** 
+     * The Constant TAG_PCLT  indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_PCLT = 1346587732;
+
+    /** 
+     * The Constant TAG_POST indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_POST = 1886352244;
+
+    /** 
+     * The Constant TAG_PREP indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_PREP = 1886545264;
+
+    /** 
+     * The Constant TAG_PROP indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_PROP = 1886547824;
+
+    /** 
+     * The Constant TAG_TRAK indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_TRAK = 1953653099;
+
+    /** 
+     * The Constant TAG_TYP1 indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_TYP1 = 1954115633;
+
+    /** 
+     * The Constant TAG_VDMX indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_VDMX = 1447316824;
+
+    /** 
+     * The Constant TAG_VHEA indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_VHEA = 1986553185;
+
+    /** 
+     * The Constant TAG_VMTX indicates corresponding table tag 
+     * in the Open Type Specification.
+     */
+    public static final int TAG_VMTX = 1986884728;
+
+    /**
+     * Returns the OpenType font version.
+     * 
+     * @return the the OpenType font version.
+     */
+    public int getVersion();
+
+    /**
+     * Gets the table for a specified tag. 
+     * Sfnt tables include cmap, name and head items. 
+     *  
+     * @param sfntTag the sfnt tag.
+     * 
+     * @return a byte array contains the font data corresponding 
+     * to the specified tag.
+     */
+    public byte[] getFontTable(int sfntTag);
+
+    /**
+     * Gets the table for a specified tag. 
+     * Sfnt tables include cmap, name and head items. 
+     *  
+     * @param sfntTag the sfnt tag.
+     * @param offset the offset of the returned table.
+     * @param count the number of returned table.
+     * 
+     * @return the table corresponding to sfntTag and containing 
+     * the bytes starting at offset byte and including count bytes.
+     */
+    public byte[] getFontTable(int sfntTag, int offset, int count);
+
+    /**
+     * Gets the table for a specified tag. 
+     * Sfnt tables include cmap, name and head items.
+     * 
+     * @param strSfntTag the str sfnt tag as a String.
+     * 
+     * @return a byte array contains the font data corresponding 
+     * to the specified tag.
+     */
+    public byte[] getFontTable(String strSfntTag);
+
+    /**
+     * Gets the table for a specified tag. 
+     * Sfnt tables include cmap, name and head items. 
+     *  
+     * @param strSfntTag the sfnt tag as a String.
+     * @param offset the offset of the returned table.
+     * @param count the number of returned table.
+     * 
+     * @return the table corresponding to sfntTag and containing 
+     * the bytes starting at offset byte and including count bytes.
+     */
+    public byte[] getFontTable(String strSfntTag, int offset, int count);
+
+    /**
+     * Gets the table size for a specified tag. 
+     * 
+     * @param strSfntTag the sfnt tag as a String.
+     * 
+     * @return the table size for a specified tag.
+     */
+    public int getFontTableSize(String strSfntTag);
+
+    /**
+     * Gets the table size for a specified tag. 
+     * 
+     * @param sfntTag the sfnt tag.
+     * 
+     * @return the table size for a specified tag.
+     */
+    public int getFontTableSize(int sfntTag);
+
+}
+
diff --git a/awt/java/awt/font/ShapeGraphicAttribute.java b/awt/java/awt/font/ShapeGraphicAttribute.java
new file mode 100644
index 0000000..45199fd
--- /dev/null
+++ b/awt/java/awt/font/ShapeGraphicAttribute.java
@@ -0,0 +1,195 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Ilya S. Okomin
+ * @version $Revision$
+ */
+package java.awt.font;
+
+import java.awt.BasicStroke;
+import java.awt.Graphics2D;
+import java.awt.Shape;
+import java.awt.Stroke;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+
+import org.apache.harmony.misc.HashCode;
+
+
+/**
+ * The ShapeGraphicAttribute class provides an opportunity to insert 
+ * shapes to a text.
+ */
+public final class ShapeGraphicAttribute extends GraphicAttribute {
+
+    // shape to render
+    /** The shape. */
+    private Shape fShape;
+    
+    // flag, if the shape should be stroked (true) or filled (false)
+    /** The stroke. */
+    private boolean fStroke;
+
+    // bounds of the shape
+    /** The bounds. */
+    private Rectangle2D fBounds;
+    
+    // X coordinate of the origin point
+    /** The origin x. */
+    private float fOriginX;
+    
+    // Y coordinate of the origin point
+    /** The origin y. */
+    private float fOriginY;
+
+    // width of the shape
+    /** The shape width. */
+    private float fShapeWidth;
+    
+    // height of the shape
+    /** The shape height. */
+    private float fShapeHeight;
+
+    /** 
+     * The Constant STROKE indicates whether the Shape is stroked 
+     * or not. 
+     */
+    public static final boolean STROKE = true;
+
+    /** 
+     * The Constant FILL indicates whether the Shape is filled 
+     * or not. */
+    public static final boolean FILL = false;
+
+    /**
+     * Instantiates a new ShapeGraphicAttribute object for the specified 
+     * Shape.
+     * 
+     * @param shape the shape to be rendered by this 
+     * ShapeGraphicAttribute.
+     * @param alignment the alignment of this ShapeGraphicAttribute.
+     * @param stroke true if the Shape is stroked,
+     *  false if the Shape is filled.
+     */
+    public ShapeGraphicAttribute(Shape shape, int alignment, boolean stroke) {
+        super(alignment);
+
+        this.fShape = shape;
+        this.fStroke = stroke;
+
+        this.fBounds  = fShape.getBounds2D();
+
+        this.fOriginX = (float)fBounds.getMinX();
+        this.fOriginY = (float)fBounds.getMinY();
+
+        this.fShapeWidth = (float)fBounds.getWidth();
+        this.fShapeHeight = (float)fBounds.getHeight();
+    }
+
+    /**
+     * Returns a hash code of this ShapeGraphicAttribute object.
+     * 
+     * @return a hash code of this ShapeGraphicAttribute object.
+     */
+    @Override
+    public int hashCode() {
+        HashCode hash = new HashCode();
+
+        hash.append(fShape.hashCode());
+        hash.append(getAlignment());
+        return hash.hashCode();
+    }
+
+    /**
+     * Compares this ShapeGraphicAttribute object to the specified
+     * ShapeGraphicAttribute object.
+     * 
+     * @param sga the ShapeGraphicAttribute object to be compared.
+     * 
+     * @return true, if this ShapeGraphicAttribute object is equal
+     * to the specified ShapeGraphicAttribute object, false otherwise.
+     */
+    public boolean equals(ShapeGraphicAttribute sga) {
+        if (sga == null) {
+            return false;
+        }
+
+        if (sga == this) {
+            return true;
+        }
+
+        return ( fStroke == sga.fStroke &&
+                getAlignment() == sga.getAlignment() &&
+                fShape.equals(sga.fShape));
+
+    }
+
+    /**
+     * Compares this ShapeGraphicAttribute object to the specified
+     * Object.
+     * 
+     * @param obj the Object to be compared.
+     * 
+     * @return true, if this ShapeGraphicAttribute object is equal
+     * to the specified Object, false otherwise.
+     */
+    @Override
+    public boolean equals(Object obj) {
+        try {
+            return equals((ShapeGraphicAttribute) obj);
+        }
+        catch(ClassCastException e) {
+            return false;
+        }
+    }
+
+    @Override
+    public void draw(Graphics2D g2, float x, float y) {
+        AffineTransform at = AffineTransform.getTranslateInstance(x, y);
+        if (fStroke == STROKE){
+            Stroke oldStroke = g2.getStroke();
+            g2.setStroke(new BasicStroke());
+            g2.draw(at.createTransformedShape(fShape));
+            g2.setStroke(oldStroke);
+        } else {
+            g2.fill(at.createTransformedShape(fShape));
+        }
+
+    }
+
+    @Override
+    public float getAdvance() {
+        return Math.max(0, fShapeWidth + fOriginX);
+    }
+
+    @Override
+    public float getAscent() {
+        return Math.max(0, -fOriginY);
+    }
+
+    @Override
+    public Rectangle2D getBounds() {
+        return (Rectangle2D)fBounds.clone();
+    }
+
+    @Override
+    public float getDescent() {
+        return Math.max(0, fShapeHeight + fOriginY);
+    }
+
+}
+
diff --git a/awt/java/awt/font/TextHitInfo.java b/awt/java/awt/font/TextHitInfo.java
new file mode 100644
index 0000000..17bbf71
--- /dev/null
+++ b/awt/java/awt/font/TextHitInfo.java
@@ -0,0 +1,216 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/*
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ */
+
+package java.awt.font;
+
+import org.apache.harmony.misc.HashCode;
+
+
+/**
+ * The TextHitInfo class provides information about a caret position 
+ * in a text model for insertion or deletion of a character in a text.
+ * The TextHitInfo defines two biases of the character: leading or trailing.
+ * Leading position means the left edge of the specified character 
+ * (TextHitInfo.leading(2) method for "text" returns the left side of "x").
+ * Trailing position means the right edge of the specified character
+ * (TextHitInfo.trailing(2) method for "text" returns the right side of "x").
+ */
+public final class TextHitInfo {
+    
+    /** The char idx. */
+    private int charIdx; // Represents character index in the line
+    
+    /** The is trailing. */
+    private boolean isTrailing;
+
+    /**
+     * Instantiates a new text hit info.
+     * 
+     * @param idx the idx
+     * @param isTrailing the is trailing
+     */
+    private TextHitInfo(int idx, boolean isTrailing) {
+        charIdx = idx;
+        this.isTrailing = isTrailing;
+    }
+
+    /**
+     * To string.
+     * 
+     * @return the string
+     */
+    @Override
+    public String toString() {
+        return new String(
+                "TextHitInfo[" + charIdx + ", " + //$NON-NLS-1$ //$NON-NLS-2$
+                (isTrailing?"Trailing":"Leading") + "]" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+        );
+    }
+
+    /**
+     * Compares this TextHitInfo object with the specified object.
+     * 
+     * @param obj the Object to be compared.
+     * 
+     * @return true, if the specified object is a TextHitInfo object 
+     * with the same data values as this TextHitInfo, false otherwise.
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof TextHitInfo) {
+            return equals((TextHitInfo) obj);
+        }
+        return false;
+    }
+
+    /**
+     * Compares this TextHitInfo object with the specified TextHitInfo
+     * object.
+     * 
+     * @param thi the TextHitInfo object to be compared.
+     * 
+     * @return true, if this TextHitInfo object has the same data values as the
+     * specified TextHitInfo object, false otherwise.
+     */
+    public boolean equals(TextHitInfo thi) {
+        return
+                thi != null &&
+                thi.charIdx == charIdx &&
+                thi.isTrailing == isTrailing;
+    }
+
+    /**
+     * Gets a TextHitInfo object with its character index 
+     * at the specified offset from the character index of 
+     * this TextHitInfo.
+     * 
+     * @param offset the offset.
+     * 
+     * @return the TextHitInfo. 
+     */
+    public TextHitInfo getOffsetHit(int offset) {
+        return new TextHitInfo(charIdx + offset, isTrailing);
+    }
+
+    /**
+     * Gets a TextHitInfo associated with the other side of 
+     * the insertion point. 
+     *  
+     * @return the other hit.
+     */
+    public TextHitInfo getOtherHit() {
+        return isTrailing ?
+                new TextHitInfo(charIdx+1, false) :
+                new TextHitInfo(charIdx-1, true);
+    }
+
+    /**
+     * Returns true if the leading edge of the character is hit,
+     * false if the trailing edge of the character is hit.
+     * 
+     * @return true if the leading edge of the character is hit,
+     * false if the trailing edge of the character is hit.
+     */
+    public boolean isLeadingEdge() {
+        return !isTrailing;
+    }
+
+    /**
+     * Hash code.
+     * 
+     * @return the int
+     */
+    @Override
+    public int hashCode() {
+        return HashCode.combine(charIdx, isTrailing);
+    }
+
+    /**
+     * Gets the insertion index.
+     * 
+     * @return the insertion index: character index if the leading edge
+     * is hit, or character index + 1 if the trailing edge is hit.   
+     */
+    public int getInsertionIndex() {
+        return isTrailing ? charIdx+1 : charIdx;
+    }
+
+    /**
+     * Gets the index of the character hit.
+     * 
+     * @return the character hit's index.
+     */
+    public int getCharIndex() {
+        return charIdx;
+    }
+
+    /**
+     * Returns a TextHitInfo associated with the trailing edge of 
+     * the character at the specified char index.
+     * 
+     * @param charIndex the char index.
+     * 
+     * @return the TextHitInfo associated with the trailing edge of 
+     * the character at the specified char index.
+     */
+    public static TextHitInfo trailing(int charIndex) {
+        return new TextHitInfo(charIndex, true);
+    }
+
+    /**
+     * Returns a TextHitInfo object associated with the leading edge 
+     * of the character at the specified char index.
+     * 
+     * @param charIndex the char index.
+     * 
+     * @return the TextHitInfo object associated with the leading edge 
+     * of the character at the specified char index.
+     */
+    public static TextHitInfo leading(int charIndex) {
+        return new TextHitInfo(charIndex, false);
+    }
+
+    /**
+     * Returns a (trailing) TextHitInfo object associated with the character 
+     * before the specified offset.
+     * 
+     * @param offset the offset.
+     * 
+     * @return the TextHitInfo object associated with the character 
+     * before the specified offset.
+     */
+    public static TextHitInfo beforeOffset(int offset) {
+        return new TextHitInfo(offset-1, true);
+    }
+
+    /**
+     * Returns a (leading) TextHitInfo object associated with the character 
+     * after the specified offset.
+     * 
+     * @param offset the offset.
+     * 
+     * @return the TextHitInfo object associated with the character 
+     * after the specified offset.
+     */
+    public static TextHitInfo afterOffset(int offset) {
+        return new TextHitInfo(offset, false);
+    }
+}
diff --git a/awt/java/awt/font/TextLayout.java b/awt/java/awt/font/TextLayout.java
new file mode 100644
index 0000000..e80afd0
--- /dev/null
+++ b/awt/java/awt/font/TextLayout.java
@@ -0,0 +1,916 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ */
+
+package java.awt.font;
+
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.GeneralPath;
+import java.text.AttributedCharacterIterator;
+import java.text.AttributedString;
+import java.util.Map;
+
+import org.apache.harmony.awt.gl.font.BasicMetrics;
+import org.apache.harmony.awt.gl.font.CaretManager;
+import org.apache.harmony.awt.gl.font.TextMetricsCalculator;
+import org.apache.harmony.awt.gl.font.TextRunBreaker;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The TextLayout class defines the graphical representation of character data.
+ * This class provides method for obtaining information about cursor 
+ * positioning and movement, split cursors for text with different directions, 
+ * logical and visual highlighting, multiple baselines, hits, justification, 
+ * ascent, descent, and advance, and rendering. A TextLayout object can be 
+ * rendered using Graphics context. 
+ */
+public final class TextLayout implements Cloneable {
+
+    /**
+     * The CaretPolicy class provides a policy for obtaining the 
+     * caret location. The single getStrongCaret method specifies 
+     * the policy.
+     */
+    public static class CaretPolicy {
+
+        /**
+         * Instantiates a new CaretPolicy.
+         */
+        public CaretPolicy() {
+            // Nothing to do
+        }
+
+        /**
+         * Returns whichever of the two specified TextHitInfo objects 
+         * has the stronger caret (higher character level) in the 
+         * specified TextLayout.
+         * 
+         * @param hit1 the first TextHitInfo of the specified TextLayout.
+         * @param hit2 the second TextHitInfo of the specified TextLayout.
+         * @param layout the TextLayout.
+         * 
+         * @return the TextHitInfo with the stronger caret.
+         */
+        public TextHitInfo getStrongCaret(TextHitInfo hit1, TextHitInfo hit2, TextLayout layout) {
+            // Stronger hit is the one with greater level.
+            // If the level is same, leading edge is stronger.
+
+            int level1 = layout.getCharacterLevel(hit1.getCharIndex());
+            int level2 = layout.getCharacterLevel(hit2.getCharIndex());
+
+            if (level1 == level2) {
+                return (hit2.isLeadingEdge() && (!hit1.isLeadingEdge())) ? hit2 : hit1;
+            }
+            return level1 > level2 ? hit1 : hit2;
+        }
+
+    }
+
+    /** 
+     * The Constant DEFAULT_CARET_POLICY indicates the default caret policy.
+     */
+    public static final TextLayout.CaretPolicy DEFAULT_CARET_POLICY = new CaretPolicy();
+
+    /** The breaker. */
+    private TextRunBreaker breaker;
+    
+    /** The metrics valid. */
+    private boolean metricsValid = false;
+    
+    /** The tmc. */
+    private TextMetricsCalculator tmc;
+    
+    /** The metrics. */
+    private BasicMetrics metrics;
+    
+    /** The caret manager. */
+    private CaretManager caretManager;
+    
+    /** The justification width. */
+    float justificationWidth = -1;
+
+    /**
+     * Instantiates a new TextLayout object from the specified string
+     * and Font.
+     * 
+     * @param string the string to be displayed.
+     * @param font the font of the text.
+     * @param frc the FontRenderContext object for obtaining
+     * information about a graphics device.
+     */
+    public TextLayout(String string, Font font, FontRenderContext frc) {
+        if (string == null){
+            // awt.01='{0}' parameter is null
+            throw new IllegalArgumentException(Messages.getString("awt.01", "string")); //$NON-NLS-1$ //$NON-NLS-2$
+        }
+        
+        if (font == null){
+            // awt.01='{0}' parameter is null
+            throw new IllegalArgumentException(Messages.getString("awt.01", "font")); //$NON-NLS-1$ //$NON-NLS-2$
+        }
+
+        if (string.length() == 0){
+            // awt.02='{0}' parameter has zero length
+            throw new IllegalArgumentException(Messages.getString("awt.02", "string")); //$NON-NLS-1$ //$NON-NLS-2$
+        }
+
+        AttributedString as = new AttributedString(string);
+        as.addAttribute(TextAttribute.FONT, font);
+        this.breaker = new TextRunBreaker(as.getIterator(), frc);
+        caretManager = new CaretManager(breaker);
+    }
+
+    /**
+     * Instantiates a new TextLayout from the specified text and 
+     * a map of attributes.
+     * 
+     * @param string the string to be displayed.
+     * @param attributes the attributes to be used for obtaining the text 
+     * style.
+     * @param frc the FontRenderContext object for obtaining
+     * information about a graphics device.
+     */
+    public TextLayout(
+            String string,
+            Map<? extends java.text.AttributedCharacterIterator.Attribute, ?> attributes,
+            FontRenderContext frc ) {
+        if (string == null){
+            // awt.01='{0}' parameter is null
+            throw new IllegalArgumentException(Messages.getString("awt.01", "string")); //$NON-NLS-1$ //$NON-NLS-2$
+        }
+        
+        if (attributes == null){
+            // awt.01='{0}' parameter is null
+            throw new IllegalArgumentException(Messages.getString("awt.01", "attributes")); //$NON-NLS-1$ //$NON-NLS-2$
+        }
+        
+        if (string.length() == 0){
+            // awt.02='{0}' parameter has zero length
+            throw new IllegalArgumentException(Messages.getString("awt.02", "string")); //$NON-NLS-1$ //$NON-NLS-2$
+        }
+        
+        
+        AttributedString as = new AttributedString(string);
+        as.addAttributes(attributes, 0, string.length());
+        this.breaker = new TextRunBreaker(as.getIterator(), frc);
+        caretManager = new CaretManager(breaker);
+    }
+
+    /**
+     * Instantiates a new TextLayout from the AttributedCharacterIterator.
+     * 
+     * @param text the AttributedCharacterIterator.
+     * @param frc the FontRenderContext object for obtaining
+     * information about a graphics device.
+     */
+    public TextLayout(AttributedCharacterIterator text, FontRenderContext frc) {
+        if (text == null){
+            // awt.03='{0}' iterator parameter is null
+            throw new IllegalArgumentException(Messages.getString("awt.03", "text")); //$NON-NLS-1$ //$NON-NLS-2$
+        }
+        
+        if (text.getBeginIndex() == text.getEndIndex()){
+            // awt.04='{0}' iterator parameter has zero length
+            throw new IllegalArgumentException(Messages.getString("awt.04", "text")); //$NON-NLS-1$ //$NON-NLS-2$
+        }
+
+        this.breaker = new TextRunBreaker(text, frc);
+        caretManager = new CaretManager(breaker);
+    }
+
+    /**
+     * Instantiates a new text layout.
+     * 
+     * @param breaker the breaker
+     */
+    TextLayout(TextRunBreaker breaker) {
+        this.breaker = breaker;
+        caretManager = new CaretManager(this.breaker);
+    }
+
+    /**
+     * Returns a hash code of this TextLayout object.
+     * 
+     * @return a hash code of this TextLayout object.
+     */
+    @Override
+    public int hashCode() {
+        return breaker.hashCode();
+    }
+
+    /**
+     * Returns a copy of this object.
+     * 
+     * @return a copy of this object.
+     */
+    @Override
+    protected Object clone() {
+        TextLayout res = new TextLayout((TextRunBreaker) breaker.clone());
+
+        if (justificationWidth >= 0) {
+            res.handleJustify(justificationWidth);
+        }
+
+        return res;
+    }
+
+    /**
+     * Compares this TextLayout object to the specified TextLayout object.
+     * 
+     * @param layout the TextLayout object to be compared.
+     * 
+     * @return true, if this TextLayout object is equal to 
+     * the specified TextLayout object, false otherwise.
+     */
+    public boolean equals(TextLayout layout) {
+        if (layout == null) {
+            return false;
+        }
+        return this.breaker.equals(layout.breaker);
+    }
+
+    /**
+     * Compares this TextLayout object to the specified Object.
+     * 
+     * @param obj the Object to be compared.
+     * 
+     * @return true, if this TextLayout object is equal to 
+     * the specified Object, false otherwise.
+     */
+    @Override
+    public boolean equals(Object obj) {
+        return obj instanceof TextLayout ? equals((TextLayout) obj) : false;
+    }
+
+    /**
+     * Gets the string representation for this TextLayout.
+     * 
+     * @return the string representation for this TextLayout.
+     */
+    @Override
+    public String toString() { // what for?
+        return super.toString();
+    }
+
+    /**
+     * Draws this TextLayout at the specified location with the 
+     * specified Graphics2D context. 
+     * 
+     * @param g2d the Graphics2D object which renders this TextLayout.
+     * @param x the X coordinate of the TextLayout origin. 
+     * @param y the Y coordinate of the TextLayout origin.
+     */
+    public void draw(Graphics2D g2d, float x, float y) {
+        updateMetrics();
+        breaker.drawSegments(g2d, x ,y);
+    }
+
+    /**
+     * Update metrics.
+     */
+    private void updateMetrics() {
+        if (!metricsValid) {
+            breaker.createAllSegments();
+            tmc = new TextMetricsCalculator(breaker);
+            metrics = tmc.createMetrics();
+            metricsValid = true;
+        }
+    }
+
+    /**
+     * Gets the advance of this TextLayout object.
+     * 
+     * @return the advance of this TextLayout object.
+     */
+    public float getAdvance() {
+        updateMetrics();
+        return metrics.getAdvance();
+    }
+
+    /**
+     * Gets the ascent of this TextLayout object.
+     * 
+     * @return the ascent of this TextLayout object.
+     */
+    public float getAscent() {
+        updateMetrics();
+        return metrics.getAscent();
+    }
+
+    /**
+     * Gets the baseline of this TextLayout object.
+     * 
+     * @return the baseline of this TextLayout object.
+     */
+    public byte getBaseline() {
+        updateMetrics();
+        return (byte) metrics.getBaseLineIndex();
+    }
+
+    /**
+     * Gets the float array of offsets for the baselines which 
+     * are used in this TextLayout.
+     * 
+     * @return the float array of offsets for the baselines which 
+     * are used in this TextLayout.
+     */
+    public float[] getBaselineOffsets() {
+        updateMetrics();
+        return tmc.getBaselineOffsets();
+    }
+
+    /**
+     * Gets the black box bounds of the characters in the specified area. 
+     * The black box bounds is an Shape which contains all 
+     * bounding boxes of all the glyphs of the characters 
+     * between firstEndpoint and secondEndpoint parameters values.     
+     *  
+     * @param firstEndpoint the first point of the area.
+     * @param secondEndpoint the second point of the area.
+     * 
+     * @return the Shape which contains black box bounds.
+     */
+    public Shape getBlackBoxBounds(int firstEndpoint, int secondEndpoint) {
+        updateMetrics();
+        if (firstEndpoint < secondEndpoint) {
+            return breaker.getBlackBoxBounds(firstEndpoint, secondEndpoint);
+        }
+        return breaker.getBlackBoxBounds(secondEndpoint, firstEndpoint);
+    }
+
+    /**
+     * Gets the bounds of this TextLayout.
+     * 
+     * @return the bounds of this TextLayout.
+     */
+    public Rectangle2D getBounds() {
+        updateMetrics();
+        return breaker.getVisualBounds();
+    }
+
+    /**
+     * Gets information about the caret of the specified TextHitInfo.
+     * 
+     * @param hitInfo the TextHitInfo.
+     * 
+     * @return the information about the caret of the specified TextHitInfo.
+     */
+    public float[] getCaretInfo(TextHitInfo hitInfo) {
+        updateMetrics();
+        return caretManager.getCaretInfo(hitInfo);
+    }
+
+    /**
+     * Gets information about the caret of the specified TextHitInfo
+     * of a character in this TextLayout.
+     * 
+     * @param hitInfo the TextHitInfo of a character in this TextLayout.
+     * @param bounds the bounds to which the caret info is constructed.
+     * 
+     * @return the caret of the specified TextHitInfo.
+     */
+    public float[] getCaretInfo(TextHitInfo hitInfo, Rectangle2D bounds) {
+        updateMetrics();
+        return caretManager.getCaretInfo(hitInfo);
+    }
+
+    /**
+     * Gets a Shape which represents the caret of the specified TextHitInfo
+     * in the bounds of this TextLayout.
+     * 
+     * @param hitInfo the TextHitInfo.
+     * @param bounds the bounds to which the caret info is constructed.
+     * 
+     * @return the Shape which represents the caret.
+     */
+    public Shape getCaretShape(TextHitInfo hitInfo, Rectangle2D bounds) {
+        updateMetrics();
+        return caretManager.getCaretShape(hitInfo, this);
+    }
+
+    /**
+     * Gets a Shape which represents the caret of the specified TextHitInfo
+     * in the bounds of this TextLayout.
+     * 
+     * @param hitInfo the TextHitInfo.
+     * 
+     * @return the Shape which represents the caret.
+     */
+    public Shape getCaretShape(TextHitInfo hitInfo) {
+        updateMetrics();
+        return caretManager.getCaretShape(hitInfo, this);
+    }
+
+    /**
+     * Gets two Shapes for the strong and weak carets with
+     * default caret policy and null bounds: the first element 
+     * is the strong caret, the second is the weak caret or null. 
+     * 
+     * @param offset an offset in the TextLayout.
+     * 
+     * @return an array of two Shapes corresponded to the strong
+     * and weak carets.
+     */
+    public Shape[] getCaretShapes(int offset) {
+        return getCaretShapes(offset, null, TextLayout.DEFAULT_CARET_POLICY);
+    }
+
+    /**
+     * Gets two Shapes for the strong and weak carets with
+     * the default caret policy: the first element is the strong 
+     * caret, the second is the weak caret or null.
+     * 
+     * @param offset an offset in the TextLayout.
+     * @param bounds the bounds to which to extend the carets.
+     * 
+     * @return an array of two Shapes corresponded to the strong
+     * and weak carets.
+     */
+    public Shape[] getCaretShapes(int offset, Rectangle2D bounds) {
+        return getCaretShapes(offset, bounds, TextLayout.DEFAULT_CARET_POLICY);
+    }
+
+    /**
+     * Gets two Shapes for the strong and weak carets: the first
+     * element is the strong caret, the second is the weak caret 
+     * or null.
+     * 
+     * @param offset an offset in the TextLayout.
+     * @param bounds the bounds to which to extend the carets.
+     * @param policy the specified CaretPolicy.
+     * 
+     * @return an array of two Shapes corresponded to the strong
+     * and weak carets.
+     */
+    public Shape[] getCaretShapes(int offset, Rectangle2D bounds, TextLayout.CaretPolicy policy) {
+        if (offset < 0 || offset > breaker.getCharCount()) {
+            // awt.195=Offset is out of bounds
+            throw new IllegalArgumentException(Messages.getString("awt.195")); //$NON-NLS-1$
+        }
+
+        updateMetrics();
+        return caretManager.getCaretShapes(offset, bounds, policy, this);
+    }
+
+    /**
+     * Gets the number of characters in this TextLayout.
+     * 
+     * @return the number of characters in this TextLayout.
+     */
+    public int getCharacterCount() {
+        return breaker.getCharCount();
+    }
+
+    /**
+     * Gets the level of the character with the specified index. 
+     *  
+     * @param index the specified index of the character.
+     * 
+     * @return the level of the character.
+     */
+    public byte getCharacterLevel(int index) {
+        if (index == -1 || index == getCharacterCount()) {
+            return (byte) breaker.getBaseLevel();
+        }
+        return breaker.getLevel(index);
+    }
+
+    /**
+     * Gets the descent of this TextLayout.
+     * 
+     * @return the descent of this TextLayout.
+     */
+    public float getDescent() {
+        updateMetrics();
+        return metrics.getDescent();
+    }
+
+    /**
+     * Gets the TextLayout wich is justified with the specified
+     * width related to this TextLayout.
+     * 
+     * @param justificationWidth the width which is used 
+     * for justification.
+     * 
+     * @return a TextLayout justified to the specified width.
+     * 
+     * @throws Error the error occures if this TextLayout has been
+     * already justified.
+     */
+    public TextLayout getJustifiedLayout(float justificationWidth) throws Error {
+        float justification = breaker.getJustification();
+
+        if (justification < 0) {
+            // awt.196=Justification impossible, layout already justified
+            throw new Error(Messages.getString("awt.196")); //$NON-NLS-1$
+        } else if (justification == 0) {
+            return this;
+        }
+
+        TextLayout justifiedLayout = new TextLayout((TextRunBreaker) breaker.clone());
+        justifiedLayout.handleJustify(justificationWidth);
+        return justifiedLayout;
+    }
+
+    /**
+     * Gets the leading of this TextLayout.
+     * 
+     * @return the leading of this TextLayout.
+     */
+    public float getLeading() {
+        updateMetrics();
+        return metrics.getLeading();
+    }
+
+    /**
+     * Gets a Shape representing the logical selection betweeen 
+     * the specified endpoints and extended to the natural 
+     * bounds of this TextLayout.
+     * 
+     * @param firstEndpoint the first selected endpoint within the area of characters
+     * @param secondEndpoint the second selected endpoint within the area of characters
+     * 
+     * @return a Shape represented the logical selection betweeen 
+     * the specified endpoints.
+     */
+    public Shape getLogicalHighlightShape(int firstEndpoint, int secondEndpoint) {
+        updateMetrics();
+        return getLogicalHighlightShape(firstEndpoint, secondEndpoint, breaker.getLogicalBounds());
+    }
+
+    /**
+     * Gets a Shape representing the logical selection betweeen 
+     * the specified endpoints and extended to the specified 
+     * bounds of this TextLayout.
+     * 
+     * @param firstEndpoint the first selected endpoint within the area of characters
+     * @param secondEndpoint the second selected endpoint within the area of characters
+     * @param bounds the specified bounds of this TextLayout.
+     * 
+     * @return a Shape represented the logical selection betweeen 
+     * the specified endpoints.
+     */
+    public Shape getLogicalHighlightShape(
+            int firstEndpoint,
+            int secondEndpoint,
+            Rectangle2D bounds
+    ) {
+        updateMetrics();
+
+        if (firstEndpoint > secondEndpoint) {
+            if (secondEndpoint < 0 || firstEndpoint > breaker.getCharCount()) {
+                // awt.197=Endpoints are out of range
+                throw new IllegalArgumentException(Messages.getString("awt.197")); //$NON-NLS-1$
+            }
+            return caretManager.getLogicalHighlightShape(
+                    secondEndpoint,
+                    firstEndpoint,
+                    bounds,
+                    this
+            );
+        }
+        if (firstEndpoint < 0 || secondEndpoint > breaker.getCharCount()) {
+            // awt.197=Endpoints are out of range
+            throw new IllegalArgumentException(Messages.getString("awt.197")); //$NON-NLS-1$
+        }
+        return caretManager.getLogicalHighlightShape(
+                firstEndpoint,
+                secondEndpoint,
+                bounds,
+                this
+        );
+    }
+
+    /**
+     * Gets the logical ranges of text which corresponds to a visual 
+     * selection.
+     * 
+     * @param hit1 the first endpoint of the visual range.
+     * @param hit2 the second endpoint of the visual range.
+     * 
+     * @return the logical ranges of text which corresponds to a visual 
+     * selection.
+     */
+    public int[] getLogicalRangesForVisualSelection(TextHitInfo hit1, TextHitInfo hit2) {
+        return caretManager.getLogicalRangesForVisualSelection(hit1, hit2);
+    }
+
+    /**
+     * Gets the TextHitInfo for the next caret to the left (or
+     * up at the end of the line) of the specified offset. 
+     * 
+     * @param offset the offset in this TextLayout.
+     * 
+     * @return the TextHitInfo for the next caret to the left (or
+     * up at the end of the line) of the specified hit, or null 
+     * if there is no hit.
+     */
+    public TextHitInfo getNextLeftHit(int offset) {
+        return getNextLeftHit(offset, DEFAULT_CARET_POLICY);
+    }
+
+    /**
+     * Gets the TextHitInfo for the next caret to the left (or
+     * up at the end of the line) of the specified hit. 
+     * 
+     * @param hitInfo the initial hit.
+     * 
+     * @return the TextHitInfo for the next caret to the left (or
+     * up at the end of the line) of the specified hit, or null 
+     * if there is no hit.
+     */
+    public TextHitInfo getNextLeftHit(TextHitInfo hitInfo) {
+        breaker.createAllSegments();
+        return caretManager.getNextLeftHit(hitInfo);
+    }
+
+    /**
+     * Gets the TextHitInfo for the next caret to the left (or
+     * up at the end of the line) of the specified offset, given the 
+     * specified caret policy. 
+     * 
+     * @param offset the offset in this TextLayout.
+     * @param policy the policy to be used for obtaining the strong caret.
+     * 
+     * @return the TextHitInfo for the next caret to the left of the 
+     * specified offset, or null if there is no hit.
+     */
+    public TextHitInfo getNextLeftHit(int offset, TextLayout.CaretPolicy policy) {
+        if (offset < 0 || offset > breaker.getCharCount()) {
+            // awt.195=Offset is out of bounds
+            throw new IllegalArgumentException(Messages.getString("awt.195")); //$NON-NLS-1$
+        }
+
+        TextHitInfo hit = TextHitInfo.afterOffset(offset);
+        TextHitInfo strongHit = policy.getStrongCaret(hit, hit.getOtherHit(), this);
+        TextHitInfo nextLeftHit = getNextLeftHit(strongHit);
+
+        if (nextLeftHit != null) {
+            return policy.getStrongCaret(getVisualOtherHit(nextLeftHit), nextLeftHit, this);
+        }
+        return null;
+    }
+
+    /**
+     * Gets the TextHitInfo for the next caret to the right (or
+     * down at the end of the line) of the specified hit. 
+     * 
+     * @param hitInfo the initial hit.
+     * 
+     * @return the TextHitInfo for the next caret to the right (or
+     * down at the end of the line) of the specified hit, or null 
+     * if there is no hit.
+     */
+    public TextHitInfo getNextRightHit(TextHitInfo hitInfo) {
+        breaker.createAllSegments();
+        return caretManager.getNextRightHit(hitInfo);
+    }
+
+    /**
+     * Gets the TextHitInfo for the next caret to the right (or
+     * down at the end of the line) of the specified offset. 
+     * 
+     * @param offset the offset in this TextLayout.
+     * 
+     * @return the TextHitInfo for the next caret to the right of the 
+     * specified offset, or null if there is no hit.
+     */
+    public TextHitInfo getNextRightHit(int offset) {
+        return getNextRightHit(offset, DEFAULT_CARET_POLICY);
+    }
+
+    /**
+     * Gets the TextHitInfo for the next caret to the right (or
+     * down at the end of the line) of the specified offset, given the 
+     * specified caret policy. 
+     * 
+     * @param offset the offset in this TextLayout.
+     * @param policy the policy to be used for obtaining the strong caret.
+     * 
+     * @return the TextHitInfo for the next caret to the right of the 
+     * specified offset, or null if there is no hit.
+     */
+    public TextHitInfo getNextRightHit(int offset, TextLayout.CaretPolicy policy) {
+        if (offset < 0 || offset > breaker.getCharCount()) {
+            // awt.195=Offset is out of bounds
+            throw new IllegalArgumentException(Messages.getString("awt.195")); //$NON-NLS-1$
+        }
+
+        TextHitInfo hit = TextHitInfo.afterOffset(offset);
+        TextHitInfo strongHit = policy.getStrongCaret(hit, hit.getOtherHit(), this);
+        TextHitInfo nextRightHit = getNextRightHit(strongHit);
+
+        if (nextRightHit != null) {
+            return policy.getStrongCaret(getVisualOtherHit(nextRightHit), nextRightHit, this);
+        }
+        return null;
+    }
+
+    /**
+     * Gets the outline of this TextLayout as a Shape.
+     * 
+     * @param xform the AffineTransform to be used to transform 
+     * the outline before returning it, or null if no transformation
+     * is desired.
+     * 
+     * @return the outline of this TextLayout as a Shape.
+     */
+    public Shape getOutline(AffineTransform xform) {
+        breaker.createAllSegments();
+
+        GeneralPath outline = breaker.getOutline();
+
+        if (outline != null && xform != null) {
+            outline.transform(xform);
+        }
+
+        return outline;
+    }
+
+    /**
+     * Gets the visible advance of this TextLayout which is defined as
+     * diffence between leading (advance) and trailing whitespace.
+     * 
+     * @return the visible advance of this TextLayout.
+     */
+    public float getVisibleAdvance() {
+        updateMetrics();
+
+        // Trailing whitespace _SHOULD_ be reordered (Unicode spec) to
+        // base direction, so it is also trailing
+        // in logical representation. We use this fact.
+        int lastNonWhitespace = breaker.getLastNonWhitespace();
+
+        if (lastNonWhitespace < 0) {
+            return 0;
+        } else if (lastNonWhitespace == getCharacterCount()-1) {
+            return getAdvance();
+        } else if (justificationWidth >= 0) { // Layout is justified
+            return justificationWidth;
+        } else {
+            breaker.pushSegments(
+                    breaker.getACI().getBeginIndex(),
+                    lastNonWhitespace + breaker.getACI().getBeginIndex() + 1
+            );
+
+            breaker.createAllSegments();
+
+            float visAdvance = tmc.createMetrics().getAdvance();
+
+            breaker.popSegments();
+            return visAdvance;
+        }
+    }
+
+    /**
+     * Gets a Shape which corresponds to the highlighted (selected) area
+     * based on two hit locations within the text and extends to the bounds.
+     * 
+     * @param hit1 the first text hit location.
+     * @param hit2 the second text hit location.
+     * @param bounds the rectangle that the highlighted area should be 
+     * extended or restricted to.
+     * 
+     * @return a Shape which corresponds to the highlighted (selected) area.
+     */
+    public Shape getVisualHighlightShape(TextHitInfo hit1, TextHitInfo hit2, Rectangle2D bounds) {
+        return caretManager.getVisualHighlightShape(hit1, hit2, bounds, this);
+    }
+
+    /**
+     * Gets a Shape which corresponds to the highlighted (selected) area
+     * based on two hit locations within the text.
+     * 
+     * @param hit1 the first text hit location.
+     * @param hit2 the second text hit location.
+     * 
+     * @return a Shape which corresponds to the highlighted (selected) area.
+     */
+    public Shape getVisualHighlightShape(TextHitInfo hit1, TextHitInfo hit2) {
+        breaker.createAllSegments();
+        return caretManager.getVisualHighlightShape(hit1, hit2, breaker.getLogicalBounds(), this);
+    }
+
+    /**
+     * Gets the TextHitInfo for a hit on the opposite side of the 
+     * specified hit's caret.
+     * 
+     * @param hitInfo the specified TextHitInfo.
+     * 
+     * @return the TextHitInfo for a hit on the opposite side of the 
+     * specified hit's caret.
+     */
+    public TextHitInfo getVisualOtherHit(TextHitInfo hitInfo) {
+        return caretManager.getVisualOtherHit(hitInfo);
+    }
+
+    /**
+     * Justifies the text; this method should be overridden
+     * by subclasses.
+     * 
+     * @param justificationWidth the width for justification.
+     */
+    protected void handleJustify(float justificationWidth) {
+        float justification = breaker.getJustification();
+
+        if (justification < 0) {
+            // awt.196=Justification impossible, layout already justified
+            throw new IllegalStateException(Messages.getString("awt.196")); //$NON-NLS-1$
+        } else if (justification == 0) {
+            return;
+        }
+
+        float gap = (justificationWidth - getVisibleAdvance()) * justification;
+        breaker.justify(gap);
+        this.justificationWidth = justificationWidth;
+
+        // Correct metrics
+        tmc = new TextMetricsCalculator(breaker);
+        tmc.correctAdvance(metrics);
+    }
+
+    /**
+     * Returns a TextHitInfo object that gives information on which 
+     * division point (between two characters) is corresponds to a 
+     * hit (such as a mouse click) at the specified coordinates.
+     * 
+     * @param x the X coordinate in this TextLayout.
+     * @param y the Y coordinate in this TextLayout.
+     * 
+     * TextHitInfo object cooresponding to the given coordinates
+     * within the text.
+     */
+    public TextHitInfo hitTestChar(float x, float y) {
+        return hitTestChar(x, y, getBounds());
+    }
+
+    /**
+     * Returns a TextHitInfo object that gives information on which 
+     * division point (between two characters) is corresponds to a 
+     * hit (such as a mouse click) at the specified coordinates within 
+     * the specified text rectangle.
+     * 
+     * @param x the X coordinate in this TextLayout.
+     * @param y the Y coordinate in this TextLayout.
+     * @param bounds the bounds of the text area.
+     * 
+     * TextHitInfo object cooresponding to the given coordinates
+     * within the text.
+     */
+    public TextHitInfo hitTestChar(float x, float y, Rectangle2D bounds) {
+        if (x > bounds.getMaxX()) {
+            return breaker.isLTR() ?
+                    TextHitInfo.trailing(breaker.getCharCount() - 1) : TextHitInfo.leading(0);
+        }
+
+        if (x < bounds.getMinX()) {
+            return breaker.isLTR() ?
+                    TextHitInfo.leading(0) : TextHitInfo.trailing(breaker.getCharCount() - 1);
+        }
+
+        return breaker.hitTest(x, y);
+    }
+
+    /**
+     * Returns true if this TextLayout has a "left to right" 
+     * direction.
+     * 
+     * @return true if this TextLayout has a "left to right" 
+     * direction, false if this TextLayout has a "right to left" 
+     * direction. 
+     */
+    public boolean isLeftToRight() {
+        return breaker.isLTR();
+    }
+
+    /**
+     * Returns true if this TextLayout is vertical, false otherwise.
+     * 
+     * @return true if this TextLayout is vertical, false if horizontal.
+     */
+    public boolean isVertical() {
+        return false;
+    }
+}
+
diff --git a/awt/java/awt/font/TextMeasurer.java b/awt/java/awt/font/TextMeasurer.java
new file mode 100644
index 0000000..017f3d9
--- /dev/null
+++ b/awt/java/awt/font/TextMeasurer.java
@@ -0,0 +1,167 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/*
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ */
+
+package java.awt.font;
+
+
+import java.text.AttributedCharacterIterator;
+
+import org.apache.harmony.awt.gl.font.TextMetricsCalculator;
+import org.apache.harmony.awt.gl.font.TextRunBreaker;
+
+/**
+ * The TextMeasurer class provides utilities for line break operations.
+ */
+public final class TextMeasurer implements Cloneable {
+    
+    /** The aci. */
+    AttributedCharacterIterator aci;
+    
+    /** The frc. */
+    FontRenderContext frc;
+    
+    /** The breaker. */
+    TextRunBreaker breaker = null;
+    
+    /** The tmc. */
+    TextMetricsCalculator tmc = null;
+
+    /**
+     * Instantiates a new text measurer from the specified text.
+     * 
+     * @param text the source text.
+     * @param frc the FontRenderContext.
+     */
+    public TextMeasurer(AttributedCharacterIterator text, FontRenderContext frc) {
+        this.aci = text;
+        this.frc = frc;
+        breaker = new TextRunBreaker(aci, this.frc);
+        tmc = new TextMetricsCalculator(breaker);
+    }
+
+    /**
+     * Replaces the current text with the new text, inserting a break
+     * character at the specified insert position.  
+     * 
+     * @param newParagraph the new paragraph text. 
+     * @param insertPos the position in the text where the character is inserted. 
+     */
+    public void insertChar(AttributedCharacterIterator newParagraph, int insertPos) {
+        AttributedCharacterIterator oldAci = aci;
+        aci = newParagraph;
+        if ((oldAci.getEndIndex() - oldAci.getBeginIndex()) -
+           (aci.getEndIndex() - aci.getBeginIndex()) != -1) {
+            breaker = new TextRunBreaker(aci, this.frc);
+            tmc = new TextMetricsCalculator(breaker);
+        } else {
+            breaker.insertChar(newParagraph, insertPos);
+        }
+    }
+
+    /**
+     * Replaces the current text with the new text and deletes a
+     * character at the specified position.  
+     * 
+     * @param newParagraph the paragraph text after deletion. 
+     * @param deletePos the position in the text where the character is removed. 
+     */
+    public void deleteChar(AttributedCharacterIterator newParagraph, int deletePos) {
+        AttributedCharacterIterator oldAci = aci;
+        aci = newParagraph;
+        if ((oldAci.getEndIndex() - oldAci.getBeginIndex()) -
+           (aci.getEndIndex() - aci.getBeginIndex()) != 1) {
+            breaker = new TextRunBreaker(aci, this.frc);
+            tmc = new TextMetricsCalculator(breaker);
+        } else {
+            breaker.deleteChar(newParagraph, deletePos);
+        }
+    }
+
+    /**
+     * Returns a copy of this object.
+     * 
+     * @return a copy of this object.
+     */
+    @Override
+    protected Object clone() {
+        return new TextMeasurer((AttributedCharacterIterator) aci.clone(), frc);
+    }
+
+    /**
+     * Returns a TextLayout of the specified character range.
+     * 
+     * @param start the index of the first character.
+     * @param limit the index after the last character. 
+     * 
+     * @return a TextLayout for the characters beginning at "start" up 
+     * to "end".
+     */
+    public TextLayout getLayout(int start, int limit) {
+        breaker.pushSegments(start - aci.getBeginIndex(), limit - aci.getBeginIndex());
+
+        breaker.createAllSegments();
+        TextLayout layout = new TextLayout((TextRunBreaker) breaker.clone());
+
+        breaker.popSegments();
+        return layout;
+    }
+
+    /**
+     * Returns the graphical width of a line beginning at "start" 
+     * parameter and including characters up to "end" parameter. 
+     * "start" and "end" are absolute indices, not relative to the 
+     * "start" of the paragraph.
+     * 
+     * @param start the character index at which to start measuring.
+     * @param end the character index at which to stop measuring.
+     * 
+     * @return the graphical width of a line beginning at "start"  
+     * and including characters up to "end".
+     */
+    public float getAdvanceBetween(int start, int end) {
+        breaker.pushSegments(start - aci.getBeginIndex(), end - aci.getBeginIndex());
+
+        breaker.createAllSegments();
+        float retval = tmc.createMetrics().getAdvance();
+
+        breaker.popSegments();
+        return retval;
+    }
+
+    /**
+     * Returns the index of the first character which is not fit on 
+     * a line beginning at start and possible measuring up to maxAdvance 
+     * in graphical width.
+     * 
+     * @param start he character index at which to start measuring. 
+     * @param maxAdvance the graphical width in which the line must fit. 
+     * 
+     * @return the index after the last character that is fit on a line 
+     * beginning at start, which is not longer than maxAdvance in graphical
+     * width.
+     */
+    public int getLineBreakIndex(int start, float maxAdvance) {
+        breaker.createAllSegments();
+        return breaker.getLineBreakIndex(
+                start - aci.getBeginIndex(), maxAdvance) + aci.getBeginIndex();
+    }
+}
+
diff --git a/awt/java/awt/font/TransformAttribute.java b/awt/java/awt/font/TransformAttribute.java
new file mode 100644
index 0000000..7c9b0bd
--- /dev/null
+++ b/awt/java/awt/font/TransformAttribute.java
@@ -0,0 +1,80 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Ilya S. Okomin
+ * @version $Revision$
+ */
+package java.awt.font;
+
+import java.awt.geom.AffineTransform;
+import java.io.Serializable;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The TransformAttribute class is a wrapper for the AffineTransform class in
+ * order to use it as attribute.
+ */
+public final class TransformAttribute implements Serializable {
+    
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = 3356247357827709530L;
+
+    // affine transform of this TransformAttribute instance
+    /** The transform. */
+    private AffineTransform fTransform;
+
+    /**
+     * Instantiates a new TransformAttribute from the specified
+     * AffineTransform.
+     * 
+     * @param transform the AffineTransform to be wrapped.
+     */
+    public TransformAttribute(AffineTransform transform) {
+        if (transform == null) {
+            // awt.94=transform can not be null
+            throw new IllegalArgumentException(Messages.getString("awt.94")); //$NON-NLS-1$
+        }
+        if (!transform.isIdentity()){
+            this.fTransform = new AffineTransform(transform);
+        }
+    }
+
+    /**
+     * Gets the initial AffineTransform which is wrapped.
+     * 
+     * @return the initial AffineTransform which is wrapped.
+     */
+    public AffineTransform getTransform() {
+        if (fTransform != null){
+            return new AffineTransform(fTransform);
+        }
+        return new AffineTransform();
+    }
+
+    /**
+     * Checks if this transform is an identity transform.
+     * 
+     * @return true, if this transform is an identity transform,
+     * false otherwise.
+     */
+    public boolean isIdentity() {
+        return (fTransform == null);
+    }
+
+}
+
diff --git a/awt/java/awt/geom/AffineTransform.java b/awt/java/awt/geom/AffineTransform.java
new file mode 100644
index 0000000..5fd3934
--- /dev/null
+++ b/awt/java/awt/geom/AffineTransform.java
@@ -0,0 +1,1158 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Denis M. Kishenko
+ * @version $Revision$
+ */
+package java.awt.geom;
+
+import java.awt.Shape;
+import java.io.IOException;
+import java.io.Serializable;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+import org.apache.harmony.misc.HashCode;
+
+/**
+ * The Class AffineTransform represents a linear transformation 
+ * (rotation, scaling, or shear) followed by a translation that 
+ * acts on a coordinate space. It preserves colinearity of points 
+ * and ratios of distances between collinear points: so if A, B, 
+ * and C are on a line, then after the space has been transformed 
+ * via the affine transform, the images of the three points will 
+ * still be on a line, and the ratio of the distance from A to B
+ * with the distance from B to C will be the same as the corresponding
+ * ratio in the image space.
+ */
+public class AffineTransform implements Cloneable, Serializable {
+
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = 1330973210523860834L;
+
+    /** The Constant TYPE_IDENTITY. */
+    public static final int TYPE_IDENTITY = 0;
+    
+    /** The Constant TYPE_TRANSLATION. */
+    public static final int TYPE_TRANSLATION = 1;
+    
+    /** The Constant TYPE_UNIFORM_SCALE. */
+    public static final int TYPE_UNIFORM_SCALE = 2;
+    
+    /** The Constant TYPE_GENERAL_SCALE. */
+    public static final int TYPE_GENERAL_SCALE = 4;
+    
+    /** The Constant TYPE_QUADRANT_ROTATION. */
+    public static final int TYPE_QUADRANT_ROTATION = 8;
+    
+    /** The Constant TYPE_GENERAL_ROTATION. */
+    public static final int TYPE_GENERAL_ROTATION = 16;
+    
+    /** The Constant TYPE_GENERAL_TRANSFORM. */
+    public static final int TYPE_GENERAL_TRANSFORM = 32;
+    
+    /** The Constant TYPE_FLIP. */
+    public static final int TYPE_FLIP = 64;
+    
+    /** The Constant TYPE_MASK_SCALE. */
+    public static final int TYPE_MASK_SCALE = TYPE_UNIFORM_SCALE | TYPE_GENERAL_SCALE;
+    
+    /** The Constant TYPE_MASK_ROTATION. */
+    public static final int TYPE_MASK_ROTATION = TYPE_QUADRANT_ROTATION | TYPE_GENERAL_ROTATION;
+
+    /** The <code>TYPE_UNKNOWN</code> is an initial type value. */
+    static final int TYPE_UNKNOWN = -1;
+    
+    /** The min value equivalent to zero. If absolute value less then ZERO it considered as zero. */
+    static final double ZERO = 1E-10;
+   
+    /** The values of transformation matrix. */
+    double m00;
+    
+    /** The m10. */
+    double m10;
+    
+    /** The m01. */
+    double m01;
+    
+    /** The m11. */
+    double m11;
+    
+    /** The m02. */
+    double m02;
+    
+    /** The m12. */
+    double m12;
+
+    /** The transformation <code>type</code>. */
+    transient int type;
+
+    /**
+     * Instantiates a new affine transform of type <code>TYPE_IDENTITY</code>
+     * (which leaves coordinates unchanged).
+     */
+    public AffineTransform() {
+        type = TYPE_IDENTITY;
+        m00 = m11 = 1.0;
+        m10 = m01 = m02 = m12 = 0.0;
+    }
+
+    /**
+     * Instantiates a new affine transform that has the same data as
+     * the given AffineTransform.
+     * 
+     * @param t the transform to copy.
+     */
+    public AffineTransform(AffineTransform t) {
+        this.type = t.type;
+        this.m00 = t.m00;
+        this.m10 = t.m10;
+        this.m01 = t.m01;
+        this.m11 = t.m11;
+        this.m02 = t.m02;
+        this.m12 = t.m12;
+    }
+
+    /**
+     * Instantiates a new affine transform by specifying the values of the 2x3
+     * transformation matrix as floats. The type is set to the default
+     * type: <code>TYPE_UNKNOWN</code>
+     * 
+     * @param m00 the m00 entry in the transformation matrix.
+     * @param m10 the m10 entry in the transformation matrix.
+     * @param m01 the m01 entry in the transformation matrix.
+     * @param m11 the m11 entry in the transformation matrix.
+     * @param m02 the m02 entry in the transformation matrix.
+     * @param m12 the m12 entry in the transformation matrix.
+     */
+    public AffineTransform(float m00, float m10, float m01, float m11, float m02, float m12) {
+        this.type = TYPE_UNKNOWN;
+        this.m00 = m00;
+        this.m10 = m10;
+        this.m01 = m01;
+        this.m11 = m11;
+        this.m02 = m02;
+        this.m12 = m12;
+    }
+
+    /**
+     * Instantiates a new affine transform by specifying the values of the 2x3
+     * transformation matrix as doubles. The type is set to the default
+     * type: <code>TYPE_UNKNOWN</code>
+     * 
+     * @param m00 the m00 entry in the transformation matrix.
+     * @param m10 the m10 entry in the transformation matrix.
+     * @param m01 the m01 entry in the transformation matrix.
+     * @param m11 the m11 entry in the transformation matrix.
+     * @param m02 the m02 entry in the transformation matrix.
+     * @param m12 the m12 entry in the transformation matrix.
+     */
+    public AffineTransform(double m00, double m10, double m01, double m11, double m02, double m12) {
+        this.type = TYPE_UNKNOWN;
+        this.m00 = m00;
+        this.m10 = m10;
+        this.m01 = m01;
+        this.m11 = m11;
+        this.m02 = m02;
+        this.m12 = m12;
+    }
+
+    /**
+     * Instantiates a new affine transform by reading the values of the 
+     * transformation matrix from an array of floats. The mapping from the
+     * array to the matrix starts with <code>matrix[0]</code> giving the 
+     * top-left entry of the matrix and 
+     * proceeds with the usual left-to-right and top-down ordering.
+     * <p>
+     * If the array has only four entries, then the two entries of the 
+     * last row of the transformation matrix default to zero.
+     * 
+     * @param matrix the array of four or six floats giving the values 
+     * of the matrix.
+     * 
+     * @throws ArrayIndexOutOfBoundsException if the size of the array
+     * is 0, 1, 2, 3, or 5.
+     */
+    public AffineTransform(float[] matrix) {
+        this.type = TYPE_UNKNOWN;
+        m00 = matrix[0];
+        m10 = matrix[1];
+        m01 = matrix[2];
+        m11 = matrix[3];
+        if (matrix.length > 4) {
+            m02 = matrix[4];
+            m12 = matrix[5];
+        }
+    }
+
+    /**
+     * Instantiates a new affine transform by reading the values of the 
+     * transformation matrix from an array of doubles. The mapping from the
+     * array to the matrix starts with <code>matrix[0]</code> giving the 
+     * top-left entry of the matrix and 
+     * proceeds with the usual left-to-right and top-down ordering.
+     * <p>
+     * If the array has only four entries, then the two entries of the 
+     * last row of the transformation matrix default to zero.
+     * 
+     * @param matrix the array of four or six doubles giving the values 
+     * of the matrix.
+     * 
+     * @throws ArrayIndexOutOfBoundsException if the size of the array
+     * is 0, 1, 2, 3, or 5.
+     */
+    public AffineTransform(double[] matrix) {
+        this.type = TYPE_UNKNOWN;
+        m00 = matrix[0];
+        m10 = matrix[1];
+        m01 = matrix[2];
+        m11 = matrix[3];
+        if (matrix.length > 4) {
+            m02 = matrix[4];
+            m12 = matrix[5];
+        }
+    }
+
+
+    /**
+     * Returns type of the affine transformation.
+     * <p>
+     * The type is computed as follows: Label the entries of the 
+     * transformation matrix as three rows (m00, m01), (m10, m11), and
+     * (m02, m12). Then if the original basis vectors are (1, 0) and (0, 1), 
+     * the new basis vectors after transformation are given by (m00, m01) 
+     * and (m10, m11), and the translation vector is (m02, m12).
+     * <p>
+     * The types are classified as follows: <br/> 
+     *   TYPE_IDENTITY - no change<br/>
+     *   TYPE_TRANSLATION - The translation vector isn't zero<br/>
+     *   TYPE_UNIFORM_SCALE - The new basis vectors have equal length<br/>
+     *   TYPE_GENERAL_SCALE - The new basis vectors dont' have equal length<br/>
+     *   TYPE_FLIP - The new basis vector orientation differs from the original one<br/>
+     *   TYPE_QUADRANT_ROTATION - The new basis is a rotation of the original by 90, 180, 270, or 360 degrees<br/>   
+     *   TYPE_GENERAL_ROTATION - The new basis is a rotation of the original by an arbitrary angle<br/>
+     *   TYPE_GENERAL_TRANSFORM - The transformation can't be inverted.<br/>
+     *   <p>
+     * Note that multiple types are possible, thus the types can be combined 
+     * using bitwise combinations.
+     * 
+     * @return the type of the Affine Transform.
+     */
+    public int getType() {
+        if (type != TYPE_UNKNOWN) {
+            return type;
+        }
+
+        int type = 0;
+
+        if (m00 * m01 + m10 * m11 != 0.0) {
+            type |= TYPE_GENERAL_TRANSFORM;
+            return type;
+        }
+
+        if (m02 != 0.0 || m12 != 0.0) {
+            type |= TYPE_TRANSLATION;
+        } else
+            if (m00 == 1.0 && m11 == 1.0 && m01 == 0.0 && m10 == 0.0) {
+                type = TYPE_IDENTITY;
+                return type;
+            }
+
+        if (m00 * m11 - m01 * m10 < 0.0) {
+            type |= TYPE_FLIP;
+        }
+
+        double dx = m00 * m00 + m10 * m10;
+        double dy = m01 * m01 + m11 * m11;
+        if (dx != dy) {
+            type |= TYPE_GENERAL_SCALE;
+        } else
+            if (dx != 1.0) {
+                type |= TYPE_UNIFORM_SCALE;
+            }
+
+        if ((m00 == 0.0 && m11 == 0.0) ||
+            (m10 == 0.0 && m01 == 0.0 && (m00 < 0.0 || m11 < 0.0)))
+        {
+            type |= TYPE_QUADRANT_ROTATION;
+        } else
+            if (m01 != 0.0 || m10 != 0.0) {
+                type |= TYPE_GENERAL_ROTATION;
+            }
+
+        return type;
+    }
+
+    /**
+     * Gets the scale x entry of the transformation matrix
+     * (the upper left matrix entry).
+     * 
+     * @return the scale x value.
+     */
+    public double getScaleX() {
+        return m00;
+    }
+
+    /**
+     * Gets the scale y entry of the transformation matrix
+     * (the lower right entry of the linear transformation).
+     * 
+     * @return the scale y value.
+     */
+    public double getScaleY() {
+        return m11;
+    }
+
+    /**
+     * Gets the shear x entry of the transformation matrix
+     * (the upper right entry of the linear transformation).
+     * 
+     * @return the shear x value.
+     */
+    public double getShearX() {
+        return m01;
+    }
+
+    /**
+     * Gets the shear y entry of the transformation matrix
+     * (the lower left entry of the linear transformation).
+     * 
+     * @return the shear y value.
+     */
+    public double getShearY() {
+        return m10;
+    }
+
+    /**
+     * Gets the x coordinate of the translation vector.
+     * 
+     * @return the x coordinate of the translation vector.
+     */
+    public double getTranslateX() {
+        return m02;
+    }
+
+    /**
+     * Gets the y coordinate of the translation vector.
+     * 
+     * @return the y coordinate of the translation vector.
+     */
+    public double getTranslateY() {
+        return m12;
+    }
+
+    /**
+     * Checks if the AffineTransformation is the identity.
+     * 
+     * @return true, if the AffineTransformation is the identity.
+     */
+    public boolean isIdentity() {
+        return getType() == TYPE_IDENTITY;
+    }
+
+    /**
+     * Writes the values of the transformation matrix into the given 
+     * array of doubles. If the array has length 4, only the linear
+     * transformation part will be written into it. If it has length 
+     * greater than 4, the translation vector will be included as well.
+     * 
+     * @param matrix the array to fill with the values of the matrix.
+     * 
+     * @throws ArrayIndexOutOfBoundsException if the size of the array
+     * is 0, 1, 2, 3, or 5.
+     */
+    public void getMatrix(double[] matrix) {
+        matrix[0] = m00;
+        matrix[1] = m10;
+        matrix[2] = m01;
+        matrix[3] = m11;
+        if (matrix.length > 4) {
+            matrix[4] = m02;
+            matrix[5] = m12;
+        }
+    }
+
+    /**
+     * Gets the determinant of the linear transformation matrix.
+     * 
+     * @return the determinant of the linear transformation matrix.
+     */
+    public double getDeterminant() {
+        return m00 * m11 - m01 * m10;
+    }
+
+    /**
+     * Sets the transform in terms of a list of double values.
+     * 
+     * @param m00 the m00 coordinate of the transformation matrix.
+     * @param m10 the m10 coordinate of the transformation matrix.
+     * @param m01 the m01 coordinate of the transformation matrix.
+     * @param m11 the m11 coordinate of the transformation matrix.
+     * @param m02 the m02 coordinate of the transformation matrix.
+     * @param m12 the m12 coordinate of the transformation matrix.
+     */
+    public void setTransform(double m00, double m10, double m01, double m11, double m02, double m12) {
+        this.type = TYPE_UNKNOWN;
+        this.m00 = m00;
+        this.m10 = m10;
+        this.m01 = m01;
+        this.m11 = m11;
+        this.m02 = m02;
+        this.m12 = m12;
+    }
+
+    /**
+     * Sets the transform's data to match the data of the transform 
+     * sent as a parameter.
+     * 
+     * @param t the transform that gives the new values.
+     */
+    public void setTransform(AffineTransform t) {
+        type = t.type;
+        setTransform(t.m00, t.m10, t.m01, t.m11, t.m02, t.m12);
+    }
+
+    /**
+     * Sets the transform to the identity transform.
+     */
+    public void setToIdentity() {
+        type = TYPE_IDENTITY;
+        m00 = m11 = 1.0;
+        m10 = m01 = m02 = m12 = 0.0;
+    }
+
+    /**
+     * Sets the transformation to a translation alone.
+     * Sets the linear part of the transformation to identity 
+     * and the translation vector to the values sent as parameters.
+     * Sets the type to <code>TYPE_IDENTITY</code>
+     * if the resulting AffineTransformation is the identity 
+     * transformation, otherwise sets it to <code>TYPE_TRANSLATION</code>.
+     * 
+     * @param mx the distance to translate in the x direction.
+     * @param my the distance to translate in the y direction.
+     */
+    public void setToTranslation(double mx, double my) {
+        m00 = m11 = 1.0;
+        m01 = m10 = 0.0;
+        m02 = mx;
+        m12 = my;
+        if (mx == 0.0 && my == 0.0) {
+            type = TYPE_IDENTITY;
+        } else {
+            type = TYPE_TRANSLATION;
+        }
+    }
+
+    /**
+     * Sets the transformation to being a scale alone, eliminating 
+     * rotation, shear, and translation elements.
+     * Sets the type to <code>TYPE_IDENTITY</code>
+     * if the resulting AffineTransformation is the identity 
+     * transformation, otherwise sets it to <code>TYPE_UNKNOWN</code>.
+     * 
+     * @param scx the scaling factor in the x direction.
+     * @param scy the scaling factor in the y direction.
+     */
+    public void setToScale(double scx, double scy) {
+        m00 = scx;
+        m11 = scy;
+        m10 = m01 = m02 = m12 = 0.0;
+        if (scx != 1.0 || scy != 1.0) {
+            type = TYPE_UNKNOWN;
+        } else {
+            type = TYPE_IDENTITY;
+        }
+    }
+
+    /**
+     * Sets the transformation to being a shear alone, eliminating 
+     * rotation, scaling, and translation elements.
+     * Sets the type to <code>TYPE_IDENTITY</code>
+     * if the resulting AffineTransformation is the identity 
+     * transformation, otherwise sets it to <code>TYPE_UNKNOWN</code>.
+     * 
+     * @param shx the shearing factor in the x direction.
+     * @param shy the shearing factor in the y direction.
+     */
+    public void setToShear(double shx, double shy) {
+        m00 = m11 = 1.0;
+        m02 = m12 = 0.0;
+        m01 = shx;
+        m10 = shy;
+        if (shx != 0.0 || shy != 0.0) {
+            type = TYPE_UNKNOWN;
+        } else {
+            type = TYPE_IDENTITY;
+        }
+    }
+
+    /**
+     * Sets the transformation to being a rotation alone, eliminating 
+     * shearing, scaling, and translation elements.
+     * Sets the type to <code>TYPE_IDENTITY</code>
+     * if the resulting AffineTransformation is the identity 
+     * transformation, otherwise sets it to <code>TYPE_UNKNOWN</code>.
+     * 
+     * @param angle the angle of rotation in radians.
+     */
+    public void setToRotation(double angle) {
+        double sin = Math.sin(angle);
+        double cos = Math.cos(angle);
+        if (Math.abs(cos) < ZERO) {
+            cos = 0.0;
+            sin = sin > 0.0 ? 1.0 : -1.0;
+        } else
+            if (Math.abs(sin) < ZERO) {
+                sin = 0.0;
+                cos = cos > 0.0 ? 1.0 : -1.0;
+            }
+        m00 = m11 = cos;
+        m01 = -sin;
+        m10 = sin;
+        m02 = m12 = 0.0;
+        type = TYPE_UNKNOWN;
+    }
+
+    /**
+     * Sets the transformation to being a rotation followed by a 
+     * translation. 
+     * Sets the type to <code>TYPE_UNKNOWN</code>.
+     * 
+     * @param angle the angle of rotation in radians.
+     * @param px the distance to translate in the x direction.
+     * @param py the distance to translate in the y direction.
+     */
+    public void setToRotation(double angle, double px, double py) {
+        setToRotation(angle);
+        m02 = px * (1.0 - m00) + py * m10;
+        m12 = py * (1.0 - m00) - px * m10;
+        type = TYPE_UNKNOWN;
+    }
+
+    /**
+     * Creates a new AffineTransformation that is a translation alone
+     * with the translation vector given by the values sent as parameters.
+     * The new transformation's type is <code>TYPE_IDENTITY</code>
+     * if the AffineTransformation is the identity 
+     * transformation, otherwise it's <code>TYPE_TRANSLATION</code>.
+     * 
+     * @param mx the distance to translate in the x direction.
+     * @param my the distance to translate in the y direction.
+
+     * @return the new AffineTransformation.
+     */
+    public static AffineTransform getTranslateInstance(double mx, double my) {
+        AffineTransform t = new AffineTransform();
+        t.setToTranslation(mx, my);
+        return t;
+    }
+
+    /**
+     * Creates a new AffineTransformation that is a scale alone.
+     * The new transformation's type is <code>TYPE_IDENTITY</code>
+     * if the AffineTransformation is the identity 
+     * transformation, otherwise it's <code>TYPE_UNKNOWN</code>.
+     * 
+     * @param scx the scaling factor in the x direction.
+     * @param scY the scaling factor in the y direction.
+     * 
+     * @return the new AffineTransformation.
+     */
+    public static AffineTransform getScaleInstance(double scx, double scY) {
+        AffineTransform t = new AffineTransform();
+        t.setToScale(scx, scY);
+        return t;
+    }
+
+    /**
+     * Creates a new AffineTransformation that is a shear alone.
+     * The new transformation's type is <code>TYPE_IDENTITY</code>
+     * if the AffineTransformation is the identity 
+     * transformation, otherwise it's <code>TYPE_UNKNOWN</code>.
+     * 
+     * @param shx the shearing factor in the x direction.
+     * @param shy the shearing factor in the y direction.
+     * 
+     * @return the new AffineTransformation.
+     */
+    public static AffineTransform getShearInstance(double shx, double shy) {
+        AffineTransform m = new AffineTransform();
+        m.setToShear(shx, shy);
+        return m;
+    }
+
+    /**
+     * Creates a new AffineTransformation that is a rotation alone.
+     * The new transformation's type is <code>TYPE_IDENTITY</code>
+     * if the AffineTransformation is the identity 
+     * transformation, otherwise it's <code>TYPE_UNKNOWN</code>.
+     * 
+     * @param angle the angle of rotation in radians.
+     * 
+     * @return the new AffineTransformation.
+     */
+    public static AffineTransform getRotateInstance(double angle) {
+        AffineTransform t = new AffineTransform();
+        t.setToRotation(angle);
+        return t;
+    }
+
+    /**
+     * Creates a new AffineTransformation that is a rotation followed by a 
+     * translation. 
+     * Sets the type to <code>TYPE_UNKNOWN</code>.
+     * 
+     * @param angle the angle of rotation in radians.
+     * @param x the distance to translate in the x direction.
+     * @param y the distance to translate in the y direction.
+     * 
+     * @return the new AffineTransformation.
+     */
+    public static AffineTransform getRotateInstance(double angle, double x, double y) {
+        AffineTransform t = new AffineTransform();
+        t.setToRotation(angle, x, y);
+        return t;
+    }
+
+    /**
+     * Applies a translation to this AffineTransformation.
+     * 
+     * @param mx the distance to translate in the x direction.
+     * @param my the distance to translate in the y direction.
+     */
+    public void translate(double mx, double my) {
+        concatenate(AffineTransform.getTranslateInstance(mx, my));
+    }
+
+    /**
+     * Applies a scaling transformation to this AffineTransformation.
+     * 
+     * @param scx the scaling factor in the x direction.
+     * @param scy the scaling factor in the y direction.
+     */
+    public void scale(double scx, double scy) {
+        concatenate(AffineTransform.getScaleInstance(scx, scy));
+    }
+
+    /**
+     * Applies a shearing transformation to this AffineTransformation.
+     * 
+     * @param shx the shearing factor in the x direction.
+     * @param shy the shearing factor in the y direction.
+     */
+    public void shear(double shx, double shy) {
+        concatenate(AffineTransform.getShearInstance(shx, shy));
+    }
+
+    /**
+     * Applies a rotation transformation to this AffineTransformation.
+     * 
+     * @param angle the angle of rotation in radians.
+     */
+    public void rotate(double angle) {
+        concatenate(AffineTransform.getRotateInstance(angle));
+    }
+
+    /**
+     * Applies a rotation and translation transformation to this 
+     * AffineTransformation.
+     * 
+     * @param angle the angle of rotation in radians.
+     * @param px the distance to translate in the x direction.
+     * @param py the distance to translate in the y direction.
+     */
+    public void rotate(double angle, double px, double py) {
+        concatenate(AffineTransform.getRotateInstance(angle, px, py));
+    }
+
+    /**
+     * Multiplies the matrix representations of two AffineTransform objects.
+     * 
+     * @param t1 - the AffineTransform object is a multiplicand
+     * @param t2 - the AffineTransform object is a multiplier
+     * 
+     * @return an AffineTransform object that is the result of t1 multiplied by the matrix t2.
+     */
+    AffineTransform multiply(AffineTransform t1, AffineTransform t2) {
+        return new AffineTransform(
+                t1.m00 * t2.m00 + t1.m10 * t2.m01,          // m00
+                t1.m00 * t2.m10 + t1.m10 * t2.m11,          // m01
+                t1.m01 * t2.m00 + t1.m11 * t2.m01,          // m10
+                t1.m01 * t2.m10 + t1.m11 * t2.m11,          // m11
+                t1.m02 * t2.m00 + t1.m12 * t2.m01 + t2.m02, // m02
+                t1.m02 * t2.m10 + t1.m12 * t2.m11 + t2.m12);// m12
+    }
+
+    /**
+     * Applies the given AffineTransform to this AffineTransform
+     * via matrix multiplication.
+     * 
+     * @param t the AffineTransform to apply to this AffineTransform.
+     */
+    public void concatenate(AffineTransform t) {
+        setTransform(multiply(t, this));
+    }
+
+    /**
+     * Changes the current AffineTransform the one obtained by 
+     * taking the transform t and applying this AffineTransform to it.
+     * 
+     * @param t the AffineTransform that this AffineTransform is multiplied by.
+     */
+    public void preConcatenate(AffineTransform t) {
+        setTransform(multiply(this, t));
+    }
+
+    /**
+     * Creates an AffineTransform that is the inverse of this transform.
+     * 
+     * @return the affine transform that is the inverse of this AffineTransform.
+     * 
+     * @throws NoninvertibleTransformException if this AffineTransform cannot be 
+     * inverted (the determinant of the linear transformation part is zero).
+     */
+    public AffineTransform createInverse() throws NoninvertibleTransformException {
+        double det = getDeterminant();
+        if (Math.abs(det) < ZERO) {
+            // awt.204=Determinant is zero
+            throw new NoninvertibleTransformException(Messages.getString("awt.204")); //$NON-NLS-1$
+        }
+        return new AffineTransform(
+                 m11 / det, // m00
+                -m10 / det, // m10
+                -m01 / det, // m01
+                 m00 / det, // m11
+                (m01 * m12 - m11 * m02) / det, // m02
+                (m10 * m02 - m00 * m12) / det  // m12
+        );
+    }
+
+    /**
+     * Apply the current AffineTransform to the point.
+     * 
+     * @param src the original point.
+     * @param dst Point2D object to be filled with the destination
+     * coordinates (where the original point is sent by this AffineTransform). May be null.
+     * 
+     * @return the point in the AffineTransform's image space where the
+     * original point is sent.
+     */
+    public Point2D transform(Point2D src, Point2D dst) {
+        if (dst == null) {
+            if (src instanceof Point2D.Double) {
+                dst = new Point2D.Double();
+            } else {
+                dst = new Point2D.Float();
+            }
+        }
+
+        double x = src.getX();
+        double y = src.getY();
+
+        dst.setLocation(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12);
+        return dst;
+    }
+
+    /**
+     * Applies this AffineTransform to an array of points.
+     * 
+     * @param src the array of points to be transformed.
+     * @param srcOff the offset in the source point array of the first point
+     * to be transformed.
+     * @param dst the point array where the images of the points (after 
+     * applying the AffineTransformation) should be placed.
+     * @param dstOff the offset in the destination array where the new 
+     * values should be written.
+     * @param length the number of points to transform.
+     * 
+     * @throws ArrayIndexOutOfBoundsException if 
+     * <code>srcOff + length > src.length</code> or
+     * <code>dstOff + length > dst.length</code>.
+     */
+    public void transform(Point2D[] src, int srcOff, Point2D[] dst, int dstOff, int length) {
+        while (--length >= 0) {
+            Point2D srcPoint = src[srcOff++]; 
+            double x = srcPoint.getX();
+            double y = srcPoint.getY();
+            Point2D dstPoint = dst[dstOff]; 
+            if (dstPoint == null) {
+                if (srcPoint instanceof Point2D.Double) {
+                    dstPoint = new Point2D.Double();
+                } else {
+                    dstPoint = new Point2D.Float();
+                }
+            }
+            dstPoint.setLocation(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12);
+            dst[dstOff++] = dstPoint;
+        }
+    }
+    
+    /**
+     * Applies this AffineTransform to a set of points given 
+     * as an array of double values where every two values in the array 
+     * give the coordinates of a point; the even-indexed values giving the
+     * x coordinates and the odd-indexed values giving the y coordinates.
+     * 
+     * @param src the array of points to be transformed.
+     * @param srcOff the offset in the source point array of the first point
+     * to be transformed.
+     * @param dst the point array where the images of the points (after 
+     * applying the AffineTransformation) should be placed.
+     * @param dstOff the offset in the destination array where the new 
+     * values should be written.
+     * @param length the number of points to transform.
+     * 
+     * @throws ArrayIndexOutOfBoundsException if 
+     * <code>srcOff + length*2 > src.length</code> or
+     * <code>dstOff + length*2 > dst.length</code>.
+     */
+     public void transform(double[] src, int srcOff, double[] dst, int dstOff, int length) {
+        int step = 2;
+        if (src == dst && srcOff < dstOff && dstOff < srcOff + length * 2) {
+            srcOff = srcOff + length * 2 - 2;
+            dstOff = dstOff + length * 2 - 2;
+            step = -2;
+        }
+        while (--length >= 0) {
+            double x = src[srcOff + 0];
+            double y = src[srcOff + 1];
+            dst[dstOff + 0] = x * m00 + y * m01 + m02;
+            dst[dstOff + 1] = x * m10 + y * m11 + m12;
+            srcOff += step;
+            dstOff += step;
+        }
+    }
+
+    /**
+     * Applies this AffineTransform to a set of points given 
+     * as an array of float values where every two values in the array 
+     * give the coordinates of a point; the even-indexed values giving the
+     * x coordinates and the odd-indexed values giving the y coordinates.
+     * 
+     * @param src the array of points to be transformed.
+     * @param srcOff the offset in the source point array of the first point
+     * to be transformed.
+     * @param dst the point array where the images of the points (after 
+     * applying the AffineTransformation) should be placed.
+     * @param dstOff the offset in the destination array where the new 
+     * values should be written.
+     * @param length the number of points to transform.
+     * 
+     * @throws ArrayIndexOutOfBoundsException if 
+     * <code>srcOff + length*2 > src.length</code> or
+     * <code>dstOff + length*2 > dst.length</code>.
+     */
+    public void transform(float[] src, int srcOff, float[] dst, int dstOff, int length) {
+        int step = 2;
+        if (src == dst && srcOff < dstOff && dstOff < srcOff + length * 2) {
+            srcOff = srcOff + length * 2 - 2;
+            dstOff = dstOff + length * 2 - 2;
+            step = -2;
+        }
+        while (--length >= 0) {
+            float x = src[srcOff + 0];
+            float y = src[srcOff + 1];
+            dst[dstOff + 0] = (float)(x * m00 + y * m01 + m02);
+            dst[dstOff + 1] = (float)(x * m10 + y * m11 + m12);
+            srcOff += step;
+            dstOff += step;
+        }
+    }
+    
+    /**
+     * Applies this AffineTransform to a set of points given 
+     * as an array of float values where every two values in the array 
+     * give the coordinates of a point; the even-indexed values giving the
+     * x coordinates and the odd-indexed values giving the y coordinates.
+     * The destination coordinates are given as values of type <code>double</code>.
+     * 
+     * @param src the array of points to be transformed.
+     * @param srcOff the offset in the source point array of the first point
+     * to be transformed.
+     * @param dst the point array where the images of the points (after 
+     * applying the AffineTransformation) should be placed.
+     * @param dstOff the offset in the destination array where the new 
+     * values should be written.
+     * @param length the number of points to transform.
+     * 
+     * @throws ArrayIndexOutOfBoundsException if 
+     * <code>srcOff + length*2 > src.length</code> or
+     * <code>dstOff + length*2 > dst.length</code>.
+     */
+    public void transform(float[] src, int srcOff, double[] dst, int dstOff, int length) {
+        while (--length >= 0) {
+            float x = src[srcOff++];
+            float y = src[srcOff++];
+            dst[dstOff++] = x * m00 + y * m01 + m02;
+            dst[dstOff++] = x * m10 + y * m11 + m12;
+        }
+    }
+
+    /**
+     * Applies this AffineTransform to a set of points given 
+     * as an array of double values where every two values in the array 
+     * give the coordinates of a point; the even-indexed values giving the
+     * x coordinates and the odd-indexed values giving the y coordinates.
+     * The destination coordinates are given as values of type <code>float</code>.
+     * 
+     * @param src the array of points to be transformed.
+     * @param srcOff the offset in the source point array of the first point
+     * to be transformed.
+     * @param dst the point array where the images of the points (after 
+     * applying the AffineTransformation) should be placed.
+     * @param dstOff the offset in the destination array where the new 
+     * values should be written.
+     * @param length the number of points to transform.
+     * 
+     * @throws ArrayIndexOutOfBoundsException if 
+     * <code>srcOff + length*2 > src.length</code> or
+     * <code>dstOff + length*2 > dst.length</code>.
+     */
+    public void transform(double[] src, int srcOff, float[] dst, int dstOff, int length) {
+        while (--length >= 0) {
+            double x = src[srcOff++];
+            double y = src[srcOff++];
+            dst[dstOff++] = (float)(x * m00 + y * m01 + m02);
+            dst[dstOff++] = (float)(x * m10 + y * m11 + m12);
+        }
+    }
+
+    /**
+     * Transforms the point according to the linear transformation
+     * part of this AffineTransformation (without applying the translation).
+     * 
+     * @param src the original point.
+     * @param dst the point object where the result of the delta transform
+     * is written.
+     * 
+     * @return the result of applying the delta transform (linear part 
+     * only) to the original point.
+     */
+    // TODO: is this right? if dst is null, we check what it's an
+    // instance of? Shouldn't it be src instanceof Point2D.Double?
+    public Point2D deltaTransform(Point2D src, Point2D dst) {
+        if (dst == null) {
+            if (dst instanceof Point2D.Double) {
+                dst = new Point2D.Double();
+            } else {
+                dst = new Point2D.Float();
+            }
+        }
+
+        double x = src.getX();
+        double y = src.getY();
+
+        dst.setLocation(x * m00 + y * m01, x * m10 + y * m11);
+        return dst;
+    }
+
+    /**
+     * Applies the linear transformation part of this AffineTransform 
+     * (ignoring the translation part) to a set of points given 
+     * as an array of double values where every two values in the array 
+     * give the coordinates of a point; the even-indexed values giving the
+     * x coordinates and the odd-indexed values giving the y coordinates.
+     * 
+     * @param src the array of points to be transformed.
+     * @param srcOff the offset in the source point array of the first point
+     * to be transformed.
+     * @param dst the point array where the images of the points (after 
+     * applying the delta transformation) should be placed.
+     * @param dstOff the offset in the destination array where the new 
+     * values should be written.
+     * @param length the number of points to transform.
+     * 
+     * @throws ArrayIndexOutOfBoundsException if 
+     * <code>srcOff + length*2 > src.length</code> or
+     * <code>dstOff + length*2 > dst.length</code>.
+     */
+    public void deltaTransform(double[] src, int srcOff, double[] dst, int dstOff, int length) {
+        while (--length >= 0) {
+            double x = src[srcOff++];
+            double y = src[srcOff++];
+            dst[dstOff++] = x * m00 + y * m01;
+            dst[dstOff++] = x * m10 + y * m11;
+        }
+    }
+
+    /**
+     * Transforms the point according to the inverse of this AffineTransformation.
+     * 
+     * @param src the original point.
+     * @param dst the point object where the result of the inverse transform
+     * is written (may be null).
+     * 
+     * @return the result of applying the inverse transform.
+     * Inverse transform.
+     * 
+     * @throws NoninvertibleTransformException if this AffineTransform cannot be 
+     * inverted (the determinant of the linear transformation part is zero).
+     */
+    public Point2D inverseTransform(Point2D src, Point2D dst) throws NoninvertibleTransformException {
+        double det = getDeterminant();
+        if (Math.abs(det) < ZERO) {
+            // awt.204=Determinant is zero
+            throw new NoninvertibleTransformException(Messages.getString("awt.204")); //$NON-NLS-1$
+        }
+
+        if (dst == null) {
+            if (src instanceof Point2D.Double) {
+                dst = new Point2D.Double();
+            } else {
+                dst = new Point2D.Float();
+            }
+        }
+
+        double x = src.getX() - m02;
+        double y = src.getY() - m12;
+
+        dst.setLocation((x * m11 - y * m01) / det, (y * m00 - x * m10) / det);
+        return dst;
+    }
+
+    /**
+     * Applies the inverse of this AffineTransform to a set of points given 
+     * as an array of double values where every two values in the array 
+     * give the coordinates of a point; the even-indexed values giving the
+     * x coordinates and the odd-indexed values giving the y coordinates.
+     * 
+     * @param src the array of points to be transformed.
+     * @param srcOff the offset in the source point array of the first point
+     * to be transformed.
+     * @param dst the point array where the images of the points (after 
+     * applying the inverse of the AffineTransformation) should be placed.
+     * @param dstOff the offset in the destination array where the new 
+     * values should be written.
+     * @param length the number of points to transform.
+     * 
+     * @throws ArrayIndexOutOfBoundsException if 
+     * <code>srcOff + length*2 > src.length</code> or
+     * <code>dstOff + length*2 > dst.length</code>.
+     * @throws NoninvertibleTransformException if this AffineTransform cannot be 
+     * inverted (the determinant of the linear transformation part is zero).
+     */
+    public void inverseTransform(double[] src, int srcOff, double[] dst, int dstOff, int length)
+        throws NoninvertibleTransformException
+    {
+        double det = getDeterminant();
+        if (Math.abs(det) < ZERO) {
+            // awt.204=Determinant is zero
+            throw new NoninvertibleTransformException(Messages.getString("awt.204")); //$NON-NLS-1$
+        }
+
+        while (--length >= 0) {
+            double x = src[srcOff++] - m02;
+            double y = src[srcOff++] - m12;
+            dst[dstOff++] = (x * m11 - y * m01) / det;
+            dst[dstOff++] = (y * m00 - x * m10) / det;
+        }
+    }
+
+    /**
+     * Creates a new shape whose data is given by applying this 
+     * AffineTransform to the specified shape.
+     * 
+     * @param src the original shape whose data is to be transformed.
+     * 
+     * @return the new shape found by applying this AffineTransform to 
+     * the original shape.
+     */
+    public Shape createTransformedShape(Shape src) {
+        if (src == null) {
+            return null;
+        }
+        if (src instanceof GeneralPath) {
+            return ((GeneralPath)src).createTransformedShape(this);
+        }
+        PathIterator path = src.getPathIterator(this);
+        GeneralPath dst = new GeneralPath(path.getWindingRule());
+        dst.append(path, false);
+        return dst;
+    }
+
+    @Override
+    public String toString() {
+        return
+            getClass().getName() +
+            "[[" + m00 + ", " + m01 + ", " + m02 + "], [" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+                + m10 + ", " + m11 + ", " + m12 + "]]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+    }
+
+    @Override
+    public Object clone() {
+        try {
+            return super.clone();
+        } catch (CloneNotSupportedException e) {
+            throw new InternalError();
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        HashCode hash = new HashCode();
+        hash.append(m00);
+        hash.append(m01);
+        hash.append(m02);
+        hash.append(m10);
+        hash.append(m11);
+        hash.append(m12);
+        return hash.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (obj instanceof AffineTransform) {
+            AffineTransform t = (AffineTransform)obj;
+            return
+                m00 == t.m00 && m01 == t.m01 &&
+                m02 == t.m02 && m10 == t.m10 &&
+                m11 == t.m11 && m12 == t.m12;
+        }
+        return false;
+    }
+
+    
+    /**
+     * Writes the AffineTrassform object to the output steam.
+     * 
+     * @param stream - the output stream
+     * 
+     * @throws IOException - if there are I/O errors while writing to the output strem
+     */
+    private void writeObject(java.io.ObjectOutputStream stream) throws IOException {
+        stream.defaultWriteObject();
+    }
+
+    
+    /**
+     * Read the AffineTransform object from the input stream.
+     * 
+     * @param stream - the input steam
+     * 
+     * @throws IOException - if there are I/O errors while reading from the input strem
+     * @throws ClassNotFoundException - if class could not be found
+     */
+    private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
+        stream.defaultReadObject();
+        type = TYPE_UNKNOWN;
+    }
+
+}
+
diff --git a/awt/java/awt/geom/Arc2D.java b/awt/java/awt/geom/Arc2D.java
new file mode 100644
index 0000000..bc1e95c
--- /dev/null
+++ b/awt/java/awt/geom/Arc2D.java
@@ -0,0 +1,1028 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Denis M. Kishenko
+ * @version $Revision$
+ */
+package java.awt.geom;
+
+import java.util.NoSuchElementException;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Class Arc2D represents a segment of a curve inscribed 
+ * in a rectangle. The curve is defined by a start angle and an 
+ * extent angle (the end angle minus the start angle) as 
+ * a pie wedge whose point is in the center of the rectangle.
+ * The Arc2D as a shape may be either OPEN (including nothing 
+ * but the curved arc segment itself), CHORD (the curved arc
+ * segment closed by a connecting segment from the end to the 
+ * beginning of the arc, or PIE (the segments from the end 
+ * of the arc to the center of the rectangle and from the
+ * center of the rectangle back to the arc's start point are 
+ * included).
+ */
+public abstract class Arc2D extends RectangularShape {
+
+    /** The arc type OPEN indicates that the shape includes only the 
+     * curved arc segment. */
+    public final static int OPEN = 0;
+    
+    /** The arc type CHORD indicates that as a shape the connecting
+     * segment from the end point of the curved arc to the beginning
+     * point is included. */
+    public final static int CHORD = 1;
+    
+    /** The arc type PIE indicates that as a shape the two segments 
+     * from the arc's endpoint to the center of the rectangle and from 
+     * the center of the rectangle to the arc's endpoint are included. */
+    public final static int PIE = 2;
+
+    /**
+     * The Class Float is a subclass of Arc2D in which all of the 
+     * data values are given as floats.
+     * @see Arc2D.Double
+     */
+    public static class Float extends Arc2D {
+
+        /** The x coordinate of the upper left corner of the rectangle that
+         * contains the arc. */
+        public float x;
+        
+        /** The y coordinate of the upper left corner of the rectangle that
+         * contains the arc. */
+        public float y;
+        
+        /** The width of the rectangle that contains the arc. */
+        public float width;
+        
+        /** The height of the rectangle that contains the arc. */
+        public float height;
+        
+        /** The start angle of the arc in degrees. */
+        public float start;
+        
+        /** The width angle of the arc in degrees. */
+        public float extent;
+
+        /**
+         * Instantiates a new Arc2D of type OPEN with float values.
+         */
+        public Float() {
+            super(OPEN);
+        }
+
+        /**
+         * Instantiates a new Arc2D of the specified type with float values.
+         * 
+         * @param type the type of the new Arc2D, either {@link Arc2D#OPEN}, 
+         * {@link Arc2D#CHORD}, or {@link Arc2D#PIE}.
+         */
+        public Float(int type) {
+            super(type);
+        }
+
+        /**
+         * Instantiates a Arc2D with the specified float-valued data.
+         * 
+         * @param x the x coordinate of the upper left corner of the rectangle that
+         * contains the arc.
+         * @param y the y coordinate of the upper left corner of the rectangle that
+         * contains the arc.
+         * @param width the width of the rectangle that
+         * contains the arc.
+         * @param height the height of the rectangle that
+         * contains the arc.
+         * @param start the start angle of the arc in degrees.
+         * @param extent the width angle of the arc in degrees.
+         * @param type the type of the new Arc2D, either {@link Arc2D#OPEN}, 
+         * {@link Arc2D#CHORD}, or {@link Arc2D#PIE}.
+         */
+        public Float(float x, float y, float width, float height, float start, float extent, int type) {
+            super(type);
+            this.x = x;
+            this.y = y;
+            this.width = width;
+            this.height = height;
+            this.start = start;
+            this.extent = extent;
+        }
+
+        /**
+         * Instantiates a new Angle2D with the specified float-valued data
+         * and the bounding rectangle given by the parameter bounds.
+         * 
+         * @param bounds the bounding rectangle of the Angle2D.
+         * @param start the start angle of the arc in degrees.
+         * @param extent the width angle of the arc in degrees.
+         * @param type the type of the new Arc2D, either {@link Arc2D#OPEN}, 
+         * {@link Arc2D#CHORD}, or {@link Arc2D#PIE}.
+         */
+        public Float(Rectangle2D bounds, float start, float extent, int type) {
+            super(type);
+            this.x = (float)bounds.getX();
+            this.y = (float)bounds.getY();
+            this.width = (float)bounds.getWidth();
+            this.height = (float)bounds.getHeight();
+            this.start = start;
+            this.extent = extent;
+        }
+
+        @Override
+        public double getX() {
+            return x;
+        }
+
+       @Override
+       public double getY() {
+            return y;
+        }
+
+        @Override
+        public double getWidth() {
+            return width;
+        }
+
+        @Override
+        public double getHeight() {
+            return height;
+        }
+
+        @Override
+        public double getAngleStart() {
+            return start;
+        }
+
+        @Override
+        public double getAngleExtent() {
+            return extent;
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return width <= 0.0f || height <= 0.0f;
+        }
+
+        @Override
+        public void setArc(double x, double y, double width, double height,
+                double start, double extent, int type)
+        {
+            this.setArcType(type);
+            this.x = (float)x;
+            this.y = (float)y;
+            this.width = (float)width;
+            this.height = (float)height;
+            this.start = (float)start;
+            this.extent = (float)extent;
+        }
+
+        @Override
+        public void setAngleStart(double start) {
+            this.start = (float)start;
+        }
+
+        @Override
+        public void setAngleExtent(double extent) {
+            this.extent = (float)extent;
+        }
+
+        @Override
+        protected Rectangle2D makeBounds(double x, double y, double width, double height) {
+            return new Rectangle2D.Float((float)x, (float)y, (float)width, (float)height);
+        }
+
+    }
+
+    /**
+     * The Class Double is a subclass of Arc2D in which all of the 
+     * data values are given as doubles.
+     * @see Arc2D.Float
+     */
+    public static class Double extends Arc2D {
+
+        /** The x coordinate of the upper left corner of the rectangle that
+         * contains the arc. */
+        public double x;
+        
+        /** The y coordinate of the upper left corner of the rectangle that
+         * contains the arc. */
+        public double y;
+        
+        /** The width of the rectangle that contains the arc. */
+        public double width;
+        
+        /** The height of the rectangle that contains the arc. */
+        public double height;
+        
+        /** The start angle of the arc in degrees. */
+        public double start;
+        
+        /** The width angle of the arc in degrees. */
+        public double extent;
+
+        /**
+         * Instantiates a new Arc2D of type OPEN with double values.
+         */
+        public Double() {
+            super(OPEN);
+        }
+
+        /**
+         * Instantiates a new Arc2D of the specified type with double values.
+         * 
+         * @param type the type of the new Arc2D, either {@link Arc2D#OPEN}, 
+         * {@link Arc2D#CHORD}, or {@link Arc2D#PIE}.
+         */
+        public Double(int type) {
+            super(type);
+        }
+
+        /**
+         * Instantiates a Arc2D with the specified double-valued data.
+         * 
+         * @param x the x coordinate of the upper left corner of the rectangle that
+         * contains the arc.
+         * @param y the y coordinate of the upper left corner of the rectangle that
+         * contains the arc.
+         * @param width the width of the rectangle that
+         * contains the arc.
+         * @param height the height of the rectangle that
+         * contains the arc.
+         * @param start the start angle of the arc in degrees.
+         * @param extent the width angle of the arc in degrees.
+         * @param type the type of the new Arc2D, either {@link Arc2D#OPEN}, 
+         * {@link Arc2D#CHORD}, or {@link Arc2D#PIE}.
+         */
+        public Double(double x, double y, double width, double height,
+                double start, double extent, int type)
+        {
+            super(type);
+            this.x = x;
+            this.y = y;
+            this.width = width;
+            this.height = height;
+            this.start = start;
+            this.extent = extent;
+        }
+
+        /**
+         * Instantiates a new Angle2D with the specified float-valued data
+         * and the bounding rectangle given by the parameter bounds.
+         * 
+         * @param bounds the bounding rectangle of the Angle2D.
+         * @param start the start angle of the arc in degrees.
+         * @param extent the width angle of the arc in degrees.
+         * @param type the type of the new Arc2D, either {@link Arc2D#OPEN}, 
+         * {@link Arc2D#CHORD}, or {@link Arc2D#PIE}.
+         */
+        public Double(Rectangle2D bounds, double start, double extent, int type) {
+            super(type);
+            this.x = bounds.getX();
+            this.y = bounds.getY();
+            this.width = bounds.getWidth();
+            this.height = bounds.getHeight();
+            this.start = start;
+            this.extent = extent;
+        }
+
+        @Override
+        public double getX() {
+            return x;
+        }
+
+        @Override
+        public double getY() {
+            return y;
+        }
+
+        @Override
+        public double getWidth() {
+            return width;
+        }
+
+        @Override
+        public double getHeight() {
+            return height;
+        }
+
+        @Override
+        public double getAngleStart() {
+            return start;
+        }
+
+        @Override
+        public double getAngleExtent() {
+            return extent;
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return width <= 0.0 || height <= 0.0;
+        }
+
+        @Override
+        public void setArc(double x, double y, double width, double height,
+                double start, double extent, int type)
+        {
+            this.setArcType(type);
+            this.x = x;
+            this.y = y;
+            this.width = width;
+            this.height = height;
+            this.start = start;
+            this.extent = extent;
+        }
+
+        @Override
+        public void setAngleStart(double start) {
+            this.start = start;
+        }
+
+        @Override
+        public void setAngleExtent(double extent) {
+            this.extent = extent;
+        }
+
+        @Override
+        protected Rectangle2D makeBounds(double x, double y, double width, double height) {
+            return new Rectangle2D.Double(x, y, width, height);
+        }
+
+    }
+
+    /**
+     * The Class Iterator is the subclass of PathIterator that is used to 
+     * traverse the boundary of a shape of type Arc2D.
+     */
+    class Iterator implements PathIterator {
+
+        /** The x coordinate of the center of the arc's bounding rectangle. */
+        double x;
+
+        /** The y coordinate of the center of the arc's bounding rectangle. */
+        double y;
+
+        /** Half of the width of the arc's bounding rectangle (the radius in the case of a circular arc). */
+        double width;
+        
+        /** Half of the height of the arc's bounding rectangle (the radius in the case of a circular arc). */
+        double height;
+        
+        /** The start angle of the arc in degrees. */
+        double angle;
+        
+        /** The angle extent in degrees. */
+        double extent;
+         
+        /** The closure type of the arc. */
+        int type;
+        
+        /** The path iterator transformation. */
+        AffineTransform t;
+        
+        /** The current segment index. */
+        int index;
+        
+        /** The number of arc segments the source arc subdivided to be approximated by Bezier curves. Depends on extent value. */
+        int arcCount;
+        
+        /** The number of line segments. Depends on closure type. */
+        int lineCount;
+        
+        /** The step to calculate next arc subdivision point. */
+        double step;
+        
+        /** The temporary value of cosinus of the current angle. */
+        double cos;
+
+        /** The temporary value of sinus of the current angle. */
+        double sin;
+        
+        /** The coefficient to calculate control points of Bezier curves. */
+        double k;
+        
+        /** The temporary value of x coordinate of the Bezier curve control vector. */
+        double kx;
+
+        /** The temporary value of y coordinate of the Bezier curve control vector. */
+        double ky;
+        
+        /** The x coordinate of the first path point (MOVE_TO). */
+        double mx;
+        
+        /** The y coordinate of the first path point (MOVE_TO). */
+        double my;
+
+        /**
+         * Constructs a new Arc2D.Iterator for given line and transformation
+         * 
+         * @param a - the source Arc2D object
+         * @param t the AffineTransformation.
+         */
+        Iterator(Arc2D a, AffineTransform t) {
+            if (width < 0 || height < 0) {
+                arcCount = 0;
+                lineCount = 0;
+                index = 1;
+                return;
+            }
+
+            this.width = a.getWidth() / 2.0;
+            this.height = a.getHeight() / 2.0;
+            this.x = a.getX() + width;
+            this.y = a.getY() + height;
+            this.angle = -Math.toRadians(a.getAngleStart());
+            this.extent = -a.getAngleExtent();
+            this.type = a.getArcType();
+            this.t = t;
+
+            if (Math.abs(extent) >= 360.0) {
+                arcCount = 4;
+                k = 4.0 / 3.0 * (Math.sqrt(2.0) - 1.0);
+                step = Math.PI / 2.0;
+                if (extent < 0.0) {
+                    step = -step;
+                    k = -k;
+                }
+            } else {
+                arcCount = (int)Math.rint(Math.abs(extent) / 90.0);
+                step = Math.toRadians(extent / arcCount);
+                k = 4.0 / 3.0 * (1.0 - Math.cos(step / 2.0))
+                        / Math.sin(step / 2.0);
+            }
+
+            lineCount = 0;
+            if (type == Arc2D.CHORD) {
+                lineCount++;
+            } else if (type == Arc2D.PIE) {
+                lineCount += 2;
+            }
+        }
+
+        public int getWindingRule() {
+            return WIND_NON_ZERO;
+        }
+
+        public boolean isDone() {
+            return index > arcCount + lineCount;
+        }
+
+        public void next() {
+            index++;
+        }
+
+        public int currentSegment(double[] coords) {
+            if (isDone()) {
+                // awt.4B=Iterator out of bounds
+                throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
+            }
+            int type;
+            int count;
+            if (index == 0) {
+                type = SEG_MOVETO;
+                count = 1;
+                cos = Math.cos(angle);
+                sin = Math.sin(angle);
+                kx = k * width * sin;
+                ky = k * height * cos;
+                coords[0] = mx = x + cos * width;
+                coords[1] = my = y + sin * height;
+            } else if (index <= arcCount) {
+                type = SEG_CUBICTO;
+                count = 3;
+                coords[0] = mx - kx;
+                coords[1] = my + ky;
+                angle += step;
+                cos = Math.cos(angle);
+                sin = Math.sin(angle);
+                kx = k * width * sin;
+                ky = k * height * cos;
+                coords[4] = mx = x + cos * width;
+                coords[5] = my = y + sin * height;
+                coords[2] = mx + kx;
+                coords[3] = my - ky;
+            } else if (index == arcCount + lineCount) {
+                type = SEG_CLOSE;
+                count = 0;
+            } else {
+                type = SEG_LINETO;
+                count = 1;
+                coords[0] = x;
+                coords[1] = y;
+            }
+            if (t != null) {
+                t.transform(coords, 0, coords, 0, count);
+            }
+            return type;
+        }
+
+        public int currentSegment(float[] coords) {
+            if (isDone()) {
+                // awt.4B=Iterator out of bounds
+                throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
+            }
+            int type;
+            int count;
+            if (index == 0) {
+                type = SEG_MOVETO;
+                count = 1;
+                cos = Math.cos(angle);
+                sin = Math.sin(angle);
+                kx = k * width * sin;
+                ky = k * height * cos;
+                coords[0] = (float)(mx = x + cos * width);
+                coords[1] = (float)(my = y + sin * height);
+            } else if (index <= arcCount) {
+                type = SEG_CUBICTO;
+                count = 3;
+                coords[0] = (float)(mx - kx);
+                coords[1] = (float)(my + ky);
+                angle += step;
+                cos = Math.cos(angle);
+                sin = Math.sin(angle);
+                kx = k * width * sin;
+                ky = k * height * cos;
+                coords[4] = (float)(mx = x + cos * width);
+                coords[5] = (float)(my = y + sin * height);
+                coords[2] = (float)(mx + kx);
+                coords[3] = (float)(my - ky);
+            } else if (index == arcCount + lineCount) {
+                type = SEG_CLOSE;
+                count = 0;
+            } else {
+                type = SEG_LINETO;
+                count = 1;
+                coords[0] = (float)x;
+                coords[1] = (float)y;
+            }
+            if (t != null) {
+                t.transform(coords, 0, coords, 0, count);
+            }
+            return type;
+        }
+
+    }
+
+    /** The closure type of the arc. */
+    private int type;
+
+    /**
+     * Instantiates a new arc2D.
+     * 
+     * @param type the closure type.
+     */
+    protected Arc2D(int type) {
+        setArcType(type);
+    }
+
+    /**
+     * Takes the double-valued data and creates the corresponding Rectangle2D
+     * object with values either of type float or of type double depending on
+     * whether this Arc2D instance is of type Float or Double.
+     * 
+     * @param x the x coordinate of the upper left corner of the bounding rectangle.
+     * @param y the y coordinate of the upper left corner of the bounding rectangle.
+     * @param width the width of the bounding rectangle.
+     * @param height the height of the bounding rectangle.
+     * 
+     * @return the corresponding Rectangle2D object.
+     */
+    protected abstract Rectangle2D makeBounds(double x, double y, double width, double height);
+
+    /**
+     * Gets the start angle.
+     * 
+     * @return the start angle.
+     */
+    public abstract double getAngleStart();
+
+    /**
+     * Gets the width angle.
+     * 
+     * @return the width angle.
+     */
+    public abstract double getAngleExtent();
+
+    /**
+     * Sets the start angle.
+     * 
+     * @param start the new start angle.
+     */
+    public abstract void setAngleStart(double start);
+
+    /**
+     * Sets the width angle.
+     * 
+     * @param extent the new width angle.
+     */
+    public abstract void setAngleExtent(double extent);
+
+    /**
+     * Sets the data values that define the arc.
+     * 
+     * @param x the x coordinate of the upper left corner of the rectangle that
+     * contains the arc.
+     * @param y the y coordinate of the upper left corner of the rectangle that
+     * contains the arc.
+     * @param width the width of the rectangle that
+     * contains the arc.
+     * @param height the height of the rectangle that
+     * contains the arc.
+     * @param start the start angle of the arc in degrees.
+     * @param extent the width angle of the arc in degrees.
+     * @param type the type of the new Arc2D, either {@link Arc2D#OPEN}, 
+     * {@link Arc2D#CHORD}, or {@link Arc2D#PIE}.
+     */
+    public abstract void setArc(double x, double y, double width,
+            double height, double start, double extent, int type);
+
+    /**
+     * Gets the arc type, either {@link Arc2D#OPEN}, 
+     * {@link Arc2D#CHORD}, or {@link Arc2D#PIE}.
+     * 
+     * @return the arc type.
+     */
+    public int getArcType() {
+        return type;
+    }
+
+    /**
+     * Sets the arc type, either {@link Arc2D#OPEN}, 
+     * {@link Arc2D#CHORD}, or {@link Arc2D#PIE}.
+     * 
+     * @param type the new arc type.
+     */
+    public void setArcType(int type) {
+        if (type != OPEN && type != CHORD && type != PIE) {
+            // awt.205=Invalid type of Arc: {0}
+            throw new IllegalArgumentException(Messages.getString("awt.205", type)); //$NON-NLS-1$
+        }
+        this.type = type;
+    }
+
+    /**
+     * Gets the start point of the arc as a Point2D.
+     * 
+     * @return the start point of the curved arc segment.
+     */
+    public Point2D getStartPoint() {
+        double a = Math.toRadians(getAngleStart());
+        return new Point2D.Double(
+                getX() + (1.0 + Math.cos(a)) * getWidth() / 2.0,
+                getY() + (1.0 - Math.sin(a)) * getHeight() / 2.0);
+    }
+
+    /**
+     * Gets the end point of the arc as a Point2D.
+     * 
+     * @return the end point of the curved arc segment.
+     */
+    public Point2D getEndPoint() {
+        double a = Math.toRadians(getAngleStart() + getAngleExtent());
+        return new Point2D.Double(
+                getX() + (1.0 + Math.cos(a)) * getWidth() / 2.0,
+                getY() + (1.0 - Math.sin(a)) * getHeight() / 2.0);
+    }
+
+    public Rectangle2D getBounds2D() {
+        if (isEmpty()) {
+            return makeBounds(getX(), getY(), getWidth(), getHeight());
+        }
+        double rx1 = getX();
+        double ry1 = getY();
+        double rx2 = rx1 + getWidth();
+        double ry2 = ry1 + getHeight();
+
+        Point2D p1 = getStartPoint();
+        Point2D p2 = getEndPoint();
+
+        double bx1 = containsAngle(180.0) ? rx1 : Math.min(p1.getX(), p2.getX());
+        double by1 = containsAngle(90.0)  ? ry1 : Math.min(p1.getY(), p2.getY());
+        double bx2 = containsAngle(0.0)   ? rx2 : Math.max(p1.getX(), p2.getX());
+        double by2 = containsAngle(270.0) ? ry2 : Math.max(p1.getY(), p2.getY());
+
+        if (type == PIE) {
+            double cx = getCenterX();
+            double cy = getCenterY();
+            bx1 = Math.min(bx1, cx);
+            by1 = Math.min(by1, cy);
+            bx2 = Math.max(bx2, cx);
+            by2 = Math.max(by2, cy);
+        }
+        return makeBounds(bx1, by1, bx2 - bx1, by2 - by1);
+    }
+
+    @Override
+    public void setFrame(double x, double y, double width, double height) {
+        setArc(x, y, width, height, getAngleStart(), getAngleExtent(), type);
+    }
+
+    /**
+     * Sets the data that defines the arc.
+     * 
+     * @param point the upper left corner of the bounding rectangle.
+     * @param size the size of the bounding rectangle.
+     * @param start the start angle of the arc in degrees.
+     * @param extent the angle witdth of the arc in degrees.
+     * @param type the closure type, either {@link Arc2D#OPEN}, 
+     * {@link Arc2D#CHORD}, or {@link Arc2D#PIE}.
+     */
+    public void setArc(Point2D point, Dimension2D size, double start, double extent, int type) {
+        setArc(point.getX(), point.getY(), size.getWidth(), size.getHeight(), start, extent, type);
+    }
+
+    /**
+     * Sets the data that defines the arc.
+     * 
+     * @param rect the arc's bounding rectangle.
+     * @param start the start angle of the arc in degrees.
+     * @param extent the angle witdth of the arc in degrees.
+     * @param type the closure type, either {@link Arc2D#OPEN}, 
+     * {@link Arc2D#CHORD}, or {@link Arc2D#PIE}.
+     */
+    public void setArc(Rectangle2D rect, double start, double extent, int type) {
+        setArc(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight(), start, extent, type);
+    }
+
+    /**
+     * Sets the data that defines the arc by copying it from another Arc2D.
+     * 
+     * @param arc the arc whose data is copied into this arc.
+     */
+    public void setArc(Arc2D arc) {
+        setArc(arc.getX(), arc.getY(), arc.getWidth(), arc.getHeight(), arc
+                .getAngleStart(), arc.getAngleExtent(), arc.getArcType());
+    }
+
+    /**
+     * Sets the data for a circular arc by giving its center and radius.
+     * 
+     * @param x the x coordinate of the center of the circle.
+     * @param y the y coordinate of the center of the circle.
+     * @param radius the radius of the circle.
+     * @param start the start angle of the arc in degrees.
+     * @param extent the angle witdth of the arc in degrees.
+     * @param type the closure type, either {@link Arc2D#OPEN}, 
+     * {@link Arc2D#CHORD}, or {@link Arc2D#PIE}.
+     */
+    public void setArcByCenter(double x, double y, double radius, double start, double extent, int type) {
+        setArc(x - radius, y - radius, radius * 2.0, radius * 2.0, start, extent, type);
+    }
+
+    /**
+     * Sets the arc data for a circular arc based on two tangent lines
+     * and the radius. The two tangent lines are the lines from p1 
+     * to p2 and from p2 to p3, which determine a unique circle 
+     * with the given radius. The start and end points of the arc 
+     * are the points where the circle touches the two lines, and 
+     * the arc itself is the shorter of the two circle segments 
+     * determined by the two points (in other words, it is the 
+     * piece of the circle that is closer to the lines' intersection 
+     * point p2 and forms a concave shape with the segments from p1 to p2 
+     * and from p2 to p3).
+     * 
+     * @param p1 a point which determines one of the two tanget lines (with p2).
+     * @param p2 the point of intersection of the two tangent lines.
+     * @param p3 a point which determines one of the two tanget lines (with p2).
+     * @param radius the radius of the circular arc.
+     */
+    public void setArcByTangent(Point2D p1, Point2D p2, Point2D p3, double radius) {
+        // Used simple geometric calculations of arc center, radius and angles by tangents
+        double a1 = -Math.atan2(p1.getY() - p2.getY(), p1.getX() - p2.getX());
+        double a2 = -Math.atan2(p3.getY() - p2.getY(), p3.getX() - p2.getX());
+        double am = (a1 + a2) / 2.0;
+        double ah = a1 - am;
+        double d = radius / Math.abs(Math.sin(ah));
+        double x = p2.getX() + d * Math.cos(am);
+        double y = p2.getY() - d * Math.sin(am);
+        ah = ah >= 0.0 ? Math.PI * 1.5 - ah : Math.PI * 0.5 - ah;
+        a1 = getNormAngle(Math.toDegrees(am - ah));
+        a2 = getNormAngle(Math.toDegrees(am + ah));
+        double delta = a2 - a1;
+        if (delta <= 0.0) {
+            delta += 360.0;
+        }
+        setArcByCenter(x, y, radius, a1, delta, type);
+    }
+
+    /**
+     * Sets a new start angle to be the angle given by the the vector 
+     * from the current center point to the specified point.
+     * 
+     * @param point the point that determines the new start angle.
+     */
+    public void setAngleStart(Point2D point) {
+        double angle = Math.atan2(point.getY() - getCenterY(), point.getX() - getCenterX());
+        setAngleStart(getNormAngle(-Math.toDegrees(angle)));
+    }
+
+    /**
+     * Sets the angles in terms of vectors from the current arc center 
+     * to the points (x1, y1) and (x2, y2). The start angle is given 
+     * by the vector from the current center to the point (x1, y1) and
+     * the end angle is given by the vector from the center to the point
+     * (x2, y2).
+     * 
+     * @param x1 the x coordinate of the point whose vector from the center
+     * point determines the new start angle of the arc.
+     * @param y1 the y coordinate of the point whose vector from the center
+     * point determines the new start angle of the arc.
+     * @param x2 the x coordinate of the point whose vector from the center
+     * point determines the new end angle of the arc.
+     * @param y2 the y coordinate of the point whose vector from the center
+     * point determines the new end angle of the arc.
+     */
+    public void setAngles(double x1, double y1, double x2, double y2) {
+        double cx = getCenterX();
+        double cy = getCenterY();
+        double a1 = getNormAngle(-Math.toDegrees(Math.atan2(y1 - cy, x1 - cx)));
+        double a2 = getNormAngle(-Math.toDegrees(Math.atan2(y2 - cy, x2 - cx)));
+        a2 -= a1;
+        if (a2 <= 0.0) {
+            a2 += 360.0;
+        }
+        setAngleStart(a1);
+        setAngleExtent(a2);
+    }
+
+    /**
+     * Sets the angles in terms of vectors from the current arc center 
+     * to the points p1 and p2. The start angle is given 
+     * by the vector from the current center to the point p1 and
+     * the end angle is given by the vector from the center to the point
+     * p2.
+     * 
+     * @param p1 the point whose vector from the center
+     * point determines the new start angle of the arc.
+     * @param p2 the point whose vector from the center
+     * point determines the new end angle of the arc.
+     */
+    public void setAngles(Point2D p1, Point2D p2) {
+        setAngles(p1.getX(), p1.getY(), p2.getX(), p2.getY());
+    }
+
+    /**
+     * Normalizes the angle by removing extra winding (past 360 degrees)
+     * and placing it in the positive degree range.
+     * 
+     * @param angle - the source angle in degrees
+     * 
+     * @return an angle between 0 and 360 degrees which corresponds
+     * to the same direction vector as the source angle.
+     */
+    double getNormAngle(double angle) {
+        double n = Math.floor(angle / 360.0);
+        return angle - n * 360.0;
+    }
+
+    /**
+     * Determines whether the given angle is contained in the span of the arc.
+     * 
+     * @param angle the angle to test in degrees.
+     * 
+     * @return true, if the given angle is between the start angle and 
+     * the end angle of the arc.
+     */
+    public boolean containsAngle(double angle) {
+        double extent = getAngleExtent();
+        if (extent >= 360.0) {
+            return true;
+        }
+        angle = getNormAngle(angle);
+        double a1 = getNormAngle(getAngleStart());
+        double a2 = a1 + extent;
+        if (a2 > 360.0) {
+            return angle >= a1 || angle <= a2 - 360.0;
+        }
+        if (a2 < 0.0) {
+            return angle >= a2 + 360.0 || angle <= a1;
+        }
+        return extent > 0.0 ? a1 <= angle && angle <= a2 : a2 <= angle
+                && angle <= a1;
+    }
+
+    public boolean contains(double px, double py) {
+        // Normalize point
+        double nx = (px - getX()) / getWidth() - 0.5;
+        double ny = (py - getY()) / getHeight() - 0.5;
+
+        if ((nx * nx + ny * ny) > 0.25) {
+            return false;
+        }
+
+        double extent = getAngleExtent();
+        double absExtent = Math.abs(extent);
+        if (absExtent >= 360.0) {
+            return true;
+        }
+
+        boolean containsAngle = containsAngle(Math.toDegrees(-Math
+                .atan2(ny, nx)));
+        if (type == PIE) {
+            return containsAngle;
+        }
+        if (absExtent <= 180.0 && !containsAngle) {
+            return false;
+        }
+
+        Line2D l = new Line2D.Double(getStartPoint(), getEndPoint());
+        int ccw1 = l.relativeCCW(px, py);
+        int ccw2 = l.relativeCCW(getCenterX(), getCenterY());
+        return ccw1 == 0 || ccw2 == 0
+                || ((ccw1 + ccw2) == 0 ^ absExtent > 180.0);
+    }
+
+    public boolean contains(double rx, double ry, double rw, double rh) {
+
+        if (!(contains(rx, ry) && contains(rx + rw, ry)
+                && contains(rx + rw, ry + rh) && contains(rx, ry + rh))) {
+            return false;
+        }
+
+        double absExtent = Math.abs(getAngleExtent());
+        if (type != PIE || absExtent <= 180.0 || absExtent >= 360.0) {
+            return true;
+        }
+
+        Rectangle2D r = new Rectangle2D.Double(rx, ry, rw, rh);
+
+        double cx = getCenterX();
+        double cy = getCenterY();
+        if (r.contains(cx, cy)) {
+            return false;
+        }
+
+        Point2D p1 = getStartPoint();
+        Point2D p2 = getEndPoint();
+
+        return !r.intersectsLine(cx, cy, p1.getX(), p1.getY())
+                && !r.intersectsLine(cx, cy, p2.getX(), p2.getY());
+    }
+
+    @Override
+    public boolean contains(Rectangle2D rect) {
+        return contains(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
+    }
+
+    public boolean intersects(double rx, double ry, double rw, double rh) {
+
+        if (isEmpty() || rw <= 0.0 || rh <= 0.0) {
+            return false;
+        }
+
+        // Check: Does arc contain rectangle's points
+        if (contains(rx, ry) || contains(rx + rw, ry) || contains(rx, ry + rh)
+                || contains(rx + rw, ry + rh)) {
+            return true;
+        }
+
+        double cx = getCenterX();
+        double cy = getCenterY();
+        Point2D p1 = getStartPoint();
+        Point2D p2 = getEndPoint();
+        Rectangle2D r = new Rectangle2D.Double(rx, ry, rw, rh);
+
+        // Check: Does rectangle contain arc's points
+        if (r.contains(p1) || r.contains(p2) || (type == PIE && r.contains(cx, cy))) {
+            return true;
+        }
+
+        if (type == PIE) {
+            if (r.intersectsLine(p1.getX(), p1.getY(), cx, cy) ||
+                r.intersectsLine(p2.getX(), p2.getY(), cx, cy))
+            {
+                return true;
+            }
+        } else {
+            if (r.intersectsLine(p1.getX(), p1.getY(), p2.getX(), p2.getY())) {
+                return true;
+            }
+        }
+
+        // Nearest rectangle point
+        double nx = cx < rx ? rx : (cx > rx + rw ? rx + rw : cx);
+        double ny = cy < ry ? ry : (cy > ry + rh ? ry + rh : cy);
+        return contains(nx, ny);
+    }
+
+    public PathIterator getPathIterator(AffineTransform at) {
+        return new Iterator(this, at);
+    }
+
+}
+
diff --git a/awt/java/awt/geom/Area.java b/awt/java/awt/geom/Area.java
new file mode 100644
index 0000000..bc27d4e
--- /dev/null
+++ b/awt/java/awt/geom/Area.java
@@ -0,0 +1,317 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Denis M. Kishenko
+ * @version $Revision$
+ */
+package java.awt.geom;
+
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Rectangle2D;
+import java.util.NoSuchElementException;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Class Area provides a minimal implementation for a generic shape.
+ */
+public class Area implements Shape, Cloneable {
+
+    /** The source Shape object. */
+    Shape s;
+
+    /**
+     * The Class NullIterator.
+     */
+    private static class NullIterator implements PathIterator {
+
+        /**
+         * Instantiates a new null iterator.
+         */
+        NullIterator() {
+        }
+
+        public int getWindingRule() {
+            return WIND_NON_ZERO;
+        }
+
+        public boolean isDone() {
+            return true;
+        }
+
+        public void next() {
+            // nothing
+        }
+
+        public int currentSegment(double[] coords) {
+            // awt.4B=Iterator out of bounds
+            throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
+        }
+
+        public int currentSegment(float[] coords) {
+            // awt.4B=Iterator out of bounds
+            throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
+        }
+
+    }
+
+    /**
+     * Instantiates a new area with no data.
+     */
+    public Area() {
+    }
+
+    /**
+     * Instantiates a new area with data given by the specified shape.
+     * 
+     * @param s the shape that gives the data for this Area
+     */
+    public Area(Shape s) {
+        if (s == null) {
+            throw new NullPointerException();
+        }
+        this.s = s;
+    }
+
+    public boolean contains(double x, double y) {
+        return s == null ? false : s.contains(x, y);
+    }
+
+    public boolean contains(double x, double y, double width, double height) {
+        return s == null ? false : s.contains(x, y, width, height);
+    }
+
+    public boolean contains(Point2D p) {
+        if (p == null) {
+            throw new NullPointerException();
+        }
+        return s == null ? false : s.contains(p);
+    }
+
+    public boolean contains(Rectangle2D r) {
+        if (r == null) {
+            throw new NullPointerException();
+        }
+        return s == null ? false : s.contains(r);
+    }
+
+    /**
+     * Tests whether the object is equal to this Area.
+     * 
+     * @param obj the object to compare
+     * 
+     * @return true, if successful
+     * 
+     * @throws NotImplementedException if this method is not implemented
+     */
+    public boolean equals(Area obj) throws org.apache.harmony.luni.util.NotImplementedException {
+        throw new RuntimeException("Not implemented"); //$NON-NLS-1$
+    }
+
+    public boolean intersects(double x, double y, double width, double height) {
+        return s == null ? false : s.intersects(x, y, width, height);
+    }
+
+    public boolean intersects(Rectangle2D r) {
+        if (r == null) {
+            throw new NullPointerException();
+        }
+        return s == null ? false : s.intersects(r);
+    }
+
+    public Rectangle getBounds() {
+        return s == null ? new Rectangle() : s.getBounds();
+    }
+
+    public Rectangle2D getBounds2D() {
+        return s == null ? new Rectangle2D.Double(): s.getBounds2D();
+    }
+
+    public PathIterator getPathIterator(AffineTransform t) {
+        return s == null ? new NullIterator() : s.getPathIterator(t);
+    }
+
+    public PathIterator getPathIterator(AffineTransform t, double flatness) {
+        return s == null ? new NullIterator() : s.getPathIterator(t, flatness);
+    }
+
+    /**
+     * Adds the specified area to this area.
+     * 
+     * @param area the area to add to this area
+     * 
+     * @throws NotImplementedException if this method is not implemented
+     */
+    public void add(Area area) throws org.apache.harmony.luni.util.NotImplementedException {
+        throw new RuntimeException("Not implemented"); //$NON-NLS-1$
+    }
+
+    /**
+     * Performs an exclusive or operation between this shape and the
+     * specified shape.
+     * 
+     * @param area the area to XOR against this area
+     * 
+     * @throws NotImplementedException if this method is not implemented
+     */
+    public void exclusiveOr(Area area) throws org.apache.harmony.luni.util.NotImplementedException {
+        throw new RuntimeException("Not implemented"); //$NON-NLS-1$
+    }
+
+    /**
+     * Extracts a Rectangle2D from the source shape if the underlying shape
+     * data describes a rectangle.
+     * 
+     * @return a Rectangle2D object if the source shape is rectangle, 
+     * or null if shape is empty or not rectangle.
+     */
+    Rectangle2D extractRectangle() {
+        if (s == null) {
+            return null;
+        }
+        float[] points = new float[12];
+        int count = 0;
+        PathIterator p = s.getPathIterator(null);
+        float[] coords = new float[6];
+        while(!p.isDone()) {
+            int type = p.currentSegment(coords);
+            if (count > 12 || type == PathIterator.SEG_QUADTO || type == PathIterator.SEG_CUBICTO) {
+                return null;
+            }
+            points[count++] = coords[0];
+            points[count++] = coords[1];
+            p.next();
+        }
+        if (points[0] == points[6] && points[6] == points[8] && points[2] == points[4] &&
+            points[1] == points[3] && points[3] == points[9] && points[5] == points[7])
+        {
+            return new Rectangle2D.Float(points[0], points[1], points[2] - points[0], points[7] - points[1]);
+        }
+        return null;
+    }
+    
+    /**
+     * Reduces the size of this Area by intersecting it with the 
+     * specified Area if they are both rectangles.
+     * 
+     * @see java.awt.geom.Rectangle2D#intersect(Rectangle2D, Rectangle2D, Rectangle2D)
+     * 
+     * @param area the area
+     */
+    public void intersect(Area area) {
+        Rectangle2D src1 = extractRectangle();
+        Rectangle2D src2 = area.extractRectangle();
+        if (src1 != null && src2 != null) {
+            Rectangle2D.intersect(src1, src2, (Rectangle2D)s);
+        }
+    }
+
+    /**
+     * Subtract the specified area from this area.
+     * 
+     * @param area the area to subtract
+     * 
+     * @throws NotImplementedException if this method is not implemented
+     */
+    public void subtract(Area area) throws org.apache.harmony.luni.util.NotImplementedException {
+        throw new RuntimeException("Not implemented"); //$NON-NLS-1$
+    }
+
+    /**
+     * Checks if this Area is empty.
+     * 
+     * @return true, if this Area is empty
+     * 
+     * @throws NotImplementedException if this method is not implemented
+     */
+    public boolean isEmpty() throws org.apache.harmony.luni.util.NotImplementedException {
+        throw new RuntimeException("Not implemented"); //$NON-NLS-1$
+    }
+
+    /**
+     * Checks if this Area is polygonal.
+     * 
+     * @return true, if this Area is polygonal
+     * 
+     * @throws NotImplementedException if this method is not implemented
+     */
+    public boolean isPolygonal() throws org.apache.harmony.luni.util.NotImplementedException {
+        throw new RuntimeException("Not implemented"); //$NON-NLS-1$
+    }
+
+    /**
+     * Checks if this Area is rectangular.
+     * 
+     * @return true, if this Area is rectangular
+     * 
+     * @throws NotImplementedException if this method is not implemented
+     */
+    public boolean isRectangular() throws org.apache.harmony.luni.util.NotImplementedException {
+        throw new RuntimeException("Not implemented"); //$NON-NLS-1$
+    }
+
+    /**
+     * Checks if this Area is singular.
+     * 
+     * @return true, if this Area is singular
+     * 
+     * @throws NotImplementedException if this method is not implemented
+     */
+    public boolean isSingular() throws org.apache.harmony.luni.util.NotImplementedException {
+        throw new RuntimeException("Not implemented"); //$NON-NLS-1$
+    }
+
+    /**
+     * Resets the data of this Area.
+     * 
+     * @throws NotImplementedException if this method is not implemented
+     */
+    public void reset() throws org.apache.harmony.luni.util.NotImplementedException {
+        throw new RuntimeException("Not implemented"); //$NON-NLS-1$
+    }
+
+    /**
+     * Transforms the data of this Area according to the specified 
+     * AffineTransform.
+     * 
+     * @param t the transform to use to transform the data
+     */
+    public void transform(AffineTransform t) {
+        s = t.createTransformedShape(s);
+    }
+
+    /**
+     * Creates a new Area that is the result of transforming the data 
+     * of this Area according to the specified AffineTransform.
+     * 
+     * @param t the transform to use to transform the data
+     * 
+     * @return the new Area that is the result of transforming the data 
+     * of this Area according to the specified AffineTransform.
+     */
+    public Area createTransformedArea(AffineTransform t) {
+        return s == null ? new Area() : new Area(t.createTransformedShape(s));
+    }
+
+    @Override
+    public Object clone() {
+        return new Area(this);
+    }
+
+}
diff --git a/awt/java/awt/geom/CubicCurve2D.java b/awt/java/awt/geom/CubicCurve2D.java
new file mode 100644
index 0000000..3e440c8
--- /dev/null
+++ b/awt/java/awt/geom/CubicCurve2D.java
@@ -0,0 +1,945 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Denis M. Kishenko
+ * @version $Revision$
+ */
+package java.awt.geom;
+
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.util.NoSuchElementException;
+
+import org.apache.harmony.awt.gl.Crossing;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Class CubicCurve2D is a Shape that represents a segment of a 
+ * quadratic (Bezier) curve. The curved segment is determined by four points:
+ * a start point, an end point, and two control points. 
+ * The control points give information about the tangent and next 
+ * derivative at the endpoints according to the standard theory of 
+ * Bezier curves. For more information on Bezier curves, 
+ * see <a href="http://en.wikipedia.org/wiki/B%C3%A9zier_curve">this article</a>.
+ */
+public abstract class CubicCurve2D implements Shape, Cloneable {
+
+    /**
+     * The Class Float is the subclass of CubicCurve2D that has all 
+     * of its data values stored with float-level precision.
+     */
+    public static class Float extends CubicCurve2D {
+
+        /** The x coordinate of the starting point. */
+        public float x1;
+        
+        /** The y coordinate of the starting point. */
+        public float y1;
+        
+        /** The x coordinate of the first control point. */
+        public float ctrlx1;
+        
+        /** The y coordinate of the first control point. */
+        public float ctrly1;
+        
+        /** The x coordinate of the second control point. */
+        public float ctrlx2;
+        
+        /** The y coordinate of the second control point. */
+        public float ctrly2;
+        
+        /** The x coordinate of the end point. */
+        public float x2;
+        
+        /** The y coordinate of the end point. */
+        public float y2;
+
+        /**
+         * Instantiates a new float-valued CubicCurve2D with all coordinate values
+         * set to zero.
+         */
+        public Float() {
+        }
+
+        /**
+         * Instantiates a new float-valued CubicCurve2D with the specified
+         * coordinate values.
+         * 
+         * @param x1 the x coordinate of the starting point
+         * @param y1 the y coordinate of the starting point
+         * @param ctrlx1 the x coordinate of the first control point
+         * @param ctrly1 the y coordinate of the first control point
+         * @param ctrlx2 the x coordinate of the second control point
+         * @param ctrly2 the y coordinate of the second control point
+         * @param x2 the x coordinate of the end point
+         * @param y2 the y coordinate of the end point
+         */
+        public Float(float x1, float y1, float ctrlx1, float ctrly1, float ctrlx2, float ctrly2, float x2, float y2) {
+            setCurve(x1, y1, ctrlx1, ctrly1, ctrlx2, ctrly2, x2, y2);
+        }
+
+        @Override
+        public double getX1() {
+            return x1;
+        }
+
+        @Override
+        public double getY1() {
+            return y1;
+        }
+
+        @Override
+        public double getCtrlX1() {
+            return ctrlx1;
+        }
+
+        @Override
+        public double getCtrlY1() {
+            return ctrly1;
+        }
+
+        @Override
+        public double getCtrlX2() {
+            return ctrlx2;
+        }
+
+        @Override
+        public double getCtrlY2() {
+            return ctrly2;
+        }
+
+        @Override
+        public double getX2() {
+            return x2;
+        }
+
+        @Override
+        public double getY2() {
+            return y2;
+        }
+
+        @Override
+        public Point2D getP1() {
+            return new Point2D.Float(x1, y1);
+        }
+
+        @Override
+        public Point2D getCtrlP1() {
+            return new Point2D.Float(ctrlx1, ctrly1);
+        }
+
+        @Override
+        public Point2D getCtrlP2() {
+            return new Point2D.Float(ctrlx2, ctrly2);
+        }
+
+        @Override
+        public Point2D getP2() {
+            return new Point2D.Float(x2, y2);
+        }
+
+        @Override
+        public void setCurve(double x1, double y1, double ctrlx1, double ctrly1,
+                double ctrlx2, double ctrly2, double x2, double y2)
+        {
+            this.x1 = (float)x1;
+            this.y1 = (float)y1;
+            this.ctrlx1 = (float)ctrlx1;
+            this.ctrly1 = (float)ctrly1;
+            this.ctrlx2 = (float)ctrlx2;
+            this.ctrly2 = (float)ctrly2;
+            this.x2 = (float)x2;
+            this.y2 = (float)y2;
+        }
+
+        /**
+         * Sets the data values of the curve.
+         * 
+         * @param x1 the x coordinate of the starting point
+         * @param y1 the y coordinate of the starting point
+         * @param ctrlx1 the x coordinate of the first control point
+         * @param ctrly1 the y coordinate of the first control point
+         * @param ctrlx2 the x coordinate of the second control point
+         * @param ctrly2 the y coordinate of the second control point
+         * @param x2 the x coordinate of the end point
+         * @param y2 the y coordinate of the end point
+         */
+        public void setCurve(float x1, float y1, float ctrlx1, float ctrly1,
+                float ctrlx2, float ctrly2, float x2, float y2)
+        {
+            this.x1 = x1;
+            this.y1 = y1;
+            this.ctrlx1 = ctrlx1;
+            this.ctrly1 = ctrly1;
+            this.ctrlx2 = ctrlx2;
+            this.ctrly2 = ctrly2;
+            this.x2 = x2;
+            this.y2 = y2;
+        }
+
+        public Rectangle2D getBounds2D() {
+            float rx1 = Math.min(Math.min(x1, x2), Math.min(ctrlx1, ctrlx2));
+            float ry1 = Math.min(Math.min(y1, y2), Math.min(ctrly1, ctrly2));
+            float rx2 = Math.max(Math.max(x1, x2), Math.max(ctrlx1, ctrlx2));
+            float ry2 = Math.max(Math.max(y1, y2), Math.max(ctrly1, ctrly2));
+            return new Rectangle2D.Float(rx1, ry1, rx2 - rx1, ry2 - ry1);
+        }
+    }
+
+    /**
+     * The Class Double is the subclass of CubicCurve2D that has all 
+     * of its data values stored with double-level precision.
+     */
+    public static class Double extends CubicCurve2D {
+
+        /** The x coordinate of the starting point. */
+        public double x1;
+        
+        /** The y coordinate of the starting point. */
+        public double y1;
+        
+        /** The x coordinate of the first control point. */
+        public double ctrlx1;
+        
+        /** The y coordinate of the first control point. */
+        public double ctrly1;
+        
+        /** The x coordinate of the second control point. */
+        public double ctrlx2;
+        
+        /** The y coordinate of the second control point. */
+        public double ctrly2;
+        
+        /** The x coordinate of the end point. */
+        public double x2;
+        
+        /** The y coordinate of the end point. */
+        public double y2;
+
+        /**
+         * Instantiates a new double-valued CubicCurve2D with all coordinate values
+         * set to zero.
+         */
+        public Double() {
+        }
+
+        /**
+         * Instantiates a new double-valued CubicCurve2D with the specified
+         * coordinate values.
+         * 
+         * @param x1 the x coordinate of the starting point
+         * @param y1 the y coordinate of the starting point
+         * @param ctrlx1 the x coordinate of the first control point
+         * @param ctrly1 the y coordinate of the first control point
+         * @param ctrlx2 the x coordinate of the second control point
+         * @param ctrly2 the y coordinate of the second control point
+         * @param x2 the x coordinate of the end point
+         * @param y2 the y coordinate of the end point
+         */
+        public Double(double x1, double y1, double ctrlx1, double ctrly1,
+                double ctrlx2, double ctrly2, double x2, double y2) {
+            setCurve(x1, y1, ctrlx1, ctrly1, ctrlx2, ctrly2, x2, y2);
+        }
+
+        @Override
+        public double getX1() {
+            return x1;
+        }
+
+        @Override
+        public double getY1() {
+            return y1;
+        }
+
+        @Override
+        public double getCtrlX1() {
+            return ctrlx1;
+        }
+
+        @Override
+        public double getCtrlY1() {
+            return ctrly1;
+        }
+
+        @Override
+        public double getCtrlX2() {
+            return ctrlx2;
+        }
+
+        @Override
+        public double getCtrlY2() {
+            return ctrly2;
+        }
+
+        @Override
+        public double getX2() {
+            return x2;
+        }
+
+        @Override
+        public double getY2() {
+            return y2;
+        }
+
+        @Override
+        public Point2D getP1() {
+            return new Point2D.Double(x1, y1);
+        }
+
+        @Override
+        public Point2D getCtrlP1() {
+            return new Point2D.Double(ctrlx1, ctrly1);
+        }
+
+        @Override
+        public Point2D getCtrlP2() {
+            return new Point2D.Double(ctrlx2, ctrly2);
+        }
+
+        @Override
+        public Point2D getP2() {
+            return new Point2D.Double(x2, y2);
+        }
+
+        @Override
+        public void setCurve(double x1, double y1, double ctrlx1, double ctrly1,
+                double ctrlx2, double ctrly2, double x2, double y2)
+        {
+            this.x1 = x1;
+            this.y1 = y1;
+            this.ctrlx1 = ctrlx1;
+            this.ctrly1 = ctrly1;
+            this.ctrlx2 = ctrlx2;
+            this.ctrly2 = ctrly2;
+            this.x2 = x2;
+            this.y2 = y2;
+        }
+
+        public Rectangle2D getBounds2D() {
+            double rx1 = Math.min(Math.min(x1, x2), Math.min(ctrlx1, ctrlx2));
+            double ry1 = Math.min(Math.min(y1, y2), Math.min(ctrly1, ctrly2));
+            double rx2 = Math.max(Math.max(x1, x2), Math.max(ctrlx1, ctrlx2));
+            double ry2 = Math.max(Math.max(y1, y2), Math.max(ctrly1, ctrly2));
+            return new Rectangle2D.Double(rx1, ry1, rx2 - rx1, ry2 - ry1);
+        }
+    }
+
+    /*
+     * CubicCurve2D path iterator 
+     */
+    /**
+     * The Iterator class for the Shape CubicCurve2D.
+     */
+    class Iterator implements PathIterator {
+
+        /** The source CubicCurve2D object. */
+        CubicCurve2D c;
+        
+        /** The path iterator transformation. */
+        AffineTransform t;
+        
+        /** The current segmenet index. */
+        int index;
+
+        /**
+         * Constructs a new CubicCurve2D.Iterator for given line and transformation
+         * 
+         * @param c - the source CubicCurve2D object
+         * @param t the t
+         */
+        Iterator(CubicCurve2D c, AffineTransform t) {
+            this.c = c;
+            this.t = t;
+        }
+
+        public int getWindingRule() {
+            return WIND_NON_ZERO;
+        }
+
+        public boolean isDone() {
+            return index > 1;
+        }
+
+        public void next() {
+            index++;
+        }
+
+        public int currentSegment(double[] coords) {
+            if (isDone()) {
+                throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
+            }
+            int type;
+            int count;
+            if (index == 0) {
+                type = SEG_MOVETO;
+                coords[0] = c.getX1();
+                coords[1] = c.getY1();
+                count = 1;
+            } else {
+                type = SEG_CUBICTO;
+                coords[0] = c.getCtrlX1();
+                coords[1] = c.getCtrlY1();
+                coords[2] = c.getCtrlX2();
+                coords[3] = c.getCtrlY2();
+                coords[4] = c.getX2();
+                coords[5] = c.getY2();
+                count = 3;
+            }
+            if (t != null) {
+                t.transform(coords, 0, coords, 0, count);
+            }
+            return type;
+        }
+
+        public int currentSegment(float[] coords) {
+            if (isDone()) {
+                throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
+            }
+            int type;
+            int count;
+            if (index == 0) {
+                type = SEG_MOVETO;
+                coords[0] = (float)c.getX1();
+                coords[1] = (float)c.getY1();
+                count = 1;
+            } else {
+                type = SEG_CUBICTO;
+                coords[0] = (float)c.getCtrlX1();
+                coords[1] = (float)c.getCtrlY1();
+                coords[2] = (float)c.getCtrlX2();
+                coords[3] = (float)c.getCtrlY2();
+                coords[4] = (float)c.getX2();
+                coords[5] = (float)c.getY2();
+                count = 3;
+            }
+            if (t != null) {
+                t.transform(coords, 0, coords, 0, count);
+            }
+            return type;
+        }
+
+    }
+
+    /**
+     * Instantiates a new 2-D cubic curve.
+     */
+    protected CubicCurve2D() {
+    }
+
+    /**
+     * Gets the x coordinate of the starting point.
+     * 
+     * @return the x coordinate of the starting point
+     */
+    public abstract double getX1();
+
+    /**
+     * Gets the y coordinate of the starting point.
+     * 
+     * @return the y coordinate of the starting point
+     */
+    public abstract double getY1();
+
+    /**
+     * Gets the starting point.
+     * 
+     * @return the starting point
+     */
+    public abstract Point2D getP1();
+
+    /**
+     * Gets the x coordinate of the first control point.
+     * 
+     * @return the x coordinate of the first control point
+     */
+    public abstract double getCtrlX1();
+
+    /**
+     * Gets the y coordinate of the first control point.
+     * 
+     * @return the y coordinate of the first control point
+     */
+    public abstract double getCtrlY1();
+
+    /**
+     * Gets the second control point.
+     * 
+     * @return the second control point
+     */
+    public abstract Point2D getCtrlP1();
+
+    /**
+     * Gets the x coordinate of the second control point.
+     * 
+     * @return the x coordinate of the second control point
+     */
+    public abstract double getCtrlX2();
+
+    /**
+     * Gets the y coordinate of the second control point.
+     * 
+     * @return the y coordinate of the second control point
+     */
+    public abstract double getCtrlY2();
+
+    /**
+     * Gets the second control point.
+     * 
+     * @return the second control point
+     */
+    public abstract Point2D getCtrlP2();
+
+    /**
+     * Gets the x coordinate of the end point.
+     * 
+     * @return the x coordinate of the end point
+     */
+    public abstract double getX2();
+
+    /**
+     * Gets the y coordinate of the end point.
+     * 
+     * @return the y coordinate of the end point
+     */
+    public abstract double getY2();
+
+    /**
+     * Gets the end point.
+     * 
+     * @return the end point
+     */
+    public abstract Point2D getP2();
+
+    /**
+     * Sets the data of the curve.
+     * 
+     * @param x1 the x coordinate of the starting point
+     * @param y1 the y coordinate of the starting point
+     * @param ctrlx1 the x coordinate of the first control point
+     * @param ctrly1 the y coordinate of the first control point
+     * @param ctrlx2 the x coordinate of the second control point
+     * @param ctrly2 the y coordinate of the second control point
+     * @param x2 the x coordinate of the end point
+     * @param y2 the y coordinate of the end point
+     */
+    public abstract void setCurve(double x1, double y1, double ctrlx1, double ctrly1,
+            double ctrlx2, double ctrly2, double x2, double y2);
+
+    /**
+     * Sets the data of the curve as point objects.
+     * 
+     * @param p1 the starting point
+     * @param cp1 the first control point
+     * @param cp2 the second control point
+     * @param p2 the end point
+     * 
+     * @throws NullPointerException if any of the points is null.
+     */
+    public void setCurve(Point2D p1, Point2D cp1, Point2D cp2, Point2D p2) {
+        setCurve(
+                p1.getX(), p1.getY(),
+                cp1.getX(), cp1.getY(),
+                cp2.getX(), cp2.getY(),
+                p2.getX(), p2.getY());
+    }
+
+    /**
+     * Sets the data of the curve by reading the data from an array
+     * of values. The values are read in the same order as the arguments
+     * of the method {@link CubicCurve2D#setCurve(double, double, double, double, double, double, double, double)}.
+     * 
+     * @param coords the array of values containing the new coordinates
+     * @param offset the offset of the data to read within the array
+     * 
+     * @throws ArrayIndexOutOfBoundsException if coords.length < offset + 8.
+     * @throws NullPointerException if the coordinate array is null.
+     */
+    public void setCurve(double[] coords, int offset) {
+        setCurve(
+                coords[offset + 0], coords[offset + 1],
+                coords[offset + 2], coords[offset + 3],
+                coords[offset + 4], coords[offset + 5],
+                coords[offset + 6], coords[offset + 7]);
+    }
+
+    /**
+     * Sets the data of the curve by reading the data from an array
+     * of points. The values are read in the same order as the arguments
+     * of the method {@link CubicCurve2D#setCurve(Point2D, Point2D, Point2D, Point2D)}
+     * 
+     * @param points the array of points containing the new coordinates
+     * @param offset the offset of the data to read within the array
+     * 
+     * @throws ArrayIndexOutOfBoundsException if points.length < offset + .
+     * @throws NullPointerException if the point array is null.
+     */
+    public void setCurve(Point2D[] points, int offset) {
+        setCurve(
+                points[offset + 0].getX(), points[offset + 0].getY(),
+                points[offset + 1].getX(), points[offset + 1].getY(),
+                points[offset + 2].getX(), points[offset + 2].getY(),
+                points[offset + 3].getX(), points[offset + 3].getY());
+    }
+
+    /**
+     * Sets the data of the curve by copying it from another CubicCurve2D.
+     * 
+     * @param curve the curve to copy the data points from
+     * 
+     * @throws NullPointerException if the curve is null.
+     */
+    public void setCurve(CubicCurve2D curve) {
+        setCurve(
+                curve.getX1(), curve.getY1(),
+                curve.getCtrlX1(), curve.getCtrlY1(),
+                curve.getCtrlX2(), curve.getCtrlY2(),
+                curve.getX2(), curve.getY2());
+    }
+
+    /**
+     * Gets the square of the flatness of this curve, where the flatness is the 
+     * maximum distance from the curves control points to the 
+     * line segment connecting the two points.
+     * 
+     * @return the square of the flatness
+     */
+    public double getFlatnessSq() {
+        return getFlatnessSq(
+                getX1(), getY1(),
+                getCtrlX1(), getCtrlY1(),
+                getCtrlX2(), getCtrlY2(),
+                getX2(), getY2());
+    }
+
+    /**
+     * Gets the square of the flatness of the cubic curve segment 
+     * defined by the specified values.
+     * 
+     * @param x1 the x coordinate of the starting point
+     * @param y1 the y coordinate of the starting point
+     * @param ctrlx1 the x coordinate of the first control point
+     * @param ctrly1 the y coordinate of the first control point
+     * @param ctrlx2 the x coordinate of the second control point
+     * @param ctrly2 the y coordinate of the second control point
+     * @param x2 the x coordinate of the end point
+     * @param y2 the y coordinate of the end point
+     * 
+     * @return the square of the flatness
+     */
+    public static double getFlatnessSq(double x1, double y1, double ctrlx1, double ctrly1,
+            double ctrlx2, double ctrly2, double x2, double y2)
+    {
+        return Math.max(
+                Line2D.ptSegDistSq(x1, y1, x2, y2, ctrlx1, ctrly1),
+                Line2D.ptSegDistSq(x1, y1, x2, y2, ctrlx2, ctrly2));
+    }
+
+    /**
+     * Gets the square of the flatness of the cubic curve segment 
+     * defined by the specified values. The values are read in the same order as the arguments
+     * of the method {@link CubicCurve2D#getFlatnessSq(double, double, double, double, double, double, double, double)}.
+     * 
+     * @param coords the array of points containing the new coordinates
+     * @param offset the offset of the data to read within the array
+     * 
+     * @return the square of the flatness
+     * 
+     * @throws ArrayIndexOutOfBoundsException if points.length < offset + .
+     * @throws NullPointerException if the point array is null.
+     */
+    public static double getFlatnessSq(double coords[], int offset) {
+        return getFlatnessSq(
+                coords[offset + 0], coords[offset + 1],
+                coords[offset + 2], coords[offset + 3],
+                coords[offset + 4], coords[offset + 5],
+                coords[offset + 6], coords[offset + 7]);
+    }
+
+    /**
+     * Gets the flatness of this curve, where the flatness is the 
+     * maximum distance from the curves control points to the 
+     * line segment connecting the two points.
+     * 
+     * @return the flatness of this curve
+     */
+    public double getFlatness() {
+        return getFlatness(
+                getX1(), getY1(),
+                getCtrlX1(), getCtrlY1(),
+                getCtrlX2(), getCtrlY2(),
+                getX2(), getY2());
+    }
+
+    /**
+     * Gets the flatness of the cubic curve segment 
+     * defined by the specified values.
+     * 
+     * @param x1 the x coordinate of the starting point
+     * @param y1 the y coordinate of the starting point
+     * @param ctrlx1 the x coordinate of the first control point
+     * @param ctrly1 the y coordinate of the first control point
+     * @param ctrlx2 the x coordinate of the second control point
+     * @param ctrly2 the y coordinate of the second control point
+     * @param x2 the x coordinate of the end point
+     * @param y2 the y coordinate of the end point
+     * 
+     * @return the flatness
+     */
+    public static double getFlatness(double x1, double y1, double ctrlx1, double ctrly1,
+            double ctrlx2, double ctrly2, double x2, double y2)
+    {
+        return Math.sqrt(getFlatnessSq(x1, y1, ctrlx1, ctrly1, ctrlx2, ctrly2, x2, y2));
+    }
+
+    /**
+     * Gets the flatness of the cubic curve segment 
+     * defined by the specified values. The values are read in the same order as the arguments
+     * of the method {@link CubicCurve2D#getFlatness(double, double, double, double, double, double, double, double)}.
+     * 
+     * @param coords the array of points containing the new coordinates
+     * @param offset the offset of the data to read within the array
+     * 
+     * @return the flatness
+     * 
+     * @throws ArrayIndexOutOfBoundsException if points.length < offset + .
+     * @throws NullPointerException if the point array is null.
+     */
+    public static double getFlatness(double coords[], int offset) {
+        return getFlatness(
+                coords[offset + 0], coords[offset + 1],
+                coords[offset + 2], coords[offset + 3],
+                coords[offset + 4], coords[offset + 5],
+                coords[offset + 6], coords[offset + 7]);
+    }
+
+    /**
+     * Creates the data for two cubic curves by dividing this
+     * curve in two. The division point is the point on the curve 
+     * that is closest to the average of curve's two control points. 
+     * The two new control points (nearest the new endpoint) are computed
+     * by averaging the original control points with the new endpoint.
+     * The data of this curve is left unchanged.
+     * 
+     * @param left the CubicCurve2D where the left (start) segment's 
+     * data is written
+     * @param right the CubicCurve2D where the right (end) segment's 
+     * data is written
+     * 
+     * @throws NullPointerException if either curve is null.
+     */
+    public void subdivide(CubicCurve2D left, CubicCurve2D right) {
+        subdivide(this, left, right);
+    }
+
+    /**
+     * Creates the data for two cubic curves by dividing the specified
+     * curve in two. The division point is the point on the curve 
+     * that is closest to the average of curve's two control points. 
+     * The two new control points (nearest the new endpoint) are computed
+     * by averaging the original control points with the new endpoint.
+     * The data of the source curve is left unchanged.
+     * 
+     * @param src the original curve to be divided in two
+     * @param left the CubicCurve2D where the left (start) segment's 
+     * data is written
+     * @param right the CubicCurve2D where the right (end) segment's 
+     * data is written
+     * 
+     * @throws NullPointerException if either curve is null.
+     */
+    public static void subdivide(CubicCurve2D src, CubicCurve2D left, CubicCurve2D right) {
+        double x1 = src.getX1();
+        double y1 = src.getY1();
+        double cx1 = src.getCtrlX1();
+        double cy1 = src.getCtrlY1();
+        double cx2 = src.getCtrlX2();
+        double cy2 = src.getCtrlY2();
+        double x2 = src.getX2();
+        double y2 = src.getY2();
+        double cx = (cx1 + cx2) / 2.0;
+        double cy = (cy1 + cy2) / 2.0;
+        cx1 = (x1 + cx1) / 2.0;
+        cy1 = (y1 + cy1) / 2.0;
+        cx2 = (x2 + cx2) / 2.0;
+        cy2 = (y2 + cy2) / 2.0;
+        double ax = (cx1 + cx) / 2.0;
+        double ay = (cy1 + cy) / 2.0;
+        double bx = (cx2 + cx) / 2.0;
+        double by = (cy2 + cy) / 2.0;
+        cx = (ax + bx) / 2.0;
+        cy = (ay + by) / 2.0;
+        if (left != null) {
+            left.setCurve(x1, y1, cx1, cy1, ax, ay, cx, cy);
+        }
+        if (right != null) {
+            right.setCurve(cx, cy, bx, by, cx2, cy2, x2, y2);
+        }
+    }
+
+    /**
+     * Creates the data for two cubic curves by dividing the specified
+     * curve in two. The division point is the point on the curve 
+     * that is closest to the average of curve's two control points. 
+     * The two new control points (nearest the new endpoint) are computed
+     * by averaging the original control points with the new endpoint.
+     * The data of the source curve is left unchanged. The data for the 
+     * three curves is read/written in the usual order: { x1, y1, 
+     * ctrlx1, ctrly1, ctrlx2, crtry2, x2, y3 }
+     * 
+     * @param src the array that gives the data values for the source curve
+     * @param srcOff the offset in the src array to read the values from
+     * @param left the array where the coordinates of the start curve should be written
+     * @param leftOff the offset in the left array to start writing the values
+     * @param right the array where the coordinates of the end curve should be written
+     * @param rightOff the offset in the right array to start writing the values
+     * 
+     * @throws ArrayIndexOutOfBoundsException if src.length < srcoff + 8
+     * or if left.length < leftOff + 8 or if right.length < rightOff + 8.
+     * @throws NullPointerException if one of the arrays is null.
+     */
+    public static void subdivide(double src[], int srcOff, double left[], int leftOff, double right[], int rightOff) {
+        double x1 = src[srcOff + 0];
+        double y1 = src[srcOff + 1];
+        double cx1 = src[srcOff + 2];
+        double cy1 = src[srcOff + 3];
+        double cx2 = src[srcOff + 4];
+        double cy2 = src[srcOff + 5];
+        double x2 = src[srcOff + 6];
+        double y2 = src[srcOff + 7];
+        double cx = (cx1 + cx2) / 2.0;
+        double cy = (cy1 + cy2) / 2.0;
+        cx1 = (x1 + cx1) / 2.0;
+        cy1 = (y1 + cy1) / 2.0;
+        cx2 = (x2 + cx2) / 2.0;
+        cy2 = (y2 + cy2) / 2.0;
+        double ax = (cx1 + cx) / 2.0;
+        double ay = (cy1 + cy) / 2.0;
+        double bx = (cx2 + cx) / 2.0;
+        double by = (cy2 + cy) / 2.0;
+        cx = (ax + bx) / 2.0;
+        cy = (ay + by) / 2.0;
+        if (left != null) {
+            left[leftOff + 0] = x1;
+            left[leftOff + 1] = y1;
+            left[leftOff + 2] = cx1;
+            left[leftOff + 3] = cy1;
+            left[leftOff + 4] = ax;
+            left[leftOff + 5] = ay;
+            left[leftOff + 6] = cx;
+            left[leftOff + 7] = cy;
+        }
+        if (right != null) {
+            right[rightOff + 0] = cx;
+            right[rightOff + 1] = cy;
+            right[rightOff + 2] = bx;
+            right[rightOff + 3] = by;
+            right[rightOff + 4] = cx2;
+            right[rightOff + 5] = cy2;
+            right[rightOff + 6] = x2;
+            right[rightOff + 7] = y2;
+        }
+    }
+
+    /**
+     * Finds the roots of the cubic polynomial. This is 
+     * accomplished by finding the (real) values of x that solve
+     * the following equation: eqn[3]*x*x*x + eqn[2]*x*x + eqn[1]*x + eqn[0] = 0.
+     * The solutions are written back into the array eqn starting
+     * from the index 0 in the array. The return value tells how 
+     * many array elements have been changed by this method call.
+     * 
+     * @param eqn an array containing the coefficients of the 
+     * cubic polynomial to solve.
+     * 
+     * @return the number of roots of the cubic polynomial
+     * 
+     * @throws ArrayIndexOutOfBoundsException if eqn.length < 4.
+     * @throws NullPointerException if the array is null.
+     */
+    public static int solveCubic(double eqn[]) {
+        return solveCubic(eqn, eqn);
+    }
+
+    /**
+     * Finds the roots of the cubic polynomial. This is 
+     * accomplished by finding the (real) values of x that solve
+     * the following equation: eqn[3]*x*x*x + eqn[2]*x*x + eqn[1]*x + eqn[0] = 0.
+     * The solutions are written into the array res starting
+     * from the index 0 in the array. The return value tells how 
+     * many array elements have been changed by this method call.
+     * 
+     * @param eqn an array containing the coefficients of the 
+     * cubic polynomial to solve.
+     * @param res the array that this method writes the results into
+     * 
+     * @return the number of roots of the cubic polynomial
+     * 
+     * @throws ArrayIndexOutOfBoundsException if eqn.length < 4 or 
+     * if res.length is less than the number of roots.
+     * @throws NullPointerException if either array is null.
+     */
+    public static int solveCubic(double eqn[], double res[]) {
+        return Crossing.solveCubic(eqn, res);
+    }
+
+    public boolean contains(double px, double py) {
+        return Crossing.isInsideEvenOdd(Crossing.crossShape(this, px, py));
+    }
+
+    public boolean contains(double rx, double ry, double rw, double rh) {
+        int cross = Crossing.intersectShape(this, rx, ry, rw, rh);
+        return cross != Crossing.CROSSING && Crossing.isInsideEvenOdd(cross);
+    }
+
+    public boolean intersects(double rx, double ry, double rw, double rh) {
+        int cross = Crossing.intersectShape(this, rx, ry, rw, rh);
+        return cross == Crossing.CROSSING || Crossing.isInsideEvenOdd(cross);
+    }
+
+    public boolean contains(Point2D p) {
+        return contains(p.getX(), p.getY());
+    }
+
+    public boolean intersects(Rectangle2D r) {
+        return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+    }
+
+    public boolean contains(Rectangle2D r) {
+        return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+    }
+
+    public Rectangle getBounds() {
+        return getBounds2D().getBounds();
+    }
+
+    public PathIterator getPathIterator(AffineTransform t) {
+        return new Iterator(this, t);
+    }
+
+    public PathIterator getPathIterator(AffineTransform at, double flatness) {
+        return new FlatteningPathIterator(getPathIterator(at), flatness);
+    }
+
+    @Override
+    public Object clone() {
+        try {
+            return super.clone();
+        } catch (CloneNotSupportedException e) {
+            throw new InternalError();
+        }
+    }
+}
\ No newline at end of file
diff --git a/awt/java/awt/geom/Dimension2D.java b/awt/java/awt/geom/Dimension2D.java
new file mode 100644
index 0000000..eef63e6
--- /dev/null
+++ b/awt/java/awt/geom/Dimension2D.java
@@ -0,0 +1,78 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Denis M. Kishenko
+ * @version $Revision$
+ */
+package java.awt.geom;
+
+/**
+ * The Class Dimension2D represents a size (width and height) of a 
+ * geometric object. It stores double-valued data in order to be compatible
+ * with high-precision geometric operations.
+ */
+public abstract class Dimension2D implements Cloneable {
+
+    /**
+     * Instantiates a new dimension 2d with no data.
+     */
+    protected Dimension2D() {
+    }
+
+    /**
+     * Gets the width.
+     * 
+     * @return the width
+     */
+    public abstract double getWidth();
+
+    /**
+     * Gets the height.
+     * 
+     * @return the height
+     */
+    public abstract double getHeight();
+
+    /**
+     * Sets the width and height.
+     * 
+     * @param width the width
+     * @param height the height
+     */
+    public abstract void setSize(double width, double height);
+
+    /**
+     * Sets the width and height based on the data of another 
+     * Dimension2D object.
+     * 
+     * @param d the Dimension2D object providing the data to copy 
+     * into this Dimension2D object
+     */
+    public void setSize(Dimension2D d) {
+        setSize(d.getWidth(), d.getHeight());
+    }
+
+    @Override
+    public Object clone() {
+        try {
+            return super.clone();
+        } catch (CloneNotSupportedException e) {
+            throw new InternalError();
+        }
+    }
+}
+
diff --git a/awt/java/awt/geom/Ellipse2D.java b/awt/java/awt/geom/Ellipse2D.java
new file mode 100644
index 0000000..33464af
--- /dev/null
+++ b/awt/java/awt/geom/Ellipse2D.java
@@ -0,0 +1,403 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Denis M. Kishenko
+ * @version $Revision$
+ */
+package java.awt.geom;
+
+import java.util.NoSuchElementException;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Class Ellipse2D describes an ellipse defined by a rectangular
+ * area in which it is inscribed.
+ */
+public abstract class Ellipse2D extends RectangularShape {
+
+    /**
+     * The Class Float is the subclass of Ellipse2D that has all 
+     * of its data values stored with float-level precision.
+     */
+    public static class Float extends Ellipse2D {
+
+        /** The x coordinate of the upper left corner of the ellipse's
+         * bounding rectangle. */
+        public float x;
+        
+        /** The y coordinate of the upper left corner of the ellipse's
+         * bounding rectangle. */
+        public float y;
+        
+        /** The width of the ellipse's bounding rectangle. */
+        public float width;
+        
+        /** The height of the ellipse's bounding rectangle. */
+        public float height;
+
+        /**
+         * Instantiates a new float-valued Ellipse2D.
+         */
+        public Float() {
+        }
+
+        /**
+         * Instantiates a new float-valued Ellipse2D with the specified data.
+         * 
+         * @param x the x coordinate of the upper left corner of the ellipse's
+         * bounding rectangle
+         * @param y the y coordinate of the upper left corner of the ellipse's
+         * bounding rectangle
+         * @param width the width of the ellipse's bounding rectangle
+         * @param height the height of the ellipse's bounding rectangle
+         */
+        public Float(float x, float y, float width, float height) {
+            setFrame(x, y, width, height);
+        }
+
+        @Override
+        public double getX() {
+            return x;
+        }
+
+        @Override
+        public double getY() {
+            return y;
+        }
+
+        @Override
+        public double getWidth() {
+            return width;
+        }
+
+        @Override
+        public double getHeight() {
+            return height;
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return width <= 0.0 || height <= 0.0;
+        }
+
+        /**
+         * Sets the data of the ellipse's bounding rectangle.
+         * 
+         * @param x the x coordinate of the upper left corner of the ellipse's
+         * bounding rectangle
+         * @param y the y coordinate of the upper left corner of the ellipse's
+         * bounding rectangle
+         * @param width the width of the ellipse's bounding rectangle
+         * @param height the height of the ellipse's bounding rectangle
+         */
+        public void setFrame(float x, float y, float width, float height) {
+            this.x = x;
+            this.y = y;
+            this.width = width;
+            this.height = height;
+        }
+
+        @Override
+        public void setFrame(double x, double y, double width, double height) {
+            this.x = (float)x;
+            this.y = (float)y;
+            this.width = (float)width;
+            this.height = (float)height;
+        }
+
+        public Rectangle2D getBounds2D() {
+            return new Rectangle2D.Float(x, y, width, height);
+        }
+    }
+
+    /**
+     * The Class Double is the subclass of Ellipse2D that has all 
+     * of its data values stored with double-level precision.
+     */
+    public static class Double extends Ellipse2D {
+
+        /** The x coordinate of the upper left corner of the ellipse's
+         * bounding rectangle. */
+        public double x;
+        
+        /** The y coordinate of the upper left corner of the ellipse's
+         * bounding rectangle. */
+        public double y;
+        
+        /** The width of the ellipse's bounding rectangle. */
+        public double width;
+        
+        /** The height of the ellipse's bounding rectangle. */
+        public double height;
+
+        /**
+         * Instantiates a new double-valued Ellipse2D.
+         */
+        public Double() {
+        }
+
+        /**
+         * Instantiates a new double-valued Ellipse2D with the specified
+         * data.
+         * 
+         * @param x the x coordinate of the upper left corner of the ellipse's
+         * bounding rectangle
+         * @param y the y coordinate of the upper left corner of the ellipse's
+         * bounding rectangle
+         * @param width the width of the ellipse's bounding rectangle
+         * @param height the height of the ellipse's bounding rectangle
+         */
+        public Double(double x, double y, double width, double height) {
+            setFrame(x, y, width, height);
+        }
+
+        @Override
+        public double getX() {
+            return x;
+        }
+
+        @Override
+        public double getY() {
+            return y;
+        }
+
+        @Override
+        public double getWidth() {
+            return width;
+        }
+
+        @Override
+        public double getHeight() {
+            return height;
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return width <= 0.0 || height <= 0.0;
+        }
+
+        @Override
+        public void setFrame(double x, double y, double width, double height) {
+            this.x = x;
+            this.y = y;
+            this.width = width;
+            this.height = height;
+        }
+
+        public Rectangle2D getBounds2D() {
+            return new Rectangle2D.Double(x, y, width, height);
+        }
+    }
+
+    /*
+     * Ellipse2D path iterator 
+     */
+    /**
+     * The subclass of PathIterator to traverse an Ellipse2D.
+     */
+    class Iterator implements PathIterator {
+
+        /*
+         * Ellipse is subdivided into four quarters by x and y axis. Each part approximated by
+         * cubic Bezier curve. Arc in first quarter is started in (a, 0) and finished in (0, b) points.
+         * Control points for cubic curve wiil be (a, 0), (a, m), (n, b) and (0, b) where n and m are
+         * calculated based on requirement Bezier curve in point 0.5 should lay on the arc.
+         */
+
+        /** The coefficient to calculate control points of Bezier curves. */
+        final double u = 2.0 / 3.0 * (Math.sqrt(2.0) - 1.0);
+
+        /** The points coordinates calculation table. */
+        final double points[][] = {
+                { 1.0, 0.5 + u, 0.5 + u, 1.0, 0.5, 1.0 },
+                { 0.5 - u, 1.0, 0.0, 0.5 + u, 0.0, 0.5 },
+                { 0.0, 0.5 - u, 0.5 - u, 0.0, 0.5, 0.0 },
+                { 0.5 + u, 0.0, 1.0, 0.5 - u, 1.0, 0.5 }
+        };
+
+        /** The x coordinate of left-upper corner of the ellipse bounds. */
+        double x;
+        
+        /** The y coordinate of left-upper corner of the ellipse bounds. */
+        double y;
+        
+        /** The width of the ellipse bounds. */
+        double width;
+        
+        /** The height of the ellipse bounds. */
+        double height;
+
+        /** The path iterator transformation. */
+        AffineTransform t;
+
+        /** The current segmenet index. */
+        int index;
+
+        /**
+         * Constructs a new Ellipse2D.Iterator for given ellipse and transformation
+         * 
+         * @param e - the source Ellipse2D object
+         * @param t the t
+         */
+        Iterator(Ellipse2D e, AffineTransform t) {
+            this.x = e.getX();
+            this.y = e.getY();
+            this.width = e.getWidth();
+            this.height = e.getHeight();
+            this.t = t;
+            if (width < 0.0 || height < 0.0) {
+                index = 6;
+            }
+        }
+
+        public int getWindingRule() {
+            return WIND_NON_ZERO;
+        }
+
+        public boolean isDone() {
+            return index > 5;
+        }
+
+        public void next() {
+            index++;
+        }
+
+        public int currentSegment(double[] coords) {
+            if (isDone()) {
+                // awt.4B=Iterator out of bounds
+                throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
+            }
+            if (index == 5) {
+                return SEG_CLOSE;
+            }
+            int type;
+            int count;
+            if (index == 0) {
+                type = SEG_MOVETO;
+                count = 1;
+                double p[] = points[3];
+                coords[0] = x + p[4] * width;
+                coords[1] = y + p[5] * height;
+            } else {
+                type = SEG_CUBICTO;
+                count = 3;
+                double p[] = points[index - 1];
+                int j = 0;
+                for (int i = 0; i < 3; i++) {
+                    coords[j] = x + p[j++] * width;
+                    coords[j] = y + p[j++] * height;
+                }
+            }
+            if (t != null) {
+                t.transform(coords, 0, coords, 0, count);
+            }
+            return type;
+        }
+
+        public int currentSegment(float[] coords) {
+            if (isDone()) {
+                // awt.4B=Iterator out of bounds
+                throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
+            }
+            if (index == 5) {
+                return SEG_CLOSE;
+            }
+            int type;
+            int count;
+            if (index == 0) {
+                type = SEG_MOVETO;
+                count = 1;
+                double p[] = points[3];
+                coords[0] = (float)(x + p[4] * width);
+                coords[1] = (float)(y + p[5] * height);
+            } else {
+                type = SEG_CUBICTO;
+                count = 3;
+                int j = 0;
+                double p[] = points[index - 1];
+                for (int i = 0; i < 3; i++) {
+                    coords[j] = (float)(x + p[j++] * width);
+                    coords[j] = (float)(y + p[j++] * height);
+                }
+            }
+            if (t != null) {
+                t.transform(coords, 0, coords, 0, count);
+            }
+            return type;
+        }
+
+    }
+
+    /**
+     * Instantiates a new Ellipse2D.
+     */
+    protected Ellipse2D() {
+    }
+
+    public boolean contains(double px, double py) {
+        if (isEmpty()) {
+            return false;
+        }
+
+        double a = (px - getX()) / getWidth() - 0.5;
+        double b = (py - getY()) / getHeight() - 0.5;
+
+        return a * a + b * b < 0.25;
+    }
+
+    public boolean intersects(double rx, double ry, double rw, double rh) {
+        if (isEmpty() || rw <= 0.0 || rh <= 0.0) {
+            return false;
+        }
+
+        double cx = getX() + getWidth() / 2.0;
+        double cy = getY() + getHeight() / 2.0;
+
+        double rx1 = rx;
+        double ry1 = ry;
+        double rx2 = rx + rw;
+        double ry2 = ry + rh;
+
+        double nx = cx < rx1 ? rx1 : (cx > rx2 ? rx2 : cx);
+        double ny = cy < ry1 ? ry1 : (cy > ry2 ? ry2 : cy);
+
+        return contains(nx, ny);
+    }
+
+    public boolean contains(double rx, double ry, double rw, double rh) {
+        if (isEmpty() || rw <= 0.0 || rh <= 0.0) {
+            return false;
+        }
+
+        double rx1 = rx;
+        double ry1 = ry;
+        double rx2 = rx + rw;
+        double ry2 = ry + rh;
+
+        return
+            contains(rx1, ry1) &&
+            contains(rx2, ry1) &&
+            contains(rx2, ry2) &&
+            contains(rx1, ry2);
+    }
+
+    public PathIterator getPathIterator(AffineTransform at) {
+        return new Iterator(this, at);
+    }
+}
+
diff --git a/awt/java/awt/geom/FlatteningPathIterator.java b/awt/java/awt/geom/FlatteningPathIterator.java
new file mode 100644
index 0000000..ca5c7c2
--- /dev/null
+++ b/awt/java/awt/geom/FlatteningPathIterator.java
@@ -0,0 +1,326 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Denis M. Kishenko
+ * @version $Revision$
+ */
+package java.awt.geom;
+
+import java.util.NoSuchElementException;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Class FlatteningPathIterator takes a PathIterator for traversing 
+ * a curved shape and flattens it by estimating the curve as a series 
+ * of line segments. The flattening factor indicates how far the 
+ * estimating line segments are allowed to be from the actual curve:
+ * the FlatteningPathIterator will keep dividing each curved segment 
+ * into smaller and smaller flat segments until either the segments 
+ * are withing the flattening factor of the curve or until the buffer
+ * limit is reached.
+ */
+public class FlatteningPathIterator implements PathIterator {
+
+    /** The default points buffer size. */
+    private static final int BUFFER_SIZE = 16;
+    
+    /** The default curve subdivision limit. */
+    private static final int BUFFER_LIMIT = 16;
+
+    /** The points buffer capacity. */
+    private static final int BUFFER_CAPACITY = 16;
+    
+    /** The type of current segment to be flat. */
+    int bufType;
+    
+    /** The curve subdivision limit. */
+    int bufLimit;
+    
+    /** The current points buffer size. */
+    int bufSize;
+    
+    /** The inner cursor position in points buffer. */
+    int bufIndex;
+    
+    /** The current subdivision count. */
+    int bufSubdiv;
+
+    /** The points buffer. */
+    double buf[];
+    
+    /** The indicator of empty points buffer. */
+    boolean bufEmpty = true;
+    
+    /** The source PathIterator. */
+    PathIterator p;
+    
+    /** The flatness of new path. */
+    double flatness;
+    
+    /** The square of flatness. */
+    double flatness2;
+    
+    /** The x coordinate of previous path segment. */
+    double px;
+
+    /** The y coordinate of previous path segment. */
+    double py;
+    
+    /** The tamporary buffer for getting points from PathIterator. */
+    double coords[] = new double[6];
+
+    /**
+     * Instantiates a new flattening path iterator given the path 
+     * iterator for a (possibly) curved path and a flattening factor
+     * which indicates how close together the points on the curve 
+     * should be chosen. The buffer limit defaults to 16 which means 
+     * that each curve will be divided into no more than 16 segments 
+     * regardless of the flattening factor.
+     * 
+     * @param path the path iterator of the original curve
+     * @param flatness the flattening factor that indicates how far the 
+     * flat path is allowed to be from the actual curve in order to 
+     * decide when to stop dividing the path into smaller and smaller
+     * segments.
+     * 
+     * @throws IllegalArgumentException if the flatness is less than zero.
+     * @throws NullPointerException if the path is null.
+     */
+    public FlatteningPathIterator(PathIterator path, double flatness) {
+        this(path, flatness, BUFFER_LIMIT);
+    }
+
+    /**
+     * Instantiates a new flattening path iterator given the path 
+     * iterator for a (possibly) curved path and a flattening factor
+     * and a buffer limit. The FlatteningPathIterator will keep 
+     * dividing each curved segment into smaller and smaller flat segments 
+     * until either the segments are withing the flattening factor of the 
+     * curve or until the buffer limit is reached.
+     * 
+     * @param path the path iterator of the original curve
+     * @param flatness the flattening factor that indicates how far the 
+     * flat path is allowed to be from the actual curve in order to 
+     * decide when to stop dividing the path into smaller and smaller
+     * segments.
+     * @param limit the maximum number of flat segments to divide each 
+     * curve into
+     * 
+     * @throws IllegalArgumentException if the flatness or limit is less than zero.
+     * @throws NullPointerException if the path is null.
+     */
+    public FlatteningPathIterator(PathIterator path, double flatness, int limit) {
+        if (flatness < 0.0) {
+            // awt.206=Flatness is less then zero
+            throw new IllegalArgumentException(Messages.getString("awt.206")); //$NON-NLS-1$
+        }
+        if (limit < 0) {
+            // awt.207=Limit is less then zero
+            throw new IllegalArgumentException(Messages.getString("awt.207")); //$NON-NLS-1$
+        }
+        if (path == null) {
+            // awt.208=Path is null
+            throw new NullPointerException(Messages.getString("awt.208")); //$NON-NLS-1$
+        }
+        this.p = path;
+        this.flatness = flatness;
+        this.flatness2 = flatness * flatness;
+        this.bufLimit = limit;
+        this.bufSize = Math.min(bufLimit, BUFFER_SIZE);
+        this.buf = new double[bufSize];
+        this.bufIndex = bufSize;
+    }
+
+    /**
+     * Gets the flattening factor.
+     * 
+     * @return the flattening factor
+     */
+    public double getFlatness() {
+        return flatness;
+    }
+
+    /**
+     * Gets the maximum number of subdivisions per curved segment.
+     * 
+     * @return the maximum number of subdivisions per curved segment
+     */
+    public int getRecursionLimit() {
+        return bufLimit;
+    }
+
+    public int getWindingRule() {
+        return p.getWindingRule();
+    }
+
+    public boolean isDone() {
+        return bufEmpty && p.isDone();
+    }
+
+    /**
+     * Calculates flat path points for current segment of the source shape.
+     * 
+     * Line segment is flat by itself. Flatness of quad and cubic curves evaluated by getFlatnessSq() method.
+     * Curves subdivided until current flatness is bigger than user defined and subdivision limit isn't exhausted.
+     * Single source segment translated to series of buffer points. The less flatness the bigger serries.
+     * Every currentSegment() call extract one point from the buffer. When series completed evaluate() takes next source shape segment.
+     */
+    void evaluate() {
+        if (bufEmpty) {
+            bufType = p.currentSegment(coords);
+        }
+
+        switch (bufType) {
+        case SEG_MOVETO:
+        case SEG_LINETO:
+            px = coords[0];
+            py = coords[1];
+            break;
+        case SEG_QUADTO:
+            if (bufEmpty) {
+                bufIndex -= 6;
+                buf[bufIndex + 0] = px;
+                buf[bufIndex + 1] = py;
+                System.arraycopy(coords, 0, buf, bufIndex + 2, 4);
+                bufSubdiv = 0;
+            }
+
+            while (bufSubdiv < bufLimit) {
+                if (QuadCurve2D.getFlatnessSq(buf, bufIndex) < flatness2) {
+                    break;
+                }
+
+                // Realloc buffer
+                if (bufIndex <= 4) {
+                    double tmp[] = new double[bufSize + BUFFER_CAPACITY];
+                    System.arraycopy(
+                            buf, bufIndex,
+                            tmp, bufIndex + BUFFER_CAPACITY,
+                            bufSize - bufIndex);
+                    buf = tmp;
+                    bufSize += BUFFER_CAPACITY;
+                    bufIndex += BUFFER_CAPACITY;
+                }
+
+                QuadCurve2D.subdivide(buf, bufIndex, buf, bufIndex - 4, buf, bufIndex);
+
+                bufIndex -= 4;
+                bufSubdiv++;
+            }
+
+            bufIndex += 4;
+            px = buf[bufIndex];
+            py = buf[bufIndex + 1];
+
+            bufEmpty = (bufIndex == bufSize - 2);
+            if (bufEmpty) {
+                bufIndex = bufSize;
+                bufType = SEG_LINETO;
+            } else {
+                bufSubdiv--;
+            }
+            break;
+        case SEG_CUBICTO:
+            if (bufEmpty) {
+                bufIndex -= 8;
+                buf[bufIndex + 0] = px;
+                buf[bufIndex + 1] = py;
+                System.arraycopy(coords, 0, buf, bufIndex + 2, 6);
+                bufSubdiv = 0;
+            }
+
+            while (bufSubdiv < bufLimit) {
+                if (CubicCurve2D.getFlatnessSq(buf, bufIndex) < flatness2) {
+                    break;
+                }
+
+                // Realloc buffer
+                if (bufIndex <= 6) {
+                    double tmp[] = new double[bufSize + BUFFER_CAPACITY];
+                    System.arraycopy(
+                            buf, bufIndex,
+                            tmp, bufIndex + BUFFER_CAPACITY,
+                            bufSize - bufIndex);
+                    buf = tmp;
+                    bufSize += BUFFER_CAPACITY;
+                    bufIndex += BUFFER_CAPACITY;
+                }
+
+                CubicCurve2D.subdivide(buf, bufIndex, buf, bufIndex - 6, buf, bufIndex);
+
+                bufIndex -= 6;
+                bufSubdiv++;
+            }
+
+            bufIndex += 6;
+            px = buf[bufIndex];
+            py = buf[bufIndex + 1];
+
+            bufEmpty = (bufIndex == bufSize - 2);
+            if (bufEmpty) {
+                bufIndex = bufSize;
+                bufType = SEG_LINETO;
+            } else {
+                bufSubdiv--;
+            }
+            break;
+        }
+
+    }
+
+    public void next() {
+        if (bufEmpty) {
+            p.next();
+        }
+    }
+
+    public int currentSegment(float[] coords) {
+        if (isDone()) {
+            // awt.4B=Iterator out of bounds
+            throw new NoSuchElementException(Messages.getString("awt.4Bx")); //$NON-NLS-1$
+        }
+        evaluate();
+        int type = bufType;
+        if (type != SEG_CLOSE) {
+            coords[0] = (float)px;
+            coords[1] = (float)py;
+            if (type != SEG_MOVETO) {
+                type = SEG_LINETO;
+            }
+        }
+        return type;
+    }
+
+    public int currentSegment(double[] coords) {
+        if (isDone()) {
+            // awt.4B=Iterator out of bounds
+            throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
+        }
+        evaluate();
+        int type = bufType;
+        if (type != SEG_CLOSE) {
+            coords[0] = px;
+            coords[1] = py;
+            if (type != SEG_MOVETO) {
+                type = SEG_LINETO;
+            }
+        }
+        return type;
+    }
+}
+
diff --git a/awt/java/awt/geom/GeneralPath.java b/awt/java/awt/geom/GeneralPath.java
new file mode 100644
index 0000000..36b01c4
--- /dev/null
+++ b/awt/java/awt/geom/GeneralPath.java
@@ -0,0 +1,566 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Denis M. Kishenko
+ * @version $Revision$
+ */
+package java.awt.geom;
+
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.util.NoSuchElementException;
+
+import org.apache.harmony.awt.gl.Crossing;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Class GeneralPath represents a shape whose outline is given 
+ * by different types of curved and straight segments.
+ */
+public final class GeneralPath implements Shape, Cloneable {
+
+    /** The Constant WIND_EVEN_ODD see {@link PathIterator#WIND_EVEN_ODD}. */
+    public static final int WIND_EVEN_ODD = PathIterator.WIND_EVEN_ODD;
+    
+    /** The Constant WIND_NON_ZERO see {@link PathIterator#WIND_NON_ZERO}. */
+    public static final int WIND_NON_ZERO = PathIterator.WIND_NON_ZERO;
+
+    /** The buffers size. */
+    private static final int BUFFER_SIZE = 10;
+    
+    /** The buffers capacity. */
+    private static final int BUFFER_CAPACITY = 10;
+
+    /** The point's types buffer. */
+    byte[] types;
+    
+    /** The points buffer. */
+    float[] points;
+    
+    /** The point's type buffer size. */
+    int typeSize;
+    
+    /** The points buffer size. */
+    int pointSize;
+    
+    /** The path rule. */
+    int rule;
+
+    /** The space amount in points buffer for different segmenet's types. */
+    static int pointShift[] = {
+            2,  // MOVETO
+            2,  // LINETO
+            4,  // QUADTO
+            6,  // CUBICTO
+            0}; // CLOSE
+
+    /*
+     * GeneralPath path iterator 
+     */
+    /**
+     * The Class Iterator is the subclass of Iterator for traversing the 
+     * outline of a GeneralPath.
+     */
+    class Iterator implements PathIterator {
+
+        /** The current cursor position in types buffer. */
+        int typeIndex;
+        
+        /** The current cursor position in points buffer. */
+        int pointIndex;
+        
+        /** The source GeneralPath object. */
+        GeneralPath p;
+        
+        /** The path iterator transformation. */
+        AffineTransform t;
+
+        /**
+         * Constructs a new GeneralPath.Iterator for given general path
+         * 
+         * @param path - the source GeneralPath object
+         */
+        Iterator(GeneralPath path) {
+            this(path, null);
+        }
+
+        /**
+         * Constructs a new GeneralPath.Iterator for given general path and transformation
+         * 
+         * @param path - the source GeneralPath object
+         * @param at - the AffineTransform object to apply rectangle path
+         */
+        Iterator(GeneralPath path, AffineTransform at) {
+            this.p = path;
+            this.t = at;
+        }
+
+        public int getWindingRule() {
+            return p.getWindingRule();
+        }
+
+        public boolean isDone() {
+            return typeIndex >= p.typeSize;
+        }
+
+        public void next() {
+            typeIndex++;
+        }
+
+        public int currentSegment(double[] coords) {
+            if (isDone()) {
+                // awt.4B=Iterator out of bounds
+                throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
+            }
+            int type = p.types[typeIndex];
+            int count = GeneralPath.pointShift[type];
+            for (int i = 0; i < count; i++) {
+                coords[i] = p.points[pointIndex + i];
+            }
+            if (t != null) {
+                t.transform(coords, 0, coords, 0, count / 2);
+            }
+            pointIndex += count;
+            return type;
+        }
+
+        public int currentSegment(float[] coords) {
+            if (isDone()) {
+                // awt.4B=Iterator out of bounds
+                throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
+            }
+            int type = p.types[typeIndex];
+            int count = GeneralPath.pointShift[type];
+            System.arraycopy(p.points, pointIndex, coords, 0, count);
+            if (t != null) {
+                t.transform(coords, 0, coords, 0, count / 2);
+            }
+            pointIndex += count;
+            return type;
+        }
+
+    }
+
+    /**
+     * Instantiates a new general path with the winding rule set 
+     * to {@link PathIterator#WIND_NON_ZERO} and the initial capacity
+     * (number of segments) set to the default value 10.
+     */
+    public GeneralPath() {
+        this(WIND_NON_ZERO, BUFFER_SIZE);
+    }
+
+    /**
+     * Instantiates a new general path with the given winding rule
+     *  and the initial capacity (number of segments) set to the 
+     *  default value 10.
+     * 
+     * @param rule the winding rule, either {@link PathIterator#WIND_EVEN_ODD}
+     * or {@link PathIterator#WIND_NON_ZERO}
+     */
+    public GeneralPath(int rule) {
+        this(rule, BUFFER_SIZE);
+    }
+
+    /**
+     * Instantiates a new general path with the given winding rule
+     * and initial capacity (number of segments).
+     * 
+     * @param rule the winding rule, either {@link PathIterator#WIND_EVEN_ODD}
+     * or {@link PathIterator#WIND_NON_ZERO}
+     * @param initialCapacity the number of segments the path is set to hold
+     */
+    public GeneralPath(int rule, int initialCapacity) {
+        setWindingRule(rule);
+        types = new byte[initialCapacity];
+        points = new float[initialCapacity * 2];
+    }
+
+    /**
+     * Creates a new GeneralPath from the outline of the given shape.
+     * 
+     * @param shape the shape
+     */
+    public GeneralPath(Shape shape) {
+        this(WIND_NON_ZERO, BUFFER_SIZE);
+        PathIterator p = shape.getPathIterator(null);
+        setWindingRule(p.getWindingRule());
+        append(p, false);
+    }
+
+    /**
+     * Sets the winding rule, which determines how to decide whether 
+     * a point that isn't on the path itself is inside or outside of 
+     * the shape.
+     * 
+     * @param rule the new winding rule
+     * 
+     * @throws IllegalArgumentException if the winding rule is neither
+     * {@link PathIterator#WIND_EVEN_ODD} nor {@link PathIterator#WIND_NON_ZERO}.
+     */
+    public void setWindingRule(int rule) {
+        if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO) {
+            // awt.209=Invalid winding rule value
+            throw new java.lang.IllegalArgumentException(Messages.getString("awt.209")); //$NON-NLS-1$
+        }
+        this.rule = rule;
+    }
+
+    /**
+     * Gets the winding rule.
+     * 
+     * @return the winding rule, either {@link PathIterator#WIND_EVEN_ODD}
+     * or {@link PathIterator#WIND_NON_ZERO}
+     */
+    public int getWindingRule() {
+        return rule;
+    }
+
+    /**
+     * Checks the point data buffer sizes to see whether pointCount additional
+     * point-data elements can fit. (Note that the number of point data 
+     * elements to add is more than one per point -- it depends on the type 
+     * of point being added.) Reallocates the buffers to enlarge the size if necessary.
+     * 
+     * @param pointCount - the number of point data elements to be added
+     * @param checkMove whether to check for existing points
+     * 
+     * @throws IllegalPathStateException checkMove is true and the 
+     * path is currently empty.
+     */
+    void checkBuf(int pointCount, boolean checkMove) {
+        if (checkMove && typeSize == 0) {
+            // awt.20A=First segment should be SEG_MOVETO type
+            throw new IllegalPathStateException(Messages.getString("awt.20A")); //$NON-NLS-1$
+        }
+        if (typeSize == types.length) {
+            byte tmp[] = new byte[typeSize + BUFFER_CAPACITY];
+            System.arraycopy(types, 0, tmp, 0, typeSize);
+            types = tmp;
+        }
+        if (pointSize + pointCount > points.length) {
+            float tmp[] = new float[pointSize + Math.max(BUFFER_CAPACITY * 2, pointCount)];
+            System.arraycopy(points, 0, tmp, 0, pointSize);
+            points = tmp;
+        }
+    }
+
+    /**
+     * Appends a new point to the end of this general path, disconnected
+     * from the existing path.
+     * 
+     * @param x the x coordinate of the next point to append
+     * @param y the y coordinate of the next point to append
+     */
+    public void moveTo(float x, float y) {
+        if (typeSize > 0 && types[typeSize - 1] == PathIterator.SEG_MOVETO) {
+            points[pointSize - 2] = x;
+            points[pointSize - 1] = y;
+        } else {
+            checkBuf(2, false);
+            types[typeSize++] = PathIterator.SEG_MOVETO;
+            points[pointSize++] = x;
+            points[pointSize++] = y;
+        }
+    }
+
+    /**
+     * Appends a new segment to the end of this general path by making 
+     * a straight line segment from the current endpoint to the 
+     * given new point.
+     * 
+     * @param x the x coordinate of the next point to append
+     * @param y the y coordinate of the next point to append
+     */
+    public void lineTo(float x, float y) {
+        checkBuf(2, true);
+        types[typeSize++] = PathIterator.SEG_LINETO;
+        points[pointSize++] = x;
+        points[pointSize++] = y;
+    }
+
+    /**
+     * Appends a new segment to the end of this general path by making 
+     * a quadratic curve from the current endpoint to the point (x2, y2)
+     * using the point (x1, y1) as the quadratic curve's control point.
+     * 
+     * @param x1 the x coordinate of the quadratic curve's control point
+     * @param y1 the y coordinate of the quadratic curve's control point
+     * @param x2 the x coordinate of the quadratic curve's end point
+     * @param y2 the y coordinate of the quadratic curve's end point
+     */
+    public void quadTo(float x1, float y1, float x2, float y2) {
+        checkBuf(4, true);
+        types[typeSize++] = PathIterator.SEG_QUADTO;
+        points[pointSize++] = x1;
+        points[pointSize++] = y1;
+        points[pointSize++] = x2;
+        points[pointSize++] = y2;
+    }
+
+    /**
+     * Appends a new segment to the end of this general path by making 
+     * a cubic curve from the current endpoint to the point (x3, y3)
+     * using (x1, y1) and (x2, y2) as control points.
+     * 
+     * @see java.awt.geom.CubicCurve2D
+     * 
+     * @param x1 the x coordinate of the new cubic segment's first control point
+     * @param y1 the y coordinate of the new cubic segment's first control point
+     * @param x2 the x coordinate of the new cubic segment's second control point
+     * @param y2 the y coordinate of the new cubic segment's second control point
+     * @param x3 the x coordinate of the new cubic segment's end point
+     * @param y3 the y coordinate of the new cubic segment's end point
+     */
+    public void curveTo(float x1, float y1, float x2, float y2, float x3, float y3) {
+        checkBuf(6, true);
+        types[typeSize++] = PathIterator.SEG_CUBICTO;
+        points[pointSize++] = x1;
+        points[pointSize++] = y1;
+        points[pointSize++] = x2;
+        points[pointSize++] = y2;
+        points[pointSize++] = x3;
+        points[pointSize++] = y3;
+    }
+
+    /**
+     * Appends the type information to declare that the current
+     * endpoint closes the curve.
+     */
+    public void closePath() {
+        if (typeSize == 0 || types[typeSize - 1] != PathIterator.SEG_CLOSE) {
+            checkBuf(0, true);
+            types[typeSize++] = PathIterator.SEG_CLOSE;
+        }
+    }
+
+    /**
+     * Appends the outline of the specified shape onto the end 
+     * of this GeneralPath.
+     * 
+     * @param shape the shape whose outline is to be appended
+     * @param connect true to connect this path's current 
+     * endpoint to the first point of the shape's outline or 
+     * false to append the shape's outline without connecting it
+     * 
+     * @throws NullPointerException if the shape parameter is null
+     */
+    public void append(Shape shape, boolean connect) {
+        PathIterator p = shape.getPathIterator(null);
+        append(p, connect);
+    }
+
+    /**
+     * Appends the path defined by the specified PathIterator onto the end 
+     * of this GeneralPath.
+     * 
+     * @param path the PathIterator that defines the new path to append
+     * @param connect true to connect this path's current 
+     * endpoint to the first point of the shape's outline or 
+     * false to append the shape's outline without connecting it
+     */
+    public void append(PathIterator path, boolean connect) {
+        while (!path.isDone()) {
+            float coords[] = new float[6];
+            switch (path.currentSegment(coords)) {
+            case PathIterator.SEG_MOVETO:
+                if (!connect || typeSize == 0) {
+                    moveTo(coords[0], coords[1]);
+                    break;
+                }
+                if (types[typeSize - 1] != PathIterator.SEG_CLOSE &&
+                    points[pointSize - 2] == coords[0] &&
+                    points[pointSize - 1] == coords[1])
+                {
+                    break;
+                }
+            // NO BREAK;
+            case PathIterator.SEG_LINETO:
+                lineTo(coords[0], coords[1]);
+                break;
+            case PathIterator.SEG_QUADTO:
+                quadTo(coords[0], coords[1], coords[2], coords[3]);
+                break;
+            case PathIterator.SEG_CUBICTO:
+                curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]);
+                break;
+            case PathIterator.SEG_CLOSE:
+                closePath();
+                break;
+            }
+            path.next();
+            connect = false;
+        }
+    }
+
+    /**
+     * Gets the current end point of the path.
+     * 
+     * @return the current end point of the path
+     */
+    public Point2D getCurrentPoint() {
+        if (typeSize == 0) {
+            return null;
+        }
+        int j = pointSize - 2;
+        if (types[typeSize - 1] == PathIterator.SEG_CLOSE) {
+
+            for (int i = typeSize - 2; i > 0; i--) {
+                int type = types[i];
+                if (type == PathIterator.SEG_MOVETO) {
+                    break;
+                }
+                j -= pointShift[type];
+            }
+        }
+        return new Point2D.Float(points[j], points[j + 1]);
+    }
+
+    /**
+     * Resets the GeneralPath to being an empty path. The underlying
+     * point and segment data is not deleted but rather the end indices
+     * of the data arrays are set to zero.
+     */
+    public void reset() {
+        typeSize = 0;
+        pointSize = 0;
+    }
+
+    /**
+     * Transform all of the coordinates of this path according to the
+     * specified AffineTransform.
+     * 
+     * @param t the AffineTransform
+     */
+    public void transform(AffineTransform t) {
+        t.transform(points, 0, points, 0, pointSize / 2);
+    }
+
+    /**
+     * Creates a new GeneralPath whose data is given by this path's 
+     * data transformed according to the specified AffineTransform.
+     * 
+     * @param t the AffineTransform
+     * 
+     * @return the new GeneralPath whose data is given by this path's 
+     * data transformed according to the specified AffineTransform
+     */
+    public Shape createTransformedShape(AffineTransform t) {
+        GeneralPath p = (GeneralPath)clone();
+        if (t != null) {
+            p.transform(t);
+        }
+        return p;
+    }
+
+    public Rectangle2D getBounds2D() {
+        float rx1, ry1, rx2, ry2;
+        if (pointSize == 0) {
+            rx1 = ry1 = rx2 = ry2 = 0.0f;
+        } else {
+            int i = pointSize - 1;
+            ry1 = ry2 = points[i--];
+            rx1 = rx2 = points[i--];
+            while (i > 0) {
+                float y = points[i--];
+                float x = points[i--];
+                if (x < rx1) {
+                    rx1 = x;
+                } else
+                    if (x > rx2) {
+                        rx2 = x;
+                    }
+                if (y < ry1) {
+                    ry1 = y;
+                } else
+                    if (y > ry2) {
+                        ry2 = y;
+                    }
+            }
+        }
+        return new Rectangle2D.Float(rx1, ry1, rx2 - rx1, ry2 - ry1);
+    }
+
+    public Rectangle getBounds() {
+        return getBounds2D().getBounds();
+    }
+
+    /**
+     * Checks the cross count (number of times a ray from the point 
+     * crosses the shape's boundary) to determine whether the number 
+     * of crossings corresponds to a point inside the shape or not
+     * (according to the shape's path rule).
+     * 
+     * @param cross - the point's cross count
+     * 
+     * @return true if the point is inside the path, or false otherwise
+     */
+    boolean isInside(int cross) {
+        if (rule == WIND_NON_ZERO) {
+            return Crossing.isInsideNonZero(cross);
+        }
+        return Crossing.isInsideEvenOdd(cross);
+    }
+
+    public boolean contains(double px, double py) {
+        return isInside(Crossing.crossShape(this, px, py));
+    }
+
+    public boolean contains(double rx, double ry, double rw, double rh) {
+        int cross = Crossing.intersectShape(this, rx, ry, rw, rh);
+        return cross != Crossing.CROSSING && isInside(cross);
+    }
+
+    public boolean intersects(double rx, double ry, double rw, double rh) {
+        int cross = Crossing.intersectShape(this, rx, ry, rw, rh);
+        return cross == Crossing.CROSSING || isInside(cross);
+    }
+
+    public boolean contains(Point2D p) {
+        return contains(p.getX(), p.getY());
+    }
+
+    public boolean contains(Rectangle2D r) {
+        return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+    }
+
+    public boolean intersects(Rectangle2D r) {
+        return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+    }
+
+    public PathIterator getPathIterator(AffineTransform t) {
+        return new Iterator(this, t);
+    }
+
+    public PathIterator getPathIterator(AffineTransform t, double flatness) {
+        return new FlatteningPathIterator(getPathIterator(t), flatness);
+    }
+
+    @Override
+    public Object clone() {
+        try {
+            GeneralPath p = (GeneralPath) super.clone();
+            p.types = types.clone();
+            p.points = points.clone();
+            return p;
+        } catch (CloneNotSupportedException e) {
+            throw new InternalError();
+        }
+    }
+
+}
+
diff --git a/awt/java/awt/geom/IllegalPathStateException.java b/awt/java/awt/geom/IllegalPathStateException.java
new file mode 100644
index 0000000..7f459e7
--- /dev/null
+++ b/awt/java/awt/geom/IllegalPathStateException.java
@@ -0,0 +1,50 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Denis M. Kishenko
+ * @version $Revision$
+ */
+package java.awt.geom;
+
+/**
+ * The Class IllegalPathStateException indicates errors where the 
+ * current state of a path object is imcompatible with the desired 
+ * action, such as performing non-trivial actions on an empty path.
+ */
+public class IllegalPathStateException extends RuntimeException {
+
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = -5158084205220481094L;
+
+    /**
+     * Instantiates a new illegal path state exception.
+     */
+    public IllegalPathStateException() {
+    }
+
+    /**
+     * Instantiates a new illegal path state exception with the 
+     * specified detail message.
+     * 
+     * @param s the details of the error
+     */
+    public IllegalPathStateException(String s) {
+        super(s);
+    }
+
+}
+
diff --git a/awt/java/awt/geom/Line2D.java b/awt/java/awt/geom/Line2D.java
new file mode 100644
index 0000000..a53c470
--- /dev/null
+++ b/awt/java/awt/geom/Line2D.java
@@ -0,0 +1,871 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Denis M. Kishenko
+ * @version $Revision$
+ */
+package java.awt.geom;
+
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.util.NoSuchElementException;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Class Line2D represents a line whose data is given in 
+ * high-precision values appropriate for graphical operations.
+ */
+public abstract class Line2D implements Shape, Cloneable {
+
+    /**
+     * The Class Float is the subclass of Line2D that has all 
+     * of its data values stored with float-level precision.
+     */
+    public static class Float extends Line2D {
+
+        /** The x coordinate of the starting point. */
+        public float x1;
+        
+        /** The y coordinate of the starting point. */
+        public float y1;
+        
+        /** The x coordinate of the end point. */
+        public float x2;
+        
+        /** The y coordinate of the end point. */
+        public float y2;
+
+        /**
+         * Instantiates a new float-valued Line2D with
+         * its data values set to zero.
+         */
+        public Float() {
+        }
+
+        /**
+         * Instantiates a new float-valued Line2D with
+         * the specified endpoints.
+         * 
+         * @param x1 the x coordinate of the starting point
+         * @param y1 the y coordinate of the starting point
+         * @param x2 the x coordinate of the end point
+         * @param y2 the y coordinate of the end point
+         */
+        public Float(float x1, float y1, float x2, float y2) {
+            setLine(x1, y1, x2, y2);
+        }
+
+        /**
+         * Instantiates a new float-valued Line2D with
+         * the specified endpoints.
+         * 
+         * @param p1 the starting point
+         * @param p2 the end point
+         */
+        public Float(Point2D p1, Point2D p2) {
+            setLine(p1, p2);
+        }
+
+        @Override
+        public double getX1() {
+            return x1;
+        }
+
+        @Override
+        public double getY1() {
+            return y1;
+        }
+
+        @Override
+        public double getX2() {
+            return x2;
+        }
+
+        @Override
+        public double getY2() {
+            return y2;
+        }
+
+        @Override
+        public Point2D getP1() {
+            return new Point2D.Float(x1, y1);
+        }
+
+        @Override
+        public Point2D getP2() {
+            return new Point2D.Float(x2, y2);
+        }
+
+        @Override
+        public void setLine(double x1, double y1, double x2, double y2) {
+            this.x1 = (float)x1;
+            this.y1 = (float)y1;
+            this.x2 = (float)x2;
+            this.y2 = (float)y2;
+        }
+
+        /**
+         * Sets the data values that define the line.
+         * 
+         * @param x1 the x coordinate of the starting point
+         * @param y1 the y coordinate of the starting point
+         * @param x2 the x coordinate of the end point
+         * @param y2 the y coordinate of the end point
+         */
+        public void setLine(float x1, float y1, float x2, float y2) {
+            this.x1 = x1;
+            this.y1 = y1;
+            this.x2 = x2;
+            this.y2 = y2;
+        }
+
+        public Rectangle2D getBounds2D() {
+            float rx, ry, rw, rh;
+            if (x1 < x2) {
+                rx = x1;
+                rw = x2 - x1;
+            } else {
+                rx = x2;
+                rw = x1 - x2;
+            }
+            if (y1 < y2) {
+                ry = y1;
+                rh = y2 - y1;
+            } else {
+                ry = y2;
+                rh = y1 - y2;
+            }
+            return new Rectangle2D.Float(rx, ry, rw, rh);
+        }
+    }
+
+    /**
+     * The Class Double is the subclass of Line2D that has all 
+     * of its data values stored with double-level precision.
+     */
+    public static class Double extends Line2D {
+
+        /** The x coordinate of the starting point. */
+        public double x1;
+        
+        /** The y coordinate of the starting point. */
+        public double y1;
+        
+        /** The x coordinate of the end point. */
+        public double x2;
+        
+        /** The y coordinate of the end point. */
+        public double y2;
+
+        /**
+         * Instantiates a new double-valued  Line2D with
+         * its data values set to zero.
+         */
+        public Double() {
+        }
+
+        /**
+         * Instantiates a new double-valued Line2D with
+         * the specified endpoints.
+         * 
+         * @param x1 the x coordinate of the starting point
+         * @param y1 the y coordinate of the starting point
+         * @param x2 the x coordinate of the end point
+         * @param y2 the y coordinate of the end point
+         */
+        public Double(double x1, double y1, double x2, double y2) {
+            setLine(x1, y1, x2, y2);
+        }
+
+        /**
+         * Instantiates a new double-valued Line2D with
+         * the specified endpoints.
+         * 
+         * @param p1 the starting point
+         * @param p2 the end point
+         */
+        public Double(Point2D p1, Point2D p2) {
+            setLine(p1, p2);
+        }
+
+        @Override
+        public double getX1() {
+            return x1;
+        }
+
+        @Override
+        public double getY1() {
+            return y1;
+        }
+
+        @Override
+        public double getX2() {
+            return x2;
+        }
+
+        @Override
+        public double getY2() {
+            return y2;
+        }
+
+        @Override
+        public Point2D getP1() {
+            return new Point2D.Double(x1, y1);
+        }
+
+        @Override
+        public Point2D getP2() {
+            return new Point2D.Double(x2, y2);
+        }
+
+        @Override
+        public void setLine(double x1, double y1, double x2, double y2) {
+            this.x1 = x1;
+            this.y1 = y1;
+            this.x2 = x2;
+            this.y2 = y2;
+        }
+
+        public Rectangle2D getBounds2D() {
+            double rx, ry, rw, rh;
+            if (x1 < x2) {
+                rx = x1;
+                rw = x2 - x1;
+            } else {
+                rx = x2;
+                rw = x1 - x2;
+            }
+            if (y1 < y2) {
+                ry = y1;
+                rh = y2 - y1;
+            } else {
+                ry = y2;
+                rh = y1 - y2;
+            }
+            return new Rectangle2D.Double(rx, ry, rw, rh);
+        }
+    }
+
+    /*
+     * Line2D path iterator 
+     */
+    /**
+     * The subclass of PathIterator to traverse a Line2D.
+     */
+    class Iterator implements PathIterator {
+
+        /** The x coordinate of the start line point. */
+        double x1;
+        
+        /** The y coordinate of the start line point. */
+        double y1;
+        
+        /** The x coordinate of the end line point. */
+        double x2;
+        
+        /** The y coordinate of the end line point. */
+        double y2;
+
+        /** The path iterator transformation. */
+        AffineTransform t;
+
+        /** The current segmenet index. */
+        int index;
+
+        /**
+         * Constructs a new Line2D.Iterator for given line and transformation
+         * 
+         * @param l - the source Line2D object
+         * @param at - the AffineTransform object to apply rectangle path
+         */
+        Iterator(Line2D l, AffineTransform at) {
+            this.x1 = l.getX1();
+            this.y1 = l.getY1();
+            this.x2 = l.getX2();
+            this.y2 = l.getY2();
+            this.t = at;
+        }
+
+        public int getWindingRule() {
+            return WIND_NON_ZERO;
+        }
+
+        public boolean isDone() {
+            return index > 1;
+        }
+
+        public void next() {
+            index++;
+        }
+
+        public int currentSegment(double[] coords) {
+            if (isDone()) {
+                // awt.4B=Iterator out of bounds
+                throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
+            }
+            int type;
+            if (index == 0) {
+                type = SEG_MOVETO;
+                coords[0] = x1;
+                coords[1] = y1;
+            } else {
+                type = SEG_LINETO;
+                coords[0] = x2;
+                coords[1] = y2;
+            }
+            if (t != null) {
+                t.transform(coords, 0, coords, 0, 1);
+            }
+            return type;
+        }
+
+        public int currentSegment(float[] coords) {
+            if (isDone()) {
+                // awt.4B=Iterator out of bounds
+                throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
+            }
+            int type;
+            if (index == 0) {
+                type = SEG_MOVETO;
+                coords[0] = (float)x1;
+                coords[1] = (float)y1;
+            } else {
+                type = SEG_LINETO;
+                coords[0] = (float)x2;
+                coords[1] = (float)y2;
+            }
+            if (t != null) {
+                t.transform(coords, 0, coords, 0, 1);
+            }
+            return type;
+        }
+
+    }
+
+    /**
+     * Instantiates a new Line2D.
+     */
+    protected Line2D() {
+    }
+
+    /**
+     * Gets the x coordinate of the starting point.
+     * 
+     * @return the x coordinate of the starting point
+     */
+    public abstract double getX1();
+
+    /**
+     * Gets the y coordinate of the starting point.
+     * 
+     * @return the y coordinate of the starting point
+     */
+    public abstract double getY1();
+
+    /**
+     * Gets the x coordinate of the end point.
+     * 
+     * @return the x2
+     */
+    public abstract double getX2();
+
+    /**
+     * Gets the y coordinate of the end point.
+     * 
+     * @return the y coordinate of the end point
+     */
+    public abstract double getY2();
+
+    /**
+     * Gets the p the starting point.
+     * 
+     * @return the p the starting point
+     */
+    public abstract Point2D getP1();
+
+    /**
+     * Gets the p end point.
+     * 
+     * @return the p end point
+     */
+    public abstract Point2D getP2();
+
+    /**
+     * Sets the line's endpoints.
+     * 
+     * @param x1 the x coordinate of the starting point
+     * @param y1 the y coordinate of the starting point
+     * @param x2 the x coordinate of the end point
+     * @param y2 the y coordinate of the end point
+     */
+    public abstract void setLine(double x1, double y1, double x2, double y2);
+
+    /**
+     * Sets the line's endpoints.
+     * 
+     * @param p1 the starting point
+     * @param p2 the end point
+     */
+    public void setLine(Point2D p1, Point2D p2) {
+        setLine(p1.getX(), p1.getY(), p2.getX(), p2.getY());
+    }
+
+    /**
+     * Sets the line's endpoints by copying the data from another Line2D.
+     * 
+     * @param line the Line2D to copy the endpoint data from
+     */
+    public void setLine(Line2D line) {
+        setLine(line.getX1(), line.getY1(), line.getX2(), line.getY2());
+    }
+
+    public Rectangle getBounds() {
+    return getBounds2D().getBounds();
+    }
+
+    /**
+     * Tells where the point is with respect to the line segment, 
+     * given the orientation of the line segment. If the ray 
+     * found by extending the line segment from its starting point 
+     * is rotated, this method tells whether the ray
+     * should rotate in a clockwise direction or a counter-clockwise
+     * direction to hit the point first. The return value is 0 if the 
+     * point is on the line segment, it's 1 if the point is on the ray 
+     * or if the ray should rotate in a counter-clockwise direction to get to the
+     * point, and it's -1 if the ray should rotate in a clockwise 
+     * direction to get to the point or if the point is on the line 
+     * determined by the line segment but not on the ray from the 
+     * segment's starting point and through its end point.
+     * 
+     * @param x1 the x coordinate of the starting point of the line segment
+     * @param y1 the y coordinate of the starting point of the line segment
+     * @param x2 the x coordinate of the end point of the line segment
+     * @param y2 the y coordinate of the end point of the line segment
+     * @param px the x coordinate of the test point
+     * @param py the p coordinate of the test point
+     * 
+     * @return the value that describes where the point is with respect to the line segment, 
+     * given the orientation of the line segment
+     */
+    public static int relativeCCW(double x1, double y1, double x2, double y2, double px, double py) {
+        /*
+         * A = (x2-x1, y2-y1) P = (px-x1, py-y1)
+         */
+        x2 -= x1;
+        y2 -= y1;
+        px -= x1;
+        py -= y1;
+        double t = px * y2 - py * x2; // PxA
+        if (t == 0.0) {
+            t = px * x2 + py * y2; // P*A
+            if (t > 0.0) {
+                px -= x2; // B-A
+                py -= y2;
+                t = px * x2 + py * y2; // (P-A)*A
+                if (t < 0.0) {
+                    t = 0.0;
+                }
+            }
+        }
+
+        return t < 0.0 ? -1 : (t > 0.0 ? 1 : 0);
+    }
+
+    /**
+     * Tells where the point is with respect to this line segment, 
+     * given the orientation of this line segment. If the ray 
+     * found by extending the line segment from its starting point 
+     * is rotated, this method tells whether the ray
+     * should rotate in a clockwise direction or a counter-clockwise
+     * direction to hit the point first. The return value is 0 if the 
+     * point is on the line segment, it's 1 if the point is on the ray 
+     * or if the ray should rotate in a counter-clockwise direction to get to the
+     * point, and it's -1 if the ray should rotate in a clockwise 
+     * direction to get to the point or if the point is on the line 
+     * determined by the line segment but not on the ray from the 
+     * segment's starting point and through its end point.
+     * 
+     * @param px the x coordinate of the test point
+     * @param py the p coordinate of the test point
+     * 
+     * @return the value that describes where the point is with respect to 
+     * this line segment, given the orientation of this line segment
+     */
+    public int relativeCCW(double px, double py) {
+        return relativeCCW(getX1(), getY1(), getX2(), getY2(), px, py);
+    }
+
+    /**
+     * Tells where the point is with respect to this line segment, 
+     * given the orientation of this line segment. If the ray 
+     * found by extending the line segment from its starting point 
+     * is rotated, this method tells whether the ray
+     * should rotate in a clockwise direction or a counter-clockwise
+     * direction to hit the point first. The return value is 0 if the 
+     * point is on the line segment, it's 1 if the point is on the ray 
+     * or if the ray should rotate in a counter-clockwise direction to get to the
+     * point, and it's -1 if the ray should rotate in a clockwise 
+     * direction to get to the point or if the point is on the line 
+     * determined by the line segment but not on the ray from the 
+     * segment's starting point and through its end point.
+     * 
+     * @param p the test point
+     * 
+     * @return the value that describes where the point is with respect to 
+     * this line segment, given the orientation of this line segment
+     */
+    public int relativeCCW(Point2D p) {
+        return relativeCCW(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
+    }
+
+    /**
+     * Tells whether the two line segments cross.
+     * 
+     * @param x1 the x coordinate of the starting point of the first segment
+     * @param y1 the y coordinate of the starting point of the first segment
+     * @param x2 the x coordinate of the end point of the first segment
+     * @param y2 the y coordinate of the end point of the first segment
+     * @param x3 the x coordinate of the starting point of the second segment
+     * @param y3 the y coordinate of the starting point of the second segment
+     * @param x4 the x coordinate of the end point of the second segment
+     * @param y4 the y coordinate of the end point of the second segment
+     * 
+     * @return true, if the two line segments cross
+     */
+    public static boolean linesIntersect(double x1, double y1, double x2,
+            double y2, double x3, double y3, double x4, double y4)
+    {
+        /*
+         * A = (x2-x1, y2-y1) B = (x3-x1, y3-y1) C = (x4-x1, y4-y1) D = (x4-x3,
+         * y4-y3) = C-B E = (x1-x3, y1-y3) = -B F = (x2-x3, y2-y3) = A-B
+         *
+         * Result is ((AxB) * (AxC) <=0) and ((DxE) * (DxF) <= 0)
+         *
+         * DxE = (C-B)x(-B) = BxB-CxB = BxC DxF = (C-B)x(A-B) = CxA-CxB-BxA+BxB =
+         * AxB+BxC-AxC
+         */
+
+        x2 -= x1; // A
+        y2 -= y1;
+        x3 -= x1; // B
+        y3 -= y1;
+        x4 -= x1; // C
+        y4 -= y1;
+
+        double AvB = x2 * y3 - x3 * y2;
+        double AvC = x2 * y4 - x4 * y2;
+
+        // Online
+        if (AvB == 0.0 && AvC == 0.0) {
+            if (x2 != 0.0) {
+                return
+                    (x4 * x3 <= 0.0) ||
+                    ((x3 * x2 >= 0.0) &&
+                     (x2 > 0.0 ? x3 <= x2 || x4 <= x2 : x3 >= x2 || x4 >= x2));
+            }
+            if (y2 != 0.0) {
+                return
+                    (y4 * y3 <= 0.0) ||
+                    ((y3 * y2 >= 0.0) &&
+                     (y2 > 0.0 ? y3 <= y2 || y4 <= y2 : y3 >= y2 || y4 >= y2));
+            }
+            return false;
+        }
+
+        double BvC = x3 * y4 - x4 * y3;
+
+        return (AvB * AvC <= 0.0) && (BvC * (AvB + BvC - AvC) <= 0.0);
+    }
+
+    /**
+     * Tells whether the specified line segments crosses this line segment.
+     * 
+     * @param x1 the x coordinate of the starting point of the test segment
+     * @param y1 the y coordinate of the starting point of the test segment
+     * @param x2 the x coordinate of the end point of the test segment
+     * @param y2 the y coordinate of the end point of the test segment
+     * 
+     * @return true, if the specified line segments crosses this line segment
+     */
+    public boolean intersectsLine(double x1, double y1, double x2, double y2) {
+        return linesIntersect(x1, y1, x2, y2, getX1(), getY1(), getX2(), getY2());
+    }
+
+    /**
+     * Tells whether the specified line segments crosses this line segment.
+     * 
+     * @param l the test segment
+     * 
+     * @return true, if the specified line segments crosses this line segment
+     * 
+     * @throws NullPointerException if l is null
+     */
+    public boolean intersectsLine(Line2D l) {
+        return linesIntersect(l.getX1(), l.getY1(), l.getX2(), l.getY2(), getX1(), getY1(), getX2(), getY2());
+    }
+
+    /**
+     * Gives the square of the distance between the point and the 
+     * line segment.
+     * 
+     * @param x1 the x coordinate of the starting point of the line segment
+     * @param y1 the y coordinate of the starting point of the line segment
+     * @param x2 the x coordinate of the end point of the line segment
+     * @param y2 the y coordinate of the end point of the line segment
+     * @param px the x coordinate of the test point
+     * @param py the y coordinate of the test point
+     * 
+     * @return the the square of the distance between the point and the 
+     * line segment
+     */
+    public static double ptSegDistSq(double x1, double y1, double x2, double y2, double px, double py) {
+        /*
+         * A = (x2 - x1, y2 - y1) P = (px - x1, py - y1)
+         */
+        x2 -= x1; // A = (x2, y2)
+        y2 -= y1;
+        px -= x1; // P = (px, py)
+        py -= y1;
+        double dist;
+        if (px * x2 + py * y2 <= 0.0) { // P*A
+            dist = px * px + py * py;
+        } else {
+            px = x2 - px; // P = A - P = (x2 - px, y2 - py)
+            py = y2 - py;
+            if (px * x2 + py * y2 <= 0.0) { // P*A
+                dist = px * px + py * py;
+            } else {
+                dist = px * y2 - py * x2;
+                dist = dist * dist / (x2 * x2 + y2 * y2); // pxA/|A|
+            }
+        }
+        if (dist < 0) {
+            dist = 0;
+        }
+        return dist;
+    }
+
+    /**
+     * Gives the distance between the point and the 
+     * line segment.
+     * 
+     * @param x1 the x coordinate of the starting point of the line segment
+     * @param y1 the y coordinate of the starting point of the line segment
+     * @param x2 the x coordinate of the end point of the line segment
+     * @param y2 the y coordinate of the end point of the line segment
+     * @param px the x coordinate of the test point
+     * @param py the y coordinate of the test point
+     * 
+     * @return the the distance between the point and the 
+     * line segment
+     */
+    public static double ptSegDist(double x1, double y1, double x2, double y2, double px, double py) {
+        return Math.sqrt(ptSegDistSq(x1, y1, x2, y2, px, py));
+    }
+
+    /**
+     * Gives the square of the distance between the point and this 
+     * line segment.
+     * 
+     * @param px the x coordinate of the test point
+     * @param py the y coordinate of the test point
+     * 
+     * @return the the square of the distance between the point and this 
+     * line segment
+     */
+    public double ptSegDistSq(double px, double py) {
+        return ptSegDistSq(getX1(), getY1(), getX2(), getY2(), px, py);
+    }
+
+    /**
+     * Gives the square of the distance between the point and this 
+     * line segment.
+     * 
+     * @param p the test point
+     * 
+     * @return the square of the distance between the point and this 
+     * line segment
+     */
+    public double ptSegDistSq(Point2D p) {
+        return ptSegDistSq(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
+    }
+
+    /**
+     * Gives the distance between the point and this 
+     * line segment.
+     * 
+     * @param px the x coordinate of the test point
+     * @param py the y coordinate of the test point
+     * 
+     * @return the distance between the point and this 
+     * line segment
+     */
+    public double ptSegDist(double px, double py) {
+        return ptSegDist(getX1(), getY1(), getX2(), getY2(), px, py);
+    }
+
+    /**
+     * Gives the distance between the point and this 
+     * line segment.
+     * 
+     * @param p the test point
+     * 
+     * @return the distance between the point and this 
+     * line segment
+     */
+    public double ptSegDist(Point2D p) {
+        return ptSegDist(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
+    }
+
+    /**
+     * Gives the square of the distance between the point and the 
+     * line.
+     * 
+     * @param x1 the x coordinate of the starting point of the line segment
+     * @param y1 the y coordinate of the starting point of the line segment
+     * @param x2 the x coordinate of the end point of the line segment
+     * @param y2 the y coordinate of the end point of the line segment
+     * @param px the x coordinate of the test point
+     * @param py the y coordinate of the test point
+     * 
+     * @return the square of the distance between the point and the 
+     * line
+     */
+    public static double ptLineDistSq(double x1, double y1, double x2, double y2, double px, double py) {
+        x2 -= x1;
+        y2 -= y1;
+        px -= x1;
+        py -= y1;
+        double s = px * y2 - py * x2;
+        return s * s / (x2 * x2 + y2 * y2);
+    }
+
+    /**
+     * Gives the square of the distance between the point and the 
+     * line.
+     * 
+     * @param x1 the x coordinate of the starting point of the line segment
+     * @param y1 the y coordinate of the starting point of the line segment
+     * @param x2 the x coordinate of the end point of the line segment
+     * @param y2 the y coordinate of the end point of the line segment
+     * @param px the x coordinate of the test point
+     * @param py the y coordinate of the test point
+     * 
+     * @return the square of the distance between the point and the 
+     * line
+     */
+    public static double ptLineDist(double x1, double y1, double x2, double y2, double px, double py) {
+        return Math.sqrt(ptLineDistSq(x1, y1, x2, y2, px, py));
+    }
+
+    /**
+     * Gives the square of the distance between the point and the 
+     * line determined by this Line2D.
+     * 
+     * @param px the x coordinate of the test point
+     * @param py the y coordinate of the test point
+     * 
+     * @return the square of the distance between the point and the 
+     * line determined by this Line2D
+     */
+    public double ptLineDistSq(double px, double py) {
+        return ptLineDistSq(getX1(), getY1(), getX2(), getY2(), px, py);
+    }
+
+    /**
+     * Gives the square of the distance between the point and the 
+     * line determined by this Line2D.
+     * 
+     * @param p the test point
+     * 
+     * @return the square of the distance between the point and the 
+     * line determined by this Line2D
+     */
+    public double ptLineDistSq(Point2D p) {
+        return ptLineDistSq(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
+    }
+
+    /**
+     * Gives the distance between the point and the 
+     * line determined by this Line2D.
+     * 
+     * @param px the x coordinate of the test point
+     * @param py the y coordinate of the test point
+     * 
+     * @return the distance between the point and the 
+     * line determined by this Line2D
+     */
+    public double ptLineDist(double px, double py) {
+        return ptLineDist(getX1(), getY1(), getX2(), getY2(), px, py);
+    }
+
+    /**
+     * Gives the distance between the point and the 
+     * line determined by this Line2D.
+     * 
+     * @param p the test point
+     * 
+     * @return the distance between the point and the 
+     * line determined by this Line2D
+     */
+    public double ptLineDist(Point2D p) {
+        return ptLineDist(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
+    }
+
+    public boolean contains(double px, double py) {
+        return false;
+    }
+
+    public boolean contains(Point2D p) {
+        return false;
+    }
+
+    public boolean contains(Rectangle2D r) {
+        return false;
+    }
+
+    public boolean contains(double rx, double ry, double rw, double rh) {
+        return false;
+    }
+
+    public boolean intersects(double rx, double ry, double rw, double rh) {
+        return intersects(new Rectangle2D.Double(rx, ry, rw, rh));
+    }
+
+    public boolean intersects(Rectangle2D r) {
+        return r.intersectsLine(getX1(), getY1(), getX2(), getY2());
+    }
+
+    public PathIterator getPathIterator(AffineTransform at) {
+        return new Iterator(this, at);
+    }
+
+    public PathIterator getPathIterator(AffineTransform at, double flatness) {
+        return new Iterator(this, at);
+    }
+
+    @Override
+    public Object clone() {
+        try {
+            return super.clone();
+        } catch (CloneNotSupportedException e) {
+            throw new InternalError();
+        }
+    }
+
+}
diff --git a/awt/java/awt/geom/NoninvertibleTransformException.java b/awt/java/awt/geom/NoninvertibleTransformException.java
new file mode 100644
index 0000000..2b7b542
--- /dev/null
+++ b/awt/java/awt/geom/NoninvertibleTransformException.java
@@ -0,0 +1,43 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Denis M. Kishenko
+ * @version $Revision$
+ */
+package java.awt.geom;
+
+/**
+ * The Class NoninvertibleTransformException is the exception that is thrown 
+ * when an action requires inverting an {@link AffineTransform} that is 
+ * not invertible (has determinant 0).
+ */
+public class NoninvertibleTransformException extends java.lang.Exception {
+
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = 6137225240503990466L;
+
+    /**
+     * Instantiates a new noninvertible transform exception.
+     * 
+     * @param s the error message
+     */
+    public NoninvertibleTransformException(String s) {
+        super(s);
+    }
+
+}
+
diff --git a/awt/java/awt/geom/PathIterator.java b/awt/java/awt/geom/PathIterator.java
new file mode 100644
index 0000000..5a98083
--- /dev/null
+++ b/awt/java/awt/geom/PathIterator.java
@@ -0,0 +1,132 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Denis M. Kishenko
+ * @version $Revision$
+ */
+package java.awt.geom;
+
+/**
+ * The Interface PathIterator represents an iterator object that can 
+ * be used to traverse the outline of a {@link java.awt.Shape}. 
+ * It returns points along the boundary of the Shape 
+ * which may be actual vertices (in the case of a shape made of line 
+ * segments) or may be points on a curved segment with the distance 
+ * between the points determined by a chosen flattening factor. 
+ * <p>
+ * If the shape is closed, the outline is traversed in the counter-clockwise 
+ * direction. That means that moving forward along the boundary is to travel 
+ * in such a way that the interior of the shape is to the left of the 
+ * outline path and the exterior of the shape is to the right of the outline
+ * path. The interior and exterior of the shape are determined by a 
+ * winding rule. 
+ */
+public interface PathIterator {
+
+    /** The Constant WIND_EVEN_ODD indicates the winding rule that says 
+     * that a point is outside the shape if any infinite ray from the point 
+     * crosses the outline of the shape an even number of times, otherwise
+     * it is inside. */
+    public static final int WIND_EVEN_ODD = 0;
+    
+    /** The Constant WIND_NON_ZERO indicates the winding rule that says that
+     * a point is inside the shape if every infinite ray starting from that
+     * point crosses the outline of the shape a non-zero number of times. */
+    public static final int WIND_NON_ZERO = 1;
+
+    /** The Constant SEG_MOVETO indicates that to follow the shape's outline
+     * from the previous point to the current point, the cursor (traversal 
+     * point) should be placed directly on the current point. */
+    public static final int SEG_MOVETO  = 0;
+    
+    /** The Constant SEG_LINETO indicates that to follow the shape's outline
+     * from the previous point to the current point, the cursor (traversal 
+     * point) should follow a straight line. */
+    public static final int SEG_LINETO  = 1;
+    
+    /** The Constant SEG_QUADTO indicates that to follow the shape's outline
+     * from the previous point to the current point, the cursor (traversal 
+     * point) should follow a quadratic curve. */
+    public static final int SEG_QUADTO  = 2;
+    
+    /** The Constant SEG_CUBICTO indicates that to follow the shape's outline
+     * from the previous point to the current point, the cursor (traversal 
+     * point) should follow a cubic curve. */
+    public static final int SEG_CUBICTO = 3;
+    
+    /** The Constant SEG_CLOSE indicates that the previous point was the end
+     * of the shape's outline. */
+    public static final int SEG_CLOSE   = 4;
+
+    /**
+     * Gets the winding rule, either {@link PathIterator#WIND_EVEN_ODD} or
+     * {@link PathIterator#WIND_NON_ZERO}.
+     * 
+     * @return the winding rule
+     */
+    public int getWindingRule();
+
+    /**
+     * Checks if this PathIterator has been completely traversed.
+     * 
+     * @return true, if this PathIterator has been completely traversed
+     */
+    public boolean isDone();
+
+    /**
+     * Tells this PathIterator to skip to the next segment.
+     */
+    public void next();
+
+    /**
+     * Gets the coordinates of the next vertex point along the shape's outline 
+     * and a flag that indicates what kind of segment to use in order to 
+     * connect the previous vertex point to the current vertex point to form 
+     * the current segment.
+     * 
+     * @param coords the array that the coordinates of the end point of the current 
+     * segment are written into.
+     * 
+     * @return the flag that indicates how to follow the shape's outline
+     * from the previous point to the current one, chosen from 
+     * the following constants:
+     * {@link PathIterator#SEG_MOVETO}, {@link PathIterator#SEG_LINETO}, 
+     * {@link PathIterator#SEG_QUADTO}, {@link PathIterator#SEG_CUBICTO}, 
+     * or {@link PathIterator#SEG_CLOSE}
+     */
+    public int currentSegment(float[] coords);
+
+    /**
+     * Gets the coordinates of the next vertex point along the shape's outline 
+     * and a flag that indicates what kind of segment to use in order to 
+     * connect the previous vertex point to the current vertex point to form 
+     * the current segment.
+     * 
+     * @param coords the array that the coordinates of the end point of the current 
+     * segment are written into.
+     * 
+     * @return the flag that indicates how to follow the shape's outline
+     * from the previous point to the current one, chosen from 
+     * the following constants:
+     * {@link PathIterator#SEG_MOVETO}, {@link PathIterator#SEG_LINETO}, 
+     * {@link PathIterator#SEG_QUADTO}, {@link PathIterator#SEG_CUBICTO}, 
+     * or {@link PathIterator#SEG_CLOSE}
+     */
+    public int currentSegment(double[] coords);
+
+}
+
diff --git a/awt/java/awt/geom/Point2D.java b/awt/java/awt/geom/Point2D.java
new file mode 100644
index 0000000..7719e67
--- /dev/null
+++ b/awt/java/awt/geom/Point2D.java
@@ -0,0 +1,288 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Denis M. Kishenko
+ * @version $Revision$
+ */
+package java.awt.geom;
+
+import org.apache.harmony.misc.HashCode;
+
+/**
+ * The Class Point2D represents a point whose data is given in 
+ * high-precision values appropriate for graphical operations.
+ */
+public abstract class Point2D implements Cloneable {
+
+    /**
+     * The Class Float is the subclass of Point2D that has all 
+     * of its data values stored with float-level precision.
+     */
+    public static class Float extends Point2D {
+
+        /** The x coordinate. */
+        public float x;
+        
+        /** The y coordinate. */
+        public float y;
+
+        /**
+         * Instantiates a new float-valued Point2D with its data 
+         * set to zero.
+         */
+        public Float() {
+        }
+
+        /**
+         * Instantiates a new float-valued Point2D with the specified coordinates.
+         * 
+         * @param x the x coordinate
+         * @param y the y coordinate
+         */
+        public Float(float x, float y) {
+            this.x = x;
+            this.y = y;
+        }
+
+        @Override
+        public double getX() {
+            return x;
+        }
+
+        @Override
+        public double getY() {
+            return y;
+        }
+
+        /**
+         * Sets the point's coordinates.
+         * 
+         * @param x the x coordinate
+         * @param y the y coordinate
+         */
+        public void setLocation(float x, float y) {
+            this.x = x;
+            this.y = y;
+        }
+
+        @Override
+        public void setLocation(double x, double y) {
+            this.x = (float)x;
+            this.y = (float)y;
+        }
+
+        @Override
+        public String toString() {
+            return getClass().getName() + "[x=" + x + ",y=" + y + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+        }
+    }
+
+    /**
+     * The Class Double is the subclass of Point2D that has all 
+     * of its data values stored with double-level precision.
+     */
+    public static class Double extends Point2D {
+
+        /** The x coordinate. */
+        public double x;
+        
+        /** The y coordinate. */
+        public double y;
+
+        /**
+         * Instantiates a new double-valued Point2D with its data 
+         * set to zero.
+         */
+        public Double() {
+        }
+
+        /**
+         * Instantiates a new double-valued Point2D with the specified coordinates.
+         * 
+         * @param x the x coordinate
+         * @param y the y coordinate
+         */
+        public Double(double x, double y) {
+            this.x = x;
+            this.y = y;
+        }
+
+        @Override
+        public double getX() {
+            return x;
+        }
+
+        @Override
+        public double getY() {
+            return y;
+        }
+
+        @Override
+        public void setLocation(double x, double y) {
+            this.x = x;
+            this.y = y;
+        }
+
+        @Override
+        public String toString() {
+            return getClass().getName() + "[x=" + x + ",y=" + y + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+        }
+    }
+
+    /**
+     * Instantiates a new Point2D.
+     */
+    protected Point2D() {
+    }
+
+    /**
+     * Gets the x coordinate.
+     * 
+     * @return the x coordinate
+     */
+    public abstract double getX();
+
+    /**
+     * Gets the y coordinate.
+     * 
+     * @return the y coordinate
+     */
+    public abstract double getY();
+
+    /**
+     * Sets the point's coordinates.
+     * 
+     * @param x the x coordinate
+     * @param y the y coordinate
+     */
+    public abstract void setLocation(double x, double y);
+
+    /**
+     * Sets the point's coordinates by copying them from another point.
+     * 
+     * @param p the point to copy the data from
+     */
+    public void setLocation(Point2D p) {
+        setLocation(p.getX(), p.getY());
+    }
+
+    /**
+     * Finds the square of the distance between the two specified points.
+     * 
+     * @param x1 the x coordinate of the first point
+     * @param y1 the y coordinate of the first point
+     * @param x2 the x coordinate of the second point
+     * @param y2 the y coordinate of the second point
+     * 
+     * @return the square of the distance between the two specified points
+     */
+    public static double distanceSq(double x1, double y1, double x2, double y2) {
+        x2 -= x1;
+        y2 -= y1;
+        return x2 * x2 + y2 * y2;
+    }
+
+    /**
+     * Finds the square of the distance between this point and the specified point.
+     * 
+     * @param px the x coordinate of the point
+     * @param py the y coordinate of the point
+     * 
+     * @return the square of the distance between this point and the specified point
+     */
+    public double distanceSq(double px, double py) {
+        return Point2D.distanceSq(getX(), getY(), px, py);
+    }
+
+    /**
+     * Finds the square of the distance between this point and the specified point.
+     * 
+     * @param p the other point
+     * 
+     * @return the square of the distance between this point and the specified point
+     */
+    public double distanceSq(Point2D p) {
+        return Point2D.distanceSq(getX(), getY(), p.getX(), p.getY());
+    }
+
+    /**
+     * Finds the distance between the two specified points.
+     * 
+     * @param x1 the x coordinate of the first point
+     * @param y1 the y coordinate of the first point
+     * @param x2 the x coordinate of the second point
+     * @param y2 the y coordinate of the second point
+     * 
+     * @return the distance between the two specified points
+     */
+    public static double distance(double x1, double y1, double x2, double y2) {
+        return Math.sqrt(distanceSq(x1, y1, x2, y2));
+    }
+
+    /**
+     * Finds the distance between this point and the specified point.
+     * 
+     * @param px the x coordinate of the point
+     * @param py the y coordinate of the point
+     * 
+     * @return the distance between this point and the specified point
+     */
+    public double distance(double px, double py) {
+        return Math.sqrt(distanceSq(px, py));
+    }
+
+    /**
+     * Finds the distance between this point and the specified point.
+     * 
+     * @param p the other point
+     * 
+     * @return the distance between this point and the specified point
+     */
+    public double distance(Point2D p) {
+        return Math.sqrt(distanceSq(p));
+    }
+
+    @Override
+    public Object clone() {
+        try {
+            return super.clone();
+        } catch (CloneNotSupportedException e) {
+            throw new InternalError();
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        HashCode hash = new HashCode();
+        hash.append(getX());
+        hash.append(getY());
+        return hash.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (obj instanceof Point2D) {
+            Point2D p = (Point2D) obj;
+            return getX() == p.getX() && getY() == p.getY();
+        }
+        return false;
+    }
+}
+
diff --git a/awt/java/awt/geom/QuadCurve2D.java b/awt/java/awt/geom/QuadCurve2D.java
new file mode 100644
index 0000000..64ea6d6
--- /dev/null
+++ b/awt/java/awt/geom/QuadCurve2D.java
@@ -0,0 +1,824 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Denis M. Kishenko
+ * @version $Revision$
+ */
+package java.awt.geom;
+
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.util.NoSuchElementException;
+
+import org.apache.harmony.awt.gl.Crossing;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Class QuadCurve2D is a Shape that represents a segment of a 
+ * quadratic (Bezier) curve. The curved segment is determined by three points:
+ * a start point, an end point, and a control point.  The line from the control 
+ * point to the starting point gives the tangent to the curve at the
+ * starting point, and the line from the control point to the end point 
+ * gives the tangent to the curve at the end point.
+ */
+public abstract class QuadCurve2D implements Shape, Cloneable {
+
+    /**
+     * The Class Float is the subclass of QuadCurve2D that has all 
+     * of its data values stored with float-level precision.
+     */
+    public static class Float extends QuadCurve2D {
+
+        /** The x coordinate of the starting point of the curved segment. */
+        public float x1;
+        
+        /** The y coordinate of the starting point of the curved segment. */
+        public float y1;
+        
+        /** The x coordinate of the control point.  */
+        public float ctrlx;
+        
+        /** The y coordinate of the control point. */
+        public float ctrly;
+        
+        /** The x coordinate of the end point of the curved segment. */
+        public float x2;
+        
+        /** The y coordinate of the end point of the curved segment. */
+        public float y2;
+
+        /**
+         * Instantiates a new float-valued QuadCurve2D with all coordinate values
+         * set to zero.
+         */
+        public Float() {
+        }
+
+        /**
+         * Instantiates a new float-valued QuadCurve2D with the specified
+         * coordinate values.
+         * 
+         * @param x1 the x coordinate of the starting point of the curved segment
+         * @param y1 the y coordinate of the starting point of the curved segment
+         * @param ctrlx the x coordinate of the control point
+         * @param ctrly the y coordinate of the control point
+         * @param x2 the x coordinate of the end point of the curved segment
+         * @param y2 the y coordinate of the end point of the curved segment
+         */
+        public Float(float x1, float y1, float ctrlx, float ctrly, float x2, float y2) {
+            setCurve(x1, y1, ctrlx, ctrly, x2, y2);
+        }
+
+        @Override
+        public double getX1() {
+            return x1;
+        }
+
+        @Override
+        public double getY1() {
+            return y1;
+        }
+
+        @Override
+        public double getCtrlX() {
+            return ctrlx;
+        }
+
+        @Override
+        public double getCtrlY() {
+            return ctrly;
+        }
+
+        @Override
+        public double getX2() {
+            return x2;
+        }
+
+        @Override
+        public double getY2() {
+            return y2;
+        }
+
+        @Override
+        public Point2D getP1() {
+            return new Point2D.Float(x1, y1);
+        }
+
+        @Override
+        public Point2D getCtrlPt() {
+            return new Point2D.Float(ctrlx, ctrly);
+        }
+
+        @Override
+        public Point2D getP2() {
+            return new Point2D.Float(x2, y2);
+        }
+
+        @Override
+        public void setCurve(double x1, double y1, double ctrlx, double ctrly, double x2, double y2) {
+            this.x1 = (float)x1;
+            this.y1 = (float)y1;
+            this.ctrlx = (float)ctrlx;
+            this.ctrly = (float)ctrly;
+            this.x2 = (float)x2;
+            this.y2 = (float)y2;
+        }
+
+        /**
+         * Sets the data values of the curve.
+         * 
+         * @param x1 the x coordinate of the starting point of the curved segment
+         * @param y1 the y coordinate of the starting point of the curved segment
+         * @param ctrlx the x coordinate of the control point
+         * @param ctrly the y coordinate of the control point
+         * @param x2 the x coordinate of the end point of the curved segment
+         * @param y2 the y coordinate of the end point of the curved segment
+         */
+        public void setCurve(float x1, float y1, float ctrlx, float ctrly, float x2, float y2) {
+            this.x1 = x1;
+            this.y1 = y1;
+            this.ctrlx = ctrlx;
+            this.ctrly = ctrly;
+            this.x2 = x2;
+            this.y2 = y2;
+        }
+
+        public Rectangle2D getBounds2D() {
+            float rx0 = Math.min(Math.min(x1, x2), ctrlx);
+            float ry0 = Math.min(Math.min(y1, y2), ctrly);
+            float rx1 = Math.max(Math.max(x1, x2), ctrlx);
+            float ry1 = Math.max(Math.max(y1, y2), ctrly);
+            return new Rectangle2D.Float(rx0, ry0, rx1 - rx0, ry1 - ry0);
+        }
+    }
+
+    /**
+     * The Class Double is the subclass of QuadCurve2D that has all 
+     * of its data values stored with double-level precision.
+     */
+    public static class Double extends QuadCurve2D {
+
+        /** The x coordinate of the starting point of the curved segment. */
+        public double x1;
+        
+        /** The y coordinate of the starting point of the curved segment. */
+        public double y1;
+        
+        /** The x coordinate of the control point. */
+        public double ctrlx;
+        
+        /** The y coordinate of the control point. */
+        public double ctrly;
+        
+        /** The x coordinate of the end point of the curved segment. */
+        public double x2;
+        
+        /** The y coordinate of the end point of the curved segment. */
+        public double y2;
+
+        /**
+         * Instantiates a new double-valued QuadCurve2D with all coordinate values
+         * set to zero.
+         */
+        public Double() {
+        }
+
+        /**
+         * Instantiates a new double-valued QuadCurve2D with the specified
+         * coordinate values.
+         * 
+         * @param x1 the x coordinate of the starting point of the curved segment
+         * @param y1 the y coordinate of the starting point of the curved segment
+         * @param ctrlx the x coordinate of the control point
+         * @param ctrly the y coordinate of the control point
+         * @param x2 the x coordinate of the end point of the curved segment
+         * @param y2 the y coordinate of the end point of the curved segment
+         */
+        public Double(double x1, double y1, double ctrlx, double ctrly, double x2, double y2) {
+            setCurve(x1, y1, ctrlx, ctrly, x2, y2);
+        }
+
+        @Override
+        public double getX1() {
+            return x1;
+        }
+
+        @Override
+        public double getY1() {
+            return y1;
+        }
+
+        @Override
+        public double getCtrlX() {
+            return ctrlx;
+        }
+
+        @Override
+        public double getCtrlY() {
+            return ctrly;
+        }
+
+        @Override
+        public double getX2() {
+            return x2;
+        }
+
+        @Override
+        public double getY2() {
+            return y2;
+        }
+
+        @Override
+        public Point2D getP1() {
+            return new Point2D.Double(x1, y1);
+        }
+
+        @Override
+        public Point2D getCtrlPt() {
+            return new Point2D.Double(ctrlx, ctrly);
+        }
+
+        @Override
+        public Point2D getP2() {
+            return new Point2D.Double(x2, y2);
+        }
+
+        @Override
+        public void setCurve(double x1, double y1, double ctrlx, double ctrly, double x2, double y2) {
+            this.x1 = x1;
+            this.y1 = y1;
+            this.ctrlx = ctrlx;
+            this.ctrly = ctrly;
+            this.x2 = x2;
+            this.y2 = y2;
+        }
+
+        public Rectangle2D getBounds2D() {
+            double rx0 = Math.min(Math.min(x1, x2), ctrlx);
+            double ry0 = Math.min(Math.min(y1, y2), ctrly);
+            double rx1 = Math.max(Math.max(x1, x2), ctrlx);
+            double ry1 = Math.max(Math.max(y1, y2), ctrly);
+            return new Rectangle2D.Double(rx0, ry0, rx1 - rx0, ry1 - ry0);
+        }
+    }
+
+    /*
+     * QuadCurve2D path iterator 
+     */
+    /**
+     * The PathIterator for a Quad2D curve.
+     */
+    class Iterator implements PathIterator {
+
+        /** The source QuadCurve2D object. */
+        QuadCurve2D c;
+
+        /** The path iterator transformation. */
+        AffineTransform t;
+
+        /** The current segment index. */
+        int index;
+
+        /**
+         * Constructs a new QuadCurve2D.Iterator for given curve and transformation
+         * 
+         * @param q - the source QuadCurve2D object
+         * @param t the AffineTransform that acts on the coordinates before 
+         * returning them (or null)
+         */
+        Iterator(QuadCurve2D q, AffineTransform t) {
+            this.c = q;
+            this.t = t;
+        }
+
+        public int getWindingRule() {
+            return WIND_NON_ZERO;
+        }
+
+        public boolean isDone() {
+            return (index > 1);
+        }
+
+        public void next() {
+            index++;
+        }
+
+        public int currentSegment(double[] coords) {
+            if (isDone()) {
+                // awt.4B=Iterator out of bounds
+                throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
+            }
+            int type;
+            int count;
+            if (index == 0) {
+                type = SEG_MOVETO;
+                coords[0] = c.getX1();
+                coords[1] = c.getY1();
+                count = 1;
+            } else {
+                type = SEG_QUADTO;
+                coords[0] = c.getCtrlX();
+                coords[1] = c.getCtrlY();
+                coords[2] = c.getX2();
+                coords[3] = c.getY2();
+                count = 2;
+            }
+            if (t != null) {
+                t.transform(coords, 0, coords, 0, count);
+            }
+            return type;
+        }
+
+        public int currentSegment(float[] coords) {
+            if (isDone()) {
+                // awt.4B=Iterator out of bounds
+                throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
+            }
+            int type;
+            int count;
+            if (index == 0) {
+                type = SEG_MOVETO;
+                coords[0] = (float)c.getX1();
+                coords[1] = (float)c.getY1();
+                count = 1;
+            } else {
+                type = SEG_QUADTO;
+                coords[0] = (float)c.getCtrlX();
+                coords[1] = (float)c.getCtrlY();
+                coords[2] = (float)c.getX2();
+                coords[3] = (float)c.getY2();
+                count = 2;
+            }
+            if (t != null) {
+                t.transform(coords, 0, coords, 0, count);
+            }
+            return type;
+        }
+
+    }
+
+    /**
+     * Instantiates a new quadratic curve.
+     */
+    protected QuadCurve2D() {
+    }
+
+    /**
+     * Gets the x coordinate of the starting point.
+     * 
+     * @return the x coordinate of the starting point
+     */
+    public abstract double getX1();
+
+    /**
+     * Gets the y coordinate of the starting point.
+     * 
+     * @return the y coordinate of the starting point
+     */
+    public abstract double getY1();
+
+    /**
+     * Gets the starting point.
+     * 
+     * @return the starting point
+     */
+    public abstract Point2D getP1();
+
+    /**
+     * Gets the x coordinate of the control point.
+     * 
+     * @return the x coordinate of the control point
+     */
+    public abstract double getCtrlX();
+
+    /**
+     * Gets the y coordinate of the control point.
+     * 
+     * @return y coordinate of the control point
+     */
+    public abstract double getCtrlY();
+
+    /**
+     * Gets the control point.
+     * 
+     * @return the control point
+     */
+    public abstract Point2D getCtrlPt();
+
+    /**
+     * Gets the x coordinate of the end point.
+     * 
+     * @return the x coordinate of the end point
+     */
+    public abstract double getX2();
+
+    /**
+     * Gets the y coordinate of the end point.
+     * 
+     * @return the y coordinate of the end point
+     */
+    public abstract double getY2();
+
+    /**
+     * Gets the end point.
+     * 
+     * @return the end point
+     */
+    public abstract Point2D getP2();
+
+    /**
+     * Sets the data of the curve.
+     * 
+     * @param x1 the x coordinate of the starting point of the curved segment
+     * @param y1 the y coordinate of the starting point of the curved segment
+     * @param ctrlx the x coordinate of the control point
+     * @param ctrly the y coordinate of the control point
+     * @param x2 the x coordinate of the end point of the curved segment
+     * @param y2 the y coordinate of the end point of the curved segment
+     */
+    public abstract void setCurve(double x1, double y1, double ctrlx, double ctrly, double x2, double y2);
+
+    /**
+     * Sets the data of the curve.
+     * 
+     * @param p1 the starting point of the curved segment
+     * @param cp the control point
+     * @param p2 the end point of the curved segment
+     * 
+     * @throws NullPointerException if any of the three points is null.
+     */
+    public void setCurve(Point2D p1, Point2D cp, Point2D p2) {
+        setCurve(p1.getX(), p1.getY(), cp.getX(), cp.getY(), p2.getX(), p2.getY());
+    }
+
+    /**
+     * Sets the data of the curve by reading the data from an array
+     * of values. The values are read in the same order as the arguments
+     * of the method {@link QuadCurve2D#setCurve(double, double, double, double, double, double)}.
+     * 
+     * @param coords the array of values containing the new coordinates
+     * @param offset the offset of the data to read within the array
+     * 
+     * @throws ArrayIndexOutOfBoundsException if coords.length < offset + 6.
+     * @throws NullPointerException if the coordinate array is null.
+     */
+    public void setCurve(double[] coords, int offset) {
+        setCurve(
+                coords[offset + 0], coords[offset + 1],
+                coords[offset + 2], coords[offset + 3],
+                coords[offset + 4], coords[offset + 5]);
+    }
+
+    /**
+     * Sets the data of the curve by reading the data from an array
+     * of points. The values are read in the same order as the arguments
+     * of the method {@link QuadCurve2D#setCurve(Point2D, Point2D, Point2D)}
+     * 
+     * @param points the array of points containing the new coordinates
+     * @param offset the offset of the data to read within the array
+     * 
+     * @throws ArrayIndexOutOfBoundsException if points.length < offset + 3.
+     * @throws NullPointerException if the point array is null.
+     */
+    public void setCurve(Point2D[] points, int offset) {
+        setCurve(
+                points[offset + 0].getX(), points[offset + 0].getY(),
+                points[offset + 1].getX(), points[offset + 1].getY(),
+                points[offset + 2].getX(), points[offset + 2].getY());
+    }
+
+    /**
+     * Sets the data of the curve by copying it from another QuadCurve2D.
+     * 
+     * @param curve the curve to copy the data points from
+     * 
+     * @throws NullPointerException if the curve is null.
+     */
+    public void setCurve(QuadCurve2D curve) {
+        setCurve(
+                curve.getX1(), curve.getY1(),
+                curve.getCtrlX(), curve.getCtrlY(),
+                curve.getX2(), curve.getY2());
+    }
+
+    /**
+     * Gets the square of the distance from the control point to the
+     * straight line segment connecting the start point and the end point
+     * for this curve.
+     * 
+     * @return the square of the distance from the control point to the
+     * straight line segment connecting the start point and the end point.
+     */
+    public double getFlatnessSq() {
+        return Line2D.ptSegDistSq(
+                getX1(), getY1(),
+                getX2(), getY2(),
+                getCtrlX(), getCtrlY());
+    }
+
+    /**
+     * Gets the square of the distance from the control point to the
+     * straight line segment connecting the start point and the end point.
+     * 
+     * @param x1 the x coordinate of the starting point of the curved segment
+     * @param y1 the y coordinate of the starting point of the curved segment
+     * @param ctrlx the x coordinate of the control point
+     * @param ctrly the y coordinate of the control point
+     * @param x2 the x coordinate of the end point of the curved segment
+     * @param y2 the y coordinate of the end point of the curved segment
+     * 
+     * @return the square of the distance from the control point to the
+     * straight line segment connecting the start point and the end point.
+     */
+    public static double getFlatnessSq(double x1, double y1, double ctrlx, double ctrly, double x2, double y2) {
+        return Line2D.ptSegDistSq(x1, y1, x2, y2, ctrlx, ctrly);
+    }
+
+    /**
+     * Gets the square of the distance from the control point to the
+     * straight line segment connecting the start point and the end point
+     * by reading the coordinates of the points from an array of values.
+     * The values are read in the same order as the arguments
+     * of the method {@link QuadCurve2D#getFlatnessSq(double, double, double, double, double, double)}.
+     * 
+     * @param coords the array of points containing the coordinates to use for 
+     * the calculation
+     * @param offset the offset of the data to read within the array
+     * 
+     * @return the square of the distance from the control point to the
+     * straight line segment connecting the start point and the end point.
+     * 
+     * @throws ArrayIndexOutOfBoundsException if coords.length < offset + 6.
+     * @throws NullPointerException if the coordinate array is null.
+     */
+    public static double getFlatnessSq(double coords[], int offset) {
+        return Line2D.ptSegDistSq(
+                coords[offset + 0], coords[offset + 1],
+                coords[offset + 4], coords[offset + 5],
+                coords[offset + 2], coords[offset + 3]);
+    }
+
+    /**
+     * Gets the distance from the control point to the
+     * straight line segment connecting the start point and the end point
+     * of this QuadCurve2D.
+     * 
+     * @return the the distance from the control point to the
+     * straight line segment connecting the start point and the end point
+     * of this QuadCurve2D
+     */
+    public double getFlatness() {
+        return Line2D.ptSegDist(getX1(), getY1(), getX2(), getY2(), getCtrlX(), getCtrlY());
+    }
+
+    /**
+     * Gets the distance from the control point to the
+     * straight line segment connecting the start point and the end point.
+     * 
+     * @param x1 the x coordinate of the starting point of the curved segment
+     * @param y1 the y coordinate of the starting point of the curved segment
+     * @param ctrlx the x coordinate of the control point
+     * @param ctrly the y coordinate of the control point
+     * @param x2 the x coordinate of the end point of the curved segment
+     * @param y2 the y coordinate of the end point of the curved segment
+     * 
+     * @return the the distance from the control point to the
+     * straight line segment connecting the start point and the end point
+     */
+    public static double getFlatness(double x1, double y1, double ctrlx,
+            double ctrly, double x2, double y2)
+    {
+        return Line2D.ptSegDist(x1, y1, x2, y2, ctrlx, ctrly);
+    }
+
+    /**
+     * Gets the the distance from the control point to the
+     * straight line segment connecting the start point and the end point.
+     * The values are read in the same order as the arguments
+     * of the method {@link QuadCurve2D#getFlatness(double, double, double, double, double, double)}.
+     * 
+     * @param coords the array of points containing the coordinates to use for 
+     * the calculation
+     * @param offset the offset of the data to read within the array
+     * 
+     * @return the the distance from the control point to the
+     * straight line segment connecting the start point and the end point
+     * 
+     * @throws ArrayIndexOutOfBoundsException if coords.length < offset + 6.
+     * @throws NullPointerException if the coordinate array is null.
+     */
+    public static double getFlatness(double coords[], int offset) {
+        return Line2D.ptSegDist(
+                coords[offset + 0], coords[offset + 1],
+                coords[offset + 4], coords[offset + 5],
+                coords[offset + 2], coords[offset + 3]);
+    }
+
+    /**
+     * Creates the data for two quadratic curves by dividing this
+     * curve in two. The division point is the point on the curve 
+     * that is closest to this curve's control point. The data of 
+     * this curve is left unchanged.
+     * 
+     * @param left the QuadCurve2D where the left (start) segment's 
+     * data is written
+     * @param right the QuadCurve2D where the right (end) segment's 
+     * data is written
+     * 
+     * @throws NullPointerException if either curve is null.
+     */
+    public void subdivide(QuadCurve2D left, QuadCurve2D right) {
+        subdivide(this, left, right);
+    }
+
+    /**
+     * Creates the data for two quadratic curves by dividing a source
+     * curve in two. The division point is the point on the curve 
+     * that is closest to the source curve's control point. The data of 
+     * the source curve is left unchanged.
+     * 
+     * @param src the curve that provides the initial data
+     * @param left the QuadCurve2D where the left (start) segment's 
+     * data is written
+     * @param right the QuadCurve2D where the right (end) segment's 
+     * data is written
+     * 
+     * @throws NullPointerException if one of the curves is null.
+     */
+    public static void subdivide(QuadCurve2D src, QuadCurve2D left, QuadCurve2D right) {
+        double x1 = src.getX1();
+        double y1 = src.getY1();
+        double cx = src.getCtrlX();
+        double cy = src.getCtrlY();
+        double x2 = src.getX2();
+        double y2 = src.getY2();
+        double cx1 = (x1 + cx) / 2.0;
+        double cy1 = (y1 + cy) / 2.0;
+        double cx2 = (x2 + cx) / 2.0;
+        double cy2 = (y2 + cy) / 2.0;
+        cx = (cx1 + cx2) / 2.0;
+        cy = (cy1 + cy2) / 2.0;
+        if (left != null) {
+            left.setCurve(x1, y1, cx1, cy1, cx, cy);
+        }
+        if (right != null) {
+            right.setCurve(cx, cy, cx2, cy2, x2, y2);
+        }
+    }
+
+    /**
+     * Creates the data for two quadratic curves by dividing a source
+     * curve in two. The division point is the point on the curve 
+     * that is closest to the source curve's control point. The data
+     * for the three curves is read and written from arrays of values in 
+     * the usual order: x1, y1, cx, cy, x2, y2.
+     *  
+     * @param src the array that gives the data values for the source curve
+     * @param srcoff the offset in the src array to read the values from
+     * @param left the array where the coordinates of the start curve should be written
+     * @param leftOff the offset in the left array to start writing the values
+     * @param right the array where the coordinates of the end curve should be written
+     * @param rightOff the offset in the right array to start writing the values
+     * 
+     * @throws ArrayIndexOutOfBoundsException if src.length < srcoff + 6
+     * or if left.length < leftOff + 6 or if right.length < rightOff + 6.
+     * @throws NullPointerException if one of the arrays is null.
+     */
+    public static void subdivide(double src[], int srcoff, double left[],
+            int leftOff, double right[], int rightOff)
+    {
+        double x1 = src[srcoff + 0];
+        double y1 = src[srcoff + 1];
+        double cx = src[srcoff + 2];
+        double cy = src[srcoff + 3];
+        double x2 = src[srcoff + 4];
+        double y2 = src[srcoff + 5];
+        double cx1 = (x1 + cx) / 2.0;
+        double cy1 = (y1 + cy) / 2.0;
+        double cx2 = (x2 + cx) / 2.0;
+        double cy2 = (y2 + cy) / 2.0;
+        cx = (cx1 + cx2) / 2.0;
+        cy = (cy1 + cy2) / 2.0;
+        if (left != null) {
+            left[leftOff + 0] = x1;
+            left[leftOff + 1] = y1;
+            left[leftOff + 2] = cx1;
+            left[leftOff + 3] = cy1;
+            left[leftOff + 4] = cx;
+            left[leftOff + 5] = cy;
+        }
+        if (right != null) {
+            right[rightOff + 0] = cx;
+            right[rightOff + 1] = cy;
+            right[rightOff + 2] = cx2;
+            right[rightOff + 3] = cy2;
+            right[rightOff + 4] = x2;
+            right[rightOff + 5] = y2;
+        }
+    }
+
+    /**
+     * Finds the roots of the quadratic polynomial. This is 
+     * accomplished by finding the (real) values of x that solve
+     * the following equation: eqn[2]*x*x + eqn[1]*x + eqn[0] = 0.
+     * The solutions are written back into the array eqn starting
+     * from the index 0 in the array. The return value tells how 
+     * many array elements have been changed by this method call.
+     * 
+     * @param eqn an array containing the coefficients of the 
+     * quadratic polynomial to solve.
+     * 
+     * @return the number of roots of the quadratic polynomial
+     * 
+     * @throws ArrayIndexOutOfBoundsException if eqn.length < 3.
+     * @throws NullPointerException if the array is null.
+     */
+    public static int solveQuadratic(double eqn[]) {
+        return solveQuadratic(eqn, eqn);
+    }
+
+    /**
+     * Finds the roots of the quadratic polynomial. This is 
+     * accomplished by finding the (real) values of x that solve
+     * the following equation: eqn[2]*x*x + eqn[1]*x + eqn[0] = 0.
+     * The solutions are written into the array res starting
+     * from the index 0 in the array. The return value tells how 
+     * many array elements have been written by this method call.
+     * 
+     * @param eqn an array containing the coefficients of the 
+     * quadratic polynomial to solve.
+     * @param res the array that this method writes the results into
+     * 
+     * @return the number of roots of the quadratic polynomial
+     * 
+     * @throws ArrayIndexOutOfBoundsException if eqn.length < 3 or 
+     * if res.length is less than the number of roots.
+     * @throws NullPointerException if either array is null.
+     */
+    public static int solveQuadratic(double eqn[], double res[]) {
+        return Crossing.solveQuad(eqn, res);
+    }
+
+    public boolean contains(double px, double py) {
+        return Crossing.isInsideEvenOdd(Crossing.crossShape(this, px, py));
+    }
+
+    public boolean contains(double rx, double ry, double rw, double rh) {
+        int cross = Crossing.intersectShape(this, rx, ry, rw, rh);
+        return cross != Crossing.CROSSING && Crossing.isInsideEvenOdd(cross);
+    }
+
+    public boolean intersects(double rx, double ry, double rw, double rh) {
+        int cross = Crossing.intersectShape(this, rx, ry, rw, rh);
+        return cross == Crossing.CROSSING || Crossing.isInsideEvenOdd(cross);
+    }
+
+    public boolean contains(Point2D p) {
+        return contains(p.getX(), p.getY());
+    }
+
+    public boolean intersects(Rectangle2D r) {
+        return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+    }
+
+    public boolean contains(Rectangle2D r) {
+        return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+    }
+
+    public Rectangle getBounds() {
+        return getBounds2D().getBounds();
+    }
+
+    public PathIterator getPathIterator(AffineTransform t) {
+        return new Iterator(this, t);
+    }
+
+    public PathIterator getPathIterator(AffineTransform t, double flatness) {
+        return new FlatteningPathIterator(getPathIterator(t), flatness);
+    }
+
+    @Override
+    public Object clone() {
+        try {
+            return super.clone();
+        } catch (CloneNotSupportedException e) {
+            throw new InternalError();
+        }
+    }
+
+}
+
diff --git a/awt/java/awt/geom/Rectangle2D.java b/awt/java/awt/geom/Rectangle2D.java
new file mode 100644
index 0000000..d33dd91
--- /dev/null
+++ b/awt/java/awt/geom/Rectangle2D.java
@@ -0,0 +1,761 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Denis M. Kishenko
+ * @version $Revision$
+ */
+package java.awt.geom;
+
+import java.util.NoSuchElementException;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+import org.apache.harmony.misc.HashCode;
+
+/**
+ * The Class Rectangle2D represents a rectangle whose coordinates are given 
+ * with the correct precision to be used with the Graphics2D classes.
+ */
+public abstract class Rectangle2D extends RectangularShape {
+
+    /** The Constant OUT_LEFT is a mask that is used to indicate that a 
+     * given point is outside the rectangle and to its left. */
+    public static final int OUT_LEFT   = 1;
+    
+    /** The Constant OUT_TOP is a mask that is used to indicate that a 
+     * given point is outside the rectangle and above it. */
+    public static final int OUT_TOP    = 2;
+    
+    /** The Constant OUT_RIGHT is a mask that is used to indicate that a 
+     * given point is outside the rectangle and to its right. */
+    public static final int OUT_RIGHT  = 4;
+    
+    /** The Constant OUT_BOTTOM is a mask that is used to indicate that a 
+     * given point is outside the rectangle and above it. */
+    public static final int OUT_BOTTOM = 8;
+
+    /**
+     * The Class Float is the subclass of Rectangle2D that represents a 
+     * rectangle whose data values are given as floats (with float-level
+     * precision).
+     */
+    public static class Float extends Rectangle2D {
+
+        /** The x coordinate of the rectangle's upper left corner. */
+        public float x;
+        
+        /** The y coordinate of the rectangle's upper left corner. */
+        public float y;
+        
+        /** The width of the rectangle. */
+        public float width;
+        
+        /** The height of the rectangle. */
+        public float height;
+
+        /**
+         * Instantiates a new empty rectangle with float-precision data fields.
+         */
+        public Float() {
+        }
+
+        /**
+         * Instantiates a new rectangle with the specified float-precision data.
+         * 
+         * @param x the x coordinate of the rectangle's upper left corner
+         * @param y the y coordinate of the rectangle's upper left corner
+         * @param width the width of the rectangle
+         * @param height the height of the rectangle
+         */
+        public Float(float x, float y, float width, float height) {
+            setRect(x, y, width, height);
+        }
+
+        @Override
+        public double getX() {
+            return x;
+        }
+
+        @Override
+        public double getY() {
+            return y;
+        }
+
+        @Override
+        public double getWidth() {
+            return width;
+        }
+
+        @Override
+        public double getHeight() {
+            return height;
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return width <= 0.0f || height <= 0.0f;
+        }
+
+        /**
+         * Sets the rectangle's data to the given values.
+         * 
+         * @param x the x coordinate of the rectangle's upper left corner
+         * @param y the y coordinate of the rectangle's upper left corner
+         * @param width the width of the rectangle
+         * @param height the height of the rectangle
+         */
+        public void setRect(float x, float y, float width, float height) {
+            this.x = x;
+            this.y = y;
+            this.width = width;
+            this.height = height;
+        }
+
+        @Override
+        public void setRect(double x, double y, double width, double height) {
+            this.x = (float)x;
+            this.y = (float)y;
+            this.width = (float)width;
+            this.height = (float)height;
+        }
+
+        @Override
+        public void setRect(Rectangle2D r) {
+            this.x = (float)r.getX();
+            this.y = (float)r.getY();
+            this.width = (float)r.getWidth();
+            this.height = (float)r.getHeight();
+        }
+
+        @Override
+        public int outcode(double px, double py) {
+            int code = 0;
+
+            if (width <= 0.0f) {
+                code |= OUT_LEFT | OUT_RIGHT;
+            } else
+                if (px < x) {
+                    code |= OUT_LEFT;
+                } else
+                    if (px > x + width) {
+                        code |= OUT_RIGHT;
+                    }
+
+            if (height <= 0.0f) {
+                code |= OUT_TOP | OUT_BOTTOM;
+            } else
+                if (py < y) {
+                    code |= OUT_TOP;
+                } else
+                    if (py > y + height) {
+                        code |= OUT_BOTTOM;
+                    }
+
+            return code;
+        }
+
+        @Override
+        public Rectangle2D getBounds2D() {
+            return new Float(x, y, width, height);
+        }
+
+        @Override
+        public Rectangle2D createIntersection(Rectangle2D r) {
+            Rectangle2D dst;
+            if (r instanceof Double) {
+                dst = new Rectangle2D.Double();
+            } else {
+                dst = new Rectangle2D.Float();
+            }
+            Rectangle2D.intersect(this, r, dst);
+            return dst;
+        }
+
+        @Override
+        public Rectangle2D createUnion(Rectangle2D r) {
+            Rectangle2D dst;
+            if (r instanceof Double) {
+                dst = new Rectangle2D.Double();
+            } else {
+                dst = new Rectangle2D.Float();
+            }
+            Rectangle2D.union(this, r, dst);
+            return dst;
+        }
+
+        @Override
+        public String toString() {
+            // The output format based on 1.5 release behaviour. It could be obtained in the following way
+            // System.out.println(new Rectangle2D.Float().toString())
+            return getClass().getName() + "[x=" + x + ",y=" + y + ",width=" + width + ",height=" + height + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+        }
+    }
+
+    /**
+     * The Class Double is the subclass of Rectangle2D that represents a 
+     * rectangle whose data values are given as doubles (with double-precision-level
+     * precision).
+     */
+    public static class Double extends Rectangle2D {
+
+        /** The x coordinate of the rectangle's upper left corner. */
+        public double x;
+        
+        /** The y coordinate of the rectangle's upper left corner. */
+        public double y;
+        
+        /** The width of the rectangle. */
+        public double width;
+        
+        /** The height of the rectangle. */
+        public double height;
+
+        /**
+         * Instantiates a new empty rectangle with double-precision data fields.
+         */
+        public Double() {
+        }
+
+        /**
+         * Instantiates a new rectangle with the given double values.
+         * 
+         * @param x the x coordinate of the rectangle's upper left corner
+         * @param y the y coordinate of the rectangle's upper left corner
+         * @param width the width of the rectangle
+         * @param height the height of the rectangle
+         */
+        public Double(double x, double y, double width, double height) {
+            setRect(x, y, width, height);
+        }
+
+        @Override
+        public double getX() {
+            return x;
+        }
+
+        @Override
+        public double getY() {
+            return y;
+        }
+
+        @Override
+        public double getWidth() {
+            return width;
+        }
+
+        @Override
+        public double getHeight() {
+            return height;
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return width <= 0.0 || height <= 0.0;
+        }
+
+        @Override
+        public void setRect(double x, double y, double width, double height) {
+            this.x = x;
+            this.y = y;
+            this.width = width;
+            this.height = height;
+        }
+
+        @Override
+        public void setRect(Rectangle2D r) {
+            this.x = r.getX();
+            this.y = r.getY();
+            this.width = r.getWidth();
+            this.height = r.getHeight();
+        }
+
+        @Override
+        public int outcode(double px, double py) {
+            int code = 0;
+
+            if (width <= 0.0) {
+                code |= OUT_LEFT | OUT_RIGHT;
+            } else
+                if (px < x) {
+                    code |= OUT_LEFT;
+                } else
+                    if (px > x + width) {
+                        code |= OUT_RIGHT;
+                    }
+
+            if (height <= 0.0) {
+                code |= OUT_TOP | OUT_BOTTOM;
+            } else
+                if (py < y) {
+                    code |= OUT_TOP;
+                } else
+                    if (py > y + height) {
+                        code |= OUT_BOTTOM;
+                    }
+
+            return code;
+        }
+
+        @Override
+        public Rectangle2D getBounds2D() {
+            return new Double(x, y, width, height);
+        }
+
+        @Override
+        public Rectangle2D createIntersection(Rectangle2D r) {
+            Rectangle2D dst = new Rectangle2D.Double();
+            Rectangle2D.intersect(this, r, dst);
+            return dst;
+        }
+
+        @Override
+        public Rectangle2D createUnion(Rectangle2D r) {
+            Rectangle2D dest = new Rectangle2D.Double();
+            Rectangle2D.union(this, r, dest);
+            return dest;
+        }
+
+        @Override
+        public String toString() {
+            // The output format based on 1.5 release behaviour. It could be obtained in the following way
+            // System.out.println(new Rectangle2D.Double().toString())
+            return getClass().getName() + "[x=" + x + ",y=" + y + ",width=" + width + ",height=" + height + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+        }
+    }
+
+    /**
+     * The Class Iterator provides 
+     * access to the coordinates of the Rectangle2D's boundary modified 
+     * by an AffineTransform. 
+     */
+    class Iterator implements PathIterator {
+
+        /** The x coordinate of the rectangle's upper left corner. */
+        double x;
+        
+        /** The y coordinate of the rectangle's upper left corner. */
+        double y;
+        
+        
+        /** The width of the rectangle. */
+        double width;
+        
+        /** The height of the rectangle. */
+        double height;
+                
+        /** The AffineTransform that is used to modify the coordinates 
+         * that are returned by the path iterator. */
+        AffineTransform t;
+        
+        /** The current segment index. */
+        int index;
+        
+        /**
+         * Constructs a new Rectangle2D.Iterator for given rectangle and transformation.
+         * 
+         * @param r - the source Rectangle2D object
+         * @param at - the AffineTransform object to apply to the coordinates 
+         * before returning them
+         */
+        Iterator(Rectangle2D r, AffineTransform at) {
+            this.x = r.getX();
+            this.y = r.getY();
+            this.width = r.getWidth();
+            this.height = r.getHeight();
+            this.t = at;
+            if (width < 0.0 || height < 0.0) {
+                index = 6;
+            }
+        }
+
+        public int getWindingRule() {
+            return WIND_NON_ZERO;
+        }
+
+        public boolean isDone() {
+            return index > 5;
+        }
+
+        public void next() {
+            index++;
+        }
+
+        public int currentSegment(double[] coords) {
+            if (isDone()) {
+                throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
+            }
+            if (index == 5) {
+                return SEG_CLOSE;
+            }
+            int type;
+            if (index == 0) {
+                type = SEG_MOVETO;
+                coords[0] = x;
+                coords[1] = y;
+            } else {
+                type = SEG_LINETO;
+                switch(index) {
+                case 1:
+                    coords[0] = x + width;
+                    coords[1] = y;
+                    break;
+                case 2:
+                    coords[0] = x + width;
+                    coords[1] = y + height;
+                    break;
+                case 3:
+                    coords[0] = x;
+                    coords[1] = y + height;
+                    break;
+                case 4:
+                    coords[0] = x;
+                    coords[1] = y;
+                    break;
+                }
+            }
+            if (t != null) {
+                t.transform(coords, 0, coords, 0, 1);
+            }
+            return type;
+        }
+
+        public int currentSegment(float[] coords) {
+            if (isDone()) {
+                throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
+            }
+            if (index == 5) {
+                return SEG_CLOSE;
+            }
+            int type;
+            if (index == 0) {
+                coords[0] = (float)x;
+                coords[1] = (float)y;
+                type = SEG_MOVETO;
+            } else {
+                type = SEG_LINETO;
+                switch(index) {
+                case 1:
+                    coords[0] = (float)(x + width);
+                    coords[1] = (float)y;
+                    break;
+                case 2:
+                    coords[0] = (float)(x + width);
+                    coords[1] = (float)(y + height);
+                    break;
+                case 3:
+                    coords[0] = (float)x;
+                    coords[1] = (float)(y + height);
+                    break;
+                case 4:
+                    coords[0] = (float)x;
+                    coords[1] = (float)y;
+                    break;
+                }
+            }
+            if (t != null) {
+                t.transform(coords, 0, coords, 0, 1);
+            }
+            return type;
+        }
+
+    }
+
+    /**
+     * Instantiates a new rectangle2 d.
+     */
+    protected Rectangle2D() {
+    }
+
+    /**
+     * Sets the rectangle's location and dimension.
+     * 
+     * @param x the x coordinate of the rectangle's upper left corner
+     * @param y the y coordinate of the rectangle's upper left corner
+     * @param width the width of the rectangle
+     * @param height the height of the rectangle
+     */
+    public abstract void setRect(double x, double y, double width, double height);
+
+    /**
+     * Gets the location of the point with respect to the rectangle and 
+     * packs the information into a single int using the bitmasks 
+     * {@link Rectangle2D#OUT_LEFT}, {@link Rectangle2D#OUT_RIGHT}, 
+     * {@link Rectangle2D#OUT_TOP}, and {@link Rectangle2D#OUT_BOTTOM}.
+     * If the rectangle has zero or negative width, then every point
+     * is regarded as being both to the left and to the right of the
+     * rectangle. Similarly, if the height is zero or negative then 
+     * all points are considered to be both both above and below it.
+     * 
+     * @param x the x coordinate of the point to check
+     * @param y the y coordinate of the point to check
+     * 
+     * @return the point's location with respect to the rectangle.
+     */
+    public abstract int outcode(double x, double y);
+
+    /**
+     * Creates an new rectangle that is the intersection of this rectangle
+     * with the given rectangle. The resulting rectangle may be empty. 
+     * The data of this rectangle is left unchanged.
+     * 
+     * @param r the rectangle to intersect with this rectangle.
+     * 
+     * @return the new rectangle given by intersection.
+     */
+    public abstract Rectangle2D createIntersection(Rectangle2D r);
+
+    /**
+     * Creates an new rectangle that is the union of this rectangle
+     * with the given rectangle. The new rectangle is the smallest 
+     * rectangle which contains both this rectangle and the rectangle
+     * specified as a parameter. The data of this rectangle is left unchanged.
+     * 
+     * @param r the rectangle to combine with this rectangle
+     * 
+     * @return the new rectangle given by union
+     */
+    public abstract Rectangle2D createUnion(Rectangle2D r);
+
+    /**
+     * Sets the data of this rectangle to match the data of the given 
+     * rectangle.
+     * 
+     * @param r the rectangle whose data is to be copied into this rectangle's fields.
+     */
+    public void setRect(Rectangle2D r) {
+        setRect(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+    }
+
+    @Override
+    public void setFrame(double x, double y, double width, double height) {
+        setRect(x, y, width, height);
+    }
+
+    public Rectangle2D getBounds2D() {
+        return (Rectangle2D)clone();
+    }
+
+    /**
+     * Determines whether any part of the line segment  between (and including) 
+     * the two given points touches any 
+     * part of the rectangle, including its boundary.
+     * 
+     * @param x1 the x coordinate of one of the points that determines the 
+     * line segment to test
+     * @param y1 the y coordinate of one of the points that determines the 
+     * line segment to test
+     * @param x2 the x coordinate of one of the points that determines the 
+     * line segment to test
+     * @param y2 the y coordinate of one of the points that determines the 
+     * line segment to test
+     * 
+     * @return true, if at least one point of the line segment between the 
+     * two points matches any point of the interior of the rectangle or the
+     * rectangle's boundary.
+     */
+    public boolean intersectsLine(double x1, double y1, double x2, double y2) {
+        double rx1 = getX();
+        double ry1 = getY();
+        double rx2 = rx1 + getWidth();
+        double ry2 = ry1 + getHeight();
+        return
+            (rx1 <= x1 && x1 <= rx2 && ry1 <= y1 && y1 <= ry2) ||
+            (rx1 <= x2 && x2 <= rx2 && ry1 <= y2 && y2 <= ry2) ||
+            Line2D.linesIntersect(rx1, ry1, rx2, ry2, x1, y1, x2, y2) ||
+            Line2D.linesIntersect(rx2, ry1, rx1, ry2, x1, y1, x2, y2);
+    }
+
+    /**
+     * Determines whether any part of the specified line segment touches any 
+     * part of the rectangle, including its boundary.
+     * 
+     * @param l the line segment to test
+     * 
+     * @return true, if at least one point of the given line segment 
+     * matches any point of the interior of the rectangle or the
+     * rectangle's boundary.
+     */
+    public boolean intersectsLine(Line2D l) {
+        return intersectsLine(l.getX1(), l.getY1(), l.getX2(), l.getY2());
+    }
+
+    /**
+     * Gets the location of the point with respect to the rectangle and 
+     * packs the information into a single int using the bitmasks 
+     * {@link Rectangle2D#OUT_LEFT}, {@link Rectangle2D#OUT_RIGHT}, 
+     * {@link Rectangle2D#OUT_TOP}, and {@link Rectangle2D#OUT_BOTTOM}.
+     * If the rectangle has zero or negative width, then every point
+     * is regarded as being both to the left and to the right of the
+     * rectangle. Similarly, if the height is zero or negative then 
+     * all points are considered to be both both above and below it.
+     * 
+     * @param p the point to check
+     * 
+     * @return the point's location with respect to the rectangle.
+     */
+    public int outcode(Point2D p) {
+        return outcode(p.getX(), p.getY());
+    }
+
+    public boolean contains(double x, double y) {
+        if (isEmpty()) {
+            return false;
+        }
+
+        double x1 = getX();
+        double y1 = getY();
+        double x2 = x1 + getWidth();
+        double y2 = y1 + getHeight();
+
+        return
+            x1 <= x && x < x2 &&
+            y1 <= y && y < y2;
+    }
+
+    public boolean intersects(double x, double y, double width, double height) {
+        if (isEmpty() || width <= 0.0 || height <= 0.0) {
+            return false;
+        }
+
+        double x1 = getX();
+        double y1 = getY();
+        double x2 = x1 + getWidth();
+        double y2 = y1 + getHeight();
+
+        return
+            x + width > x1 && x < x2 &&
+            y + height > y1 && y < y2;
+    }
+
+    public boolean contains(double x, double y, double width, double height) {
+        if (isEmpty() || width <= 0.0 || height <= 0.0) {
+            return false;
+        }
+
+        double x1 = getX();
+        double y1 = getY();
+        double x2 = x1 + getWidth();
+        double y2 = y1 + getHeight();
+
+        return
+            x1 <= x && x + width <= x2 &&
+            y1 <= y && y + height <= y2;
+    }
+
+    /**
+     * Changes the data values of the destination rectangle to match 
+     * the intersection of the two source rectangles, leaving the 
+     * two source rectangles unchanged. The resulting rectangle may be empty. 
+     * 
+     * @param src1 one of the two source rectangles giving the data to intersect
+     * @param src2 one of the two source rectangles giving the data to intersect
+     * @param dst the destination object where the data of the intersection is written
+     */
+    public static void intersect(Rectangle2D src1, Rectangle2D src2, Rectangle2D dst) {
+        double x1 = Math.max(src1.getMinX(), src2.getMinX());
+        double y1 = Math.max(src1.getMinY(), src2.getMinY());
+        double x2 = Math.min(src1.getMaxX(), src2.getMaxX());
+        double y2 = Math.min(src1.getMaxY(), src2.getMaxY());
+        dst.setFrame(x1, y1, x2 - x1, y2 - y1);
+    }
+
+    /**
+     * Changes the data values of the destination rectangle to match 
+     * the union of the two source rectangles, leaving the 
+     * two source rectangles unchanged. The union is the smallest rectangle
+     * tha completely covers the two source rectangles. 
+     * 
+     * @param src1 one of the two source rectangles giving the data
+     * @param src2 one of the two source rectangles giving the data
+     * @param dst the destination object where the data of the union is written
+     */
+    public static void union(Rectangle2D src1, Rectangle2D src2, Rectangle2D dst) {
+        double x1 = Math.min(src1.getMinX(), src2.getMinX());
+        double y1 = Math.min(src1.getMinY(), src2.getMinY());
+        double x2 = Math.max(src1.getMaxX(), src2.getMaxX());
+        double y2 = Math.max(src1.getMaxY(), src2.getMaxY());
+        dst.setFrame(x1, y1, x2 - x1, y2 - y1);
+    }
+
+    /**
+     * Enlarges the rectangle so that it includes the given point.
+     * 
+     * @param x the x coordinate of the new point to be covered by the rectangle
+     * @param y the y coordinate of the new point to be covered by the rectangle
+     */
+    public void add(double x, double y) {
+        double x1 = Math.min(getMinX(), x);
+        double y1 = Math.min(getMinY(), y);
+        double x2 = Math.max(getMaxX(), x);
+        double y2 = Math.max(getMaxY(), y);
+        setRect(x1, y1, x2 - x1, y2 - y1);
+    }
+
+    /**
+     * Enlarges the rectangle so that it includes the given point.
+     * 
+     * @param p the new point to be covered by the rectangle
+     */
+    public void add(Point2D p) {
+        add(p.getX(), p.getY());
+    }
+
+    /**
+     * Enlarges the rectangle so that it covers the given rectangle.
+     * 
+     * @param r the new rectangle to be covered by this rectangle
+     */
+    public void add(Rectangle2D r) {
+        union(this, r, this);
+    }
+
+    public PathIterator getPathIterator(AffineTransform t) {
+        return new Iterator(this, t);
+    }
+
+    @Override
+    public PathIterator getPathIterator(AffineTransform t, double flatness) {
+        return new Iterator(this, t);
+    }
+
+    @Override
+    public int hashCode() {
+        HashCode hash = new HashCode();
+        hash.append(getX());
+        hash.append(getY());
+        hash.append(getWidth());
+        hash.append(getHeight());
+        return hash.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (obj instanceof Rectangle2D) {
+            Rectangle2D r = (Rectangle2D)obj;
+            return
+                getX() == r.getX() &&
+                getY() == r.getY() &&
+                getWidth() == r.getWidth() &&
+                getHeight() == r.getHeight();
+        }
+        return false;
+    }
+
+}
+
diff --git a/awt/java/awt/geom/RectangularShape.java b/awt/java/awt/geom/RectangularShape.java
new file mode 100644
index 0000000..0a77dfd
--- /dev/null
+++ b/awt/java/awt/geom/RectangularShape.java
@@ -0,0 +1,276 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Denis M. Kishenko
+ * @version $Revision$
+ */
+package java.awt.geom;
+
+import java.awt.Rectangle;
+import java.awt.Shape;
+
+/**
+ * The Class RectangularShape represents a Shape whose data is 
+ * (at least partially) described by a rectangular frame. This includes 
+ * shapes which are obviously rectangular (such as Rectangle2D) as well as
+ * shapes like Arc2D which are largely determined by the rectangle they 
+ * fit inside.
+ */
+public abstract class RectangularShape implements Shape, Cloneable {
+
+    /**
+     * Instantiates a new rectangular shape.
+     */
+    protected RectangularShape() {
+    }
+
+    /**
+     * Gets the x coordinate of the upper left corner of the rectangle.
+     * 
+     * @return the x coordinate of the upper left corner of the rectangle.
+     */
+    public abstract double getX();
+
+    /**
+     * Gets the y coordinate of the upper left corner of the rectangle.
+     * 
+     * @return the y coordinate of the upper left corner of the rectangle.
+     */
+    public abstract double getY();
+
+    /**
+     * Gets the width of the rectangle.
+     * 
+     * @return the width of the rectangle.
+     */
+    public abstract double getWidth();
+
+    /**
+     * Gets the height of the rectangle.
+     * 
+     * @return the height of the rectangle.
+     */
+    public abstract double getHeight();
+
+    /**
+     * Checks if this is an empty rectangle: one with zero as its width or height.
+     * 
+     * @return true, if the width or height is empty.
+     */
+    public abstract boolean isEmpty();
+
+    /**
+     * Sets the data for the bounding rectangle in terms of double values. 
+     * 
+     * @param x the x coordinate of the upper left corner of the rectangle.
+     * @param y the y coordinate of the upper left corner of the rectangle.
+     * @param w the width of the rectangle.
+     * @param h the height of the rectangle.
+     */
+    public abstract void setFrame(double x, double y, double w, double h);
+
+    /**
+     * Gets the minimum x value of the bounding rectangle (the x 
+     * coordinate of the upper left corner of the rectangle).
+     * 
+     * @return the minimum x value of the bounding rectangle.
+     */
+    public double getMinX() {
+        return getX();
+    }
+
+    /**
+     * Gets the minimum y value of the bounding rectangle (the y 
+     * coordinate of the upper left corner of the rectangle).
+     * 
+     * @return the minimum y value of the bounding rectangle.
+     */
+    public double getMinY() {
+        return getY();
+    }
+
+    /**
+     * Gets the maximum x value of the bounding rectangle (the x
+     * coordinate of the upper left corner of the rectangle plus the 
+     * rectangle's width).
+     * 
+     * @return the maximum x value of the bounding rectangle.
+     */
+    public double getMaxX() {
+        return getX() + getWidth();
+    }
+
+    /**
+     * Gets the maximum y value of the bounding rectangle (the y
+     * coordinate of the upper left corner of the rectangle plus the 
+     * rectangle's height).
+     * 
+     * @return the maximum y value of the bounding rectangle.
+     */
+    public double getMaxY() {
+        return getY() + getHeight();
+    }
+
+    /**
+     * Gets the x coordinate of the center of the rectangle.
+     * 
+     * @return the x coordinate of the center of the rectangle.
+     */
+    public double getCenterX() {
+        return getX() + getWidth() / 2.0;
+    }
+
+    /**
+     * Gets the y coordinate of the center of the rectangle.
+     * 
+     * @return the y coordinate of the center of the rectangle.
+     */
+    public double getCenterY() {
+        return getY() + getHeight() / 2.0;
+    }
+
+    /**
+     * Places the rectangle's size and location data in a new Rectangle2D
+     * object and returns it.
+     * 
+     * @return the bounding rectangle as a new Rectangle2D object.
+     */
+    public Rectangle2D getFrame() {
+        return new Rectangle2D.Double(getX(), getY(), getWidth(), getHeight());
+    }
+
+    /**
+     * Sets the bounding rectangle in terms of a Point2D which gives its
+     * upper left corner and a Dimension2D object giving its width and height.
+     * 
+     * @param loc the new upper left corner coordinate.
+     * @param size the new size dimensions.
+     */
+    public void setFrame(Point2D loc, Dimension2D size) {
+        setFrame(loc.getX(), loc.getY(), size.getWidth(), size.getHeight());
+    }
+
+    /**
+     * Sets the bounding rectangle to match the data contained in the 
+     * specified Rectangle2D.
+     * 
+     * @param r the rectangle that gives the new frame data.
+     */
+    public void setFrame(Rectangle2D r) {
+        setFrame(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+    }
+
+    /**
+     * Sets the framing rectangle given two opposite corners. Any two corners
+     * may be used in any order as long as they are diagonally opposite one another.
+     * 
+     * @param x1 the x coordinate of one of the corner points.
+     * @param y1 the y coordinate of one of the corner points.
+     * @param x2 the x coordinate of the other corner point.
+     * @param y2 the y coordinate of the other corner point.
+     */
+    public void setFrameFromDiagonal(double x1, double y1, double x2, double y2) {
+        double rx, ry, rw, rh;
+        if (x1 < x2) {
+            rx = x1;
+            rw = x2 - x1;
+        } else {
+            rx = x2;
+            rw = x1 - x2;
+        }
+        if (y1 < y2) {
+            ry = y1;
+            rh = y2 - y1;
+        } else {
+            ry = y2;
+            rh = y1 - y2;
+        }
+        setFrame(rx, ry, rw, rh);
+    }
+
+    /**
+     * Sets the framing rectangle given two opposite corners. Any two corners
+     * may be used in any order as long as they are diagonally opposite one another.
+     * 
+     * @param p1 one of the corner points.
+     * @param p2 the other corner point.
+     */
+    public void setFrameFromDiagonal(Point2D p1, Point2D p2) {
+        setFrameFromDiagonal(p1.getX(), p1.getY(), p2.getX(), p2.getY());
+    }
+
+    /**
+     * Sets the framing rectangle given the center point and one corner. Any
+     * corner may be used.
+     * 
+     * @param centerX the x coordinate of the center point.
+     * @param centerY the y coordinate of the center point.
+     * @param cornerX the x coordinate of one of the corner points.
+     * @param cornerY the y coordinate of one of the corner points.
+     */
+    public void setFrameFromCenter(double centerX, double centerY, double cornerX, double cornerY) {
+        double width = Math.abs(cornerX - centerX);
+        double height = Math.abs(cornerY - centerY);
+        setFrame(centerX - width, centerY - height, width * 2.0, height * 2.0);
+    }
+
+    /**
+     * Sets the framing rectangle given the center point and one corner. Any
+     * corner may be used.
+     * 
+     * @param center the center point.
+     * @param corner a corner point.
+     */
+    public void setFrameFromCenter(Point2D center, Point2D corner) {
+        setFrameFromCenter(center.getX(), center.getY(), corner.getX(), corner.getY());
+    }
+
+    public boolean contains(Point2D point) {
+        return contains(point.getX(), point.getY());
+    }
+
+    public boolean intersects(Rectangle2D rect) {
+        return intersects(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
+    }
+
+    public boolean contains(Rectangle2D rect) {
+        return contains(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
+    }
+
+    public Rectangle getBounds() {
+        int x1 = (int)Math.floor(getMinX());
+        int y1 = (int)Math.floor(getMinY());
+        int x2 = (int)Math.ceil(getMaxX());
+        int y2 = (int)Math.ceil(getMaxY());
+        return new Rectangle(x1, y1, x2 - x1, y2 - y1);
+    }
+
+    public PathIterator getPathIterator(AffineTransform t, double flatness) {
+        return new FlatteningPathIterator(getPathIterator(t), flatness);
+    }
+
+    @Override
+    public Object clone() {
+        try {
+            return super.clone();
+        } catch (CloneNotSupportedException e) {
+            throw new InternalError();
+        }
+    }
+
+}
+
diff --git a/awt/java/awt/geom/RoundRectangle2D.java b/awt/java/awt/geom/RoundRectangle2D.java
new file mode 100644
index 0000000..680a146
--- /dev/null
+++ b/awt/java/awt/geom/RoundRectangle2D.java
@@ -0,0 +1,552 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Denis M. Kishenko
+ * @version $Revision$
+ */
+package java.awt.geom;
+
+import java.util.NoSuchElementException;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Class RoundRectangle2D describes a rectangle with rounded 
+ * corners with high-precision data that is appropriate for geometric
+ * operations.
+ */
+public abstract class RoundRectangle2D extends RectangularShape {
+
+    /**
+     * The Class Float is the subclass of RoundRectangle2D that has all 
+     * of its data values stored with float-level precision.
+     */
+    public static class Float extends RoundRectangle2D {
+
+        /** The x coordinate of the rectangle's upper left corner. */
+        public float x;
+        
+        /** The y coordinate of the rectangle's upper left corner. */
+        public float y;
+        
+        /** The width of the rectangle. */
+        public float width;
+        
+        /** The height of the rectangle. */
+        public float height;
+        
+        /** The arcwidth of the rounded corners. */
+        public float arcwidth;
+        
+        /** The archeight of the rounded corners. */
+        public float archeight;
+
+        /**
+         * Instantiates a new float-valued RoundRectangle2D with 
+         * its data-values set to zero.
+         */
+        public Float() {
+        }
+
+        /**
+         * Instantiates a new float-valued RoundRectangle2D with 
+         * the specified data values
+         * 
+         * @param x the x coordinate of the rectangle's upper left corner
+         * @param y the y coordinate of the rectangle's upper left corner
+         * @param width the width of the rectangle
+         * @param height the height of the rectangle
+         * @param arcwidth the arcwidth of the rounded corners
+         * @param archeight the archeight of the rounded corners
+         */
+        public Float(float x, float y, float width, float height, float arcwidth, float archeight) {
+            setRoundRect(x, y, width, height, arcwidth, archeight);
+        }
+
+        @Override
+        public double getX() {
+            return x;
+        }
+
+        @Override
+        public double getY() {
+            return y;
+        }
+
+        @Override
+        public double getWidth() {
+            return width;
+        }
+
+        @Override
+        public double getHeight() {
+            return height;
+        }
+
+        @Override
+        public double getArcWidth() {
+            return arcwidth;
+        }
+
+        @Override
+        public double getArcHeight() {
+            return archeight;
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return width <= 0.0f || height <= 0.0f;
+        }
+
+        /**
+         * Sets the data of the round rect.
+         * 
+         * @param x the x coordinate of the rectangle's upper left corner
+         * @param y the y coordinate of the rectangle's upper left corner
+         * @param width the width of the rectangle
+         * @param height the height of the rectangle
+         * @param arcwidth the arcwidth of the rounded corners
+         * @param archeight the archeight of the rounded corners
+         */
+        public void setRoundRect(float x, float y, float width, float height, float arcwidth, float archeight) {
+            this.x = x;
+            this.y = y;
+            this.width = width;
+            this.height = height;
+            this.arcwidth = arcwidth;
+            this.archeight = archeight;
+        }
+
+        @Override
+        public void setRoundRect(double x, double y, double width, double height, double arcwidth, double archeight) {
+            this.x = (float)x;
+            this.y = (float)y;
+            this.width = (float)width;
+            this.height = (float)height;
+            this.arcwidth = (float)arcwidth;
+            this.archeight = (float)archeight;
+        }
+
+        @Override
+        public void setRoundRect(RoundRectangle2D rr) {
+            this.x = (float)rr.getX();
+            this.y = (float)rr.getY();
+            this.width = (float)rr.getWidth();
+            this.height = (float)rr.getHeight();
+            this.arcwidth = (float)rr.getArcWidth();
+            this.archeight = (float)rr.getArcHeight();
+        }
+
+        public Rectangle2D getBounds2D() {
+            return new Rectangle2D.Float(x, y, width, height);
+        }
+    }
+
+    /**
+     * The Class Double is the subclass of RoundRectangle2D that has all 
+     * of its data values stored with double-level precision.
+     */
+    public static class Double extends RoundRectangle2D {
+
+        /** The x coordinate of the rectangle's upper left corner. */
+        public double x;
+        
+        /** The y coordinate of the rectangle's upper left corner. */
+        public double y;
+        
+        /** The width of the rectangle. */
+        public double width;
+        
+        /** The height of the rectangle. */
+        public double height;
+        
+        /** The arcwidth of the rounded corners. */
+        public double arcwidth;
+        
+        /** The archeight of the rounded corners. */
+        public double archeight;
+
+        /**
+         * Instantiates a new double-valued RoundRectangle2D with 
+         * its data-values set to zero.
+         */
+        public Double() {
+        }
+
+        /**
+         * Instantiates a new double-valued RoundRectangle2D with 
+         * the specified data values.
+         * 
+         * @param x the x coordinate of the rectangle's upper left corner
+         * @param y the y coordinate of the rectangle's upper left corner
+         * @param width the width of the rectangle
+         * @param height the height of the rectangle
+         * @param arcwidth the arcwidth of the rounded corners
+         * @param archeight the archeight of the rounded corners
+         */
+        public Double(double x, double y, double width, double height, double arcwidth, double archeight) {
+            setRoundRect(x, y, width, height, arcwidth, archeight);
+        }
+
+        @Override
+        public double getX() {
+            return x;
+        }
+
+        @Override
+        public double getY() {
+            return y;
+        }
+
+        @Override
+        public double getWidth() {
+            return width;
+        }
+
+        @Override
+        public double getHeight() {
+            return height;
+        }
+
+        @Override
+        public double getArcWidth() {
+            return arcwidth;
+        }
+
+        @Override
+        public double getArcHeight() {
+            return archeight;
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return width <= 0.0 || height <= 0.0;
+        }
+
+        @Override
+        public void setRoundRect(double x, double y, double width, double height, double arcwidth, double archeight) {
+            this.x = x;
+            this.y = y;
+            this.width = width;
+            this.height = height;
+            this.arcwidth = arcwidth;
+            this.archeight = archeight;
+        }
+
+        @Override
+        public void setRoundRect(RoundRectangle2D rr) {
+            this.x = rr.getX();
+            this.y = rr.getY();
+            this.width = rr.getWidth();
+            this.height = rr.getHeight();
+            this.arcwidth = rr.getArcWidth();
+            this.archeight = rr.getArcHeight();
+        }
+
+        public Rectangle2D getBounds2D() {
+            return new Rectangle2D.Double(x, y, width, height);
+        }
+    }
+
+    /*
+     * RoundRectangle2D path iterator 
+     */
+    /**
+     * The subclass of PathIterator to traverse a RoundRectangle2D.
+     */
+    class Iterator implements PathIterator {
+
+        /*
+         * Path for round corners generated the same way as Ellipse2D
+         */
+
+        /** The coefficient to calculate control points of Bezier curves. */
+        double u = 0.5 - 2.0 / 3.0 * (Math.sqrt(2.0) - 1.0);
+
+        /** The points coordinates calculation table. */
+        double points[][] = {
+                { 0.0,  0.5, 0.0,  0.0 }, // MOVETO
+                { 1.0, -0.5, 0.0,  0.0 }, // LINETO
+                { 1.0,   -u, 0.0,  0.0,   // CUBICTO
+                  1.0,  0.0, 0.0,    u,
+                  1.0,  0.0, 0.0,  0.5 },
+                { 1.0,  0.0, 1.0, -0.5 }, // LINETO
+                { 1.0,  0.0, 1.0,   -u,   // CUBICTO
+                  1.0,   -u, 1.0,  0.0,
+                  1.0, -0.5, 1.0,  0.0 },
+                { 0.0,  0.5, 1.0,  0.0 }, // LINETO
+                { 0.0,    u, 1.0,  0.0,   // CUBICTO
+                  0.0,  0.0, 1.0,   -u,
+                  0.0,  0.0, 1.0, -0.5 },
+                { 0.0,  0.0, 0.0,  0.5 }, // LINETO
+                { 0.0,  0.0, 0.0,    u,   // CUBICTO
+                  0.0,    u, 0.0,  0.0,
+                  0.0,  0.5, 0.0,  0.0 } };
+
+        /** The segment types correspond to points array. */
+        int types[] = {
+                SEG_MOVETO,
+                SEG_LINETO,
+                SEG_CUBICTO,
+                SEG_LINETO,
+                SEG_CUBICTO,
+                SEG_LINETO,
+                SEG_CUBICTO,
+                SEG_LINETO,
+                SEG_CUBICTO};
+
+        /** The x coordinate of left-upper corner of the round rectangle bounds. */
+        double x;
+        
+        /** The y coordinate of left-upper corner of the round rectangle bounds. */
+        double y;
+        
+        /** The width of the round rectangle bounds. */
+        double width;
+        
+        /** The height of the round rectangle bounds. */
+        double height;
+        
+        /** The width of arc corners of the round rectangle. */
+        double aw;
+        
+        /** The height of arc corners of the round rectangle. */
+        double ah;
+
+        /** The path iterator transformation. */
+        AffineTransform t;
+
+        /** The current segmenet index. */
+        int index;
+
+        /**
+         * Constructs a new RoundRectangle2D.Iterator for given round rectangle and transformation.
+         * 
+         * @param rr - the source RoundRectangle2D object
+         * @param at - the AffineTransform object to apply rectangle path
+         */
+        Iterator(RoundRectangle2D rr, AffineTransform at) {
+            this.x = rr.getX();
+            this.y = rr.getY();
+            this.width = rr.getWidth();
+            this.height = rr.getHeight();
+            this.aw = Math.min(width, rr.getArcWidth());
+            this.ah = Math.min(height, rr.getArcHeight());
+            this.t = at;
+            if (width < 0.0 || height < 0.0 || aw < 0.0 || ah < 0.0) {
+                index = points.length;
+            }
+        }
+
+        public int getWindingRule() {
+            return WIND_NON_ZERO;
+        }
+
+        public boolean isDone() {
+            return index > points.length;
+        }
+
+        public void next() {
+            index++;
+        }
+
+        public int currentSegment(double[] coords) {
+            if (isDone()) {
+                // awt.4B=Iterator out of bounds
+                throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
+            }
+            if (index == points.length) {
+                return SEG_CLOSE;
+            }
+            int j = 0;
+            double p[] = points[index];
+            for (int i = 0; i < p.length; i += 4) {
+                coords[j++] = x + p[i + 0] * width + p[i + 1] * aw;
+                coords[j++] = y + p[i + 2] * height + p[i + 3] * ah;
+            }
+            if (t != null) {
+                t.transform(coords, 0, coords, 0, j / 2);
+            }
+            return types[index];
+        }
+
+        public int currentSegment(float[] coords) {
+            if (isDone()) {
+                // awt.4B=Iterator out of bounds
+                throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
+            }
+            if (index == points.length) {
+                return SEG_CLOSE;
+            }
+            int j = 0;
+            double p[] = points[index];
+            for (int i = 0; i < p.length; i += 4) {
+                coords[j++] = (float)(x + p[i + 0] * width + p[i + 1] * aw);
+                coords[j++] = (float)(y + p[i + 2] * height + p[i + 3] * ah);
+            }
+            if (t != null) {
+                t.transform(coords, 0, coords, 0, j / 2);
+            }
+            return types[index];
+        }
+
+    }
+
+    /**
+     * Instantiates a new RoundRectangle2D.
+     */
+    protected RoundRectangle2D() {
+    }
+
+    /**
+     * Gets the arc width.
+     * 
+     * @return the arc width
+     */
+    public abstract double getArcWidth();
+
+    /**
+     * Gets the arc height.
+     * 
+     * @return the arc height
+     */
+    public abstract double getArcHeight();
+
+    /**
+     * Sets the data of the RoundRectangle2D.
+     * 
+     * @param x the x coordinate of the rectangle's upper left corner
+     * @param y the y coordinate of the rectangle's upper left corner
+     * @param width the width of the rectangle
+     * @param height the height of the rectangle
+     * @param arcWidth the arcwidth of the rounded corners
+     * @param arcHeight the archeight of the rounded corners
+     */
+    public abstract void setRoundRect(double x, double y, double width, double height,
+            double arcWidth, double arcHeight);
+
+    /**
+     * Sets the data of the RoundRectangle2D by copying the values
+     * from an existing RoundRectangle2D.
+     * 
+     * @param rr the round rectangle to copy the data from
+     * 
+     * @throws NullPointerException if rr is null
+     */
+    public void setRoundRect(RoundRectangle2D rr) {
+        setRoundRect(rr.getX(), rr.getY(), rr.getWidth(), rr.getHeight(), rr
+                .getArcWidth(), rr.getArcHeight());
+    }
+
+    @Override
+    public void setFrame(double x, double y, double width, double height) {
+        setRoundRect(x, y, width, height, getArcWidth(), getArcHeight());
+    }
+
+    public boolean contains(double px, double py) {
+        if (isEmpty()) {
+            return false;
+        }
+
+        double rx1 = getX();
+        double ry1 = getY();
+        double rx2 = rx1 + getWidth();
+        double ry2 = ry1 + getHeight();
+
+        if (px < rx1 || px >= rx2 || py < ry1 || py >= ry2) {
+            return false;
+        }
+
+        double aw = getArcWidth() / 2.0;
+        double ah = getArcHeight() / 2.0;
+
+        double cx, cy;
+
+        if (px < rx1 + aw) {
+            cx = rx1 + aw;
+        } else
+            if (px > rx2 - aw) {
+                cx = rx2 - aw;
+            } else {
+                return true;
+            }
+
+        if (py < ry1 + ah) {
+            cy = ry1 + ah;
+        } else
+            if (py > ry2 - ah) {
+                cy = ry2 - ah;
+            } else {
+                return true;
+            }
+
+        px = (px - cx) / aw;
+        py = (py - cy) / ah;
+        return px * px + py * py <= 1.0;
+    }
+
+    public boolean intersects(double rx, double ry, double rw, double rh) {
+        if (isEmpty() || rw <= 0.0 || rh <= 0.0) {
+            return false;
+        }
+
+        double x1 = getX();
+        double y1 = getY();
+        double x2 = x1 + getWidth();
+        double y2 = y1 + getHeight();
+
+        double rx1 = rx;
+        double ry1 = ry;
+        double rx2 = rx + rw;
+        double ry2 = ry + rh;
+
+        if (rx2 < x1 || x2 < rx1 || ry2 < y1 || y2 < ry1) {
+            return false;
+        }
+
+        double cx = (x1 + x2) / 2.0;
+        double cy = (y1 + y2) / 2.0;
+
+        double nx = cx < rx1 ? rx1 : (cx > rx2 ? rx2 : cx);
+        double ny = cy < ry1 ? ry1 : (cy > ry2 ? ry2 : cy);
+
+        return contains(nx, ny);
+    }
+
+    public boolean contains(double rx, double ry, double rw, double rh) {
+        if (isEmpty() || rw <= 0.0 || rh <= 0.0) {
+            return false;
+        }
+
+        double rx1 = rx;
+        double ry1 = ry;
+        double rx2 = rx + rw;
+        double ry2 = ry + rh;
+
+        return
+            contains(rx1, ry1) &&
+            contains(rx2, ry1) &&
+            contains(rx2, ry2) &&
+            contains(rx1, ry2);
+    }
+
+    public PathIterator getPathIterator(AffineTransform at) {
+        return new Iterator(this, at);
+    }
+
+}
+
diff --git a/awt/java/awt/im/InputContext.java b/awt/java/awt/im/InputContext.java
new file mode 100644
index 0000000..3468474
--- /dev/null
+++ b/awt/java/awt/im/InputContext.java
@@ -0,0 +1,77 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.im;
+
+import java.awt.AWTEvent;
+//???AWT: import java.awt.Component;
+import java.util.Locale;
+
+import org.apache.harmony.awt.im.InputMethodContext;
+
+public class InputContext {
+    protected InputContext() {
+    }
+
+    public static InputContext getInstance() {
+        return new InputMethodContext();
+    }
+
+    public void dispatchEvent(AWTEvent event) {
+    }
+
+    public void dispose() {
+    }
+
+    public void endComposition() {
+    }
+
+    public Object getInputMethodControlObject() {
+        return null;
+    }
+
+    public Locale getLocale() {
+        return null;
+    }
+
+    public boolean isCompositionEnabled() {
+        return false;
+    }
+
+    public void reconvert() {
+    }
+
+    //???AWT
+    /*
+    public void removeNotify(Component client) {
+    }
+    */
+
+    public boolean selectInputMethod(Locale locale) {
+        return false;
+    }
+
+    public void setCharacterSubsets(Character.Subset[] subsets) {
+    }
+    
+    public void setCompositionEnabled(boolean enable) {
+    }
+}
+
diff --git a/awt/java/awt/im/InputMethodHighlight.java b/awt/java/awt/im/InputMethodHighlight.java
new file mode 100644
index 0000000..53bb20b
--- /dev/null
+++ b/awt/java/awt/im/InputMethodHighlight.java
@@ -0,0 +1,89 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Dmitry A. Durnev
+ * @version $Revision$
+ */
+package java.awt.im;
+
+import java.util.Map;
+import java.awt.font.TextAttribute;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+public class InputMethodHighlight {
+
+    public static final int RAW_TEXT = 0;
+
+    public static final int CONVERTED_TEXT = 1;
+
+    public static final InputMethodHighlight
+        UNSELECTED_RAW_TEXT_HIGHLIGHT = new InputMethodHighlight(false, RAW_TEXT);
+
+    public static final InputMethodHighlight
+        SELECTED_RAW_TEXT_HIGHLIGHT = new InputMethodHighlight(true, RAW_TEXT);
+
+    public static final InputMethodHighlight
+        UNSELECTED_CONVERTED_TEXT_HIGHLIGHT = 
+            new InputMethodHighlight(false, CONVERTED_TEXT);
+
+    public static final InputMethodHighlight
+        SELECTED_CONVERTED_TEXT_HIGHLIGHT = 
+            new InputMethodHighlight(true, CONVERTED_TEXT);
+    
+    private boolean selected;
+    private int state;
+    private int variation;
+    private Map<TextAttribute,?> style;
+
+    public InputMethodHighlight(boolean selected, int state, int variation) {
+        this(selected, state, variation, null);
+    }
+
+    public InputMethodHighlight(boolean selected, int state,
+                                int variation, Map<java.awt.font.TextAttribute, ?> style) {
+        if ((state != RAW_TEXT) && (state != CONVERTED_TEXT)) {
+            // awt.20B=unknown input method highlight state
+            throw new IllegalArgumentException(Messages.getString("awt.20B")); //$NON-NLS-1$
+        }
+        this.selected = selected;
+        this.state = state;
+        this.variation = variation;
+        this.style = style;
+    }
+
+    public InputMethodHighlight(boolean selected, int state) {
+        this(selected, state, 0, null);
+    }
+
+    public int getState() {
+        return state;
+    }
+
+    public Map<java.awt.font.TextAttribute, ?> getStyle() {
+        return style;
+    }
+
+    public int getVariation() {
+        return variation;
+    }
+
+    public boolean isSelected() {
+        return selected;
+    }
+}
+
diff --git a/awt/java/awt/im/InputMethodRequests.java b/awt/java/awt/im/InputMethodRequests.java
new file mode 100644
index 0000000..bdd25e6
--- /dev/null
+++ b/awt/java/awt/im/InputMethodRequests.java
@@ -0,0 +1,43 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.im;
+
+import java.awt.Rectangle;
+import java.awt.font.TextHitInfo;
+import java.text.AttributedCharacterIterator;
+
+public interface InputMethodRequests {
+
+    public AttributedCharacterIterator cancelLatestCommittedText(AttributedCharacterIterator.Attribute[] attributes);
+
+    public AttributedCharacterIterator getCommittedText(int beginIndex, int endIndex, AttributedCharacterIterator.Attribute[] attributes);
+
+    public int getCommittedTextLength();
+
+    public int getInsertPositionOffset();
+
+    public TextHitInfo getLocationOffset(int x, int y);
+
+    public AttributedCharacterIterator getSelectedText(AttributedCharacterIterator.Attribute[] attributes);
+
+    public Rectangle getTextLocation(TextHitInfo offset);
+}
+
diff --git a/awt/java/awt/im/InputSubset.java b/awt/java/awt/im/InputSubset.java
new file mode 100644
index 0000000..02a1049
--- /dev/null
+++ b/awt/java/awt/im/InputSubset.java
@@ -0,0 +1,53 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Dmitry A. Durnev
+ * @version $Revision$
+ */
+package java.awt.im;
+
+public final class InputSubset extends Character.Subset {
+
+    public static final InputSubset LATIN = new InputSubset("LATIN"); //$NON-NLS-1$
+
+    public static final InputSubset 
+        LATIN_DIGITS = new InputSubset("LATIN_DIGITS"); //$NON-NLS-1$
+
+    public static final InputSubset 
+        TRADITIONAL_HANZI = new InputSubset("TRADITIONAL_HANZI"); //$NON-NLS-1$
+
+    public static final InputSubset 
+        SIMPLIFIED_HANZI = new InputSubset("SIMPLIFIED_HANZI"); //$NON-NLS-1$
+
+    public static final InputSubset KANJI = new InputSubset("KANJI"); //$NON-NLS-1$
+
+    public static final InputSubset HANJA = new InputSubset("HANJA"); //$NON-NLS-1$
+
+    public static final InputSubset 
+        HALFWIDTH_KATAKANA = new InputSubset("HALFWIDTH_KATAKANA"); //$NON-NLS-1$
+
+    public static final InputSubset 
+        FULLWIDTH_LATIN = new InputSubset("FULLWIDTH_LATIN"); //$NON-NLS-1$
+
+    public static final InputSubset 
+        FULLWIDTH_DIGITS = new InputSubset("FULLWIDTH_DIGITS"); //$NON-NLS-1$
+
+    private InputSubset(String name) {
+        super(name);
+    }
+}
+
diff --git a/awt/java/awt/im/spi/InputMethod.java b/awt/java/awt/im/spi/InputMethod.java
new file mode 100644
index 0000000..2c98c46
--- /dev/null
+++ b/awt/java/awt/im/spi/InputMethod.java
@@ -0,0 +1,61 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.im.spi;
+
+import java.awt.AWTEvent;
+import java.awt.Rectangle;
+import java.util.Locale;
+
+public interface InputMethod {
+
+    public void activate();
+
+    public void deactivate(boolean isTemporary);
+
+    public void dispatchEvent(AWTEvent event);
+
+    public void dispose();
+
+    public void endComposition();
+
+    public Object getControlObject();
+
+    public Locale getLocale();
+
+    public void hideWindows();
+
+    public boolean isCompositionEnabled();
+
+    public void notifyClientWindowChange(Rectangle bounds);
+
+    public void reconvert();
+
+    public void removeNotify();
+
+    public void setCharacterSubsets(Character.Subset[] subsets);
+
+    public void setCompositionEnabled(boolean enable);
+
+    public void setInputMethodContext(InputMethodContext context);
+
+    public boolean setLocale(Locale locale);
+}
+
diff --git a/awt/java/awt/im/spi/InputMethodContext.java b/awt/java/awt/im/spi/InputMethodContext.java
new file mode 100644
index 0000000..ca33e87
--- /dev/null
+++ b/awt/java/awt/im/spi/InputMethodContext.java
@@ -0,0 +1,40 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.im.spi;
+
+//???AWT: import java.awt.Window;
+import java.awt.font.TextHitInfo;
+import java.awt.im.InputMethodRequests;
+import java.text.AttributedCharacterIterator;
+//???AWT: import javax.swing.JFrame;
+
+public interface InputMethodContext extends InputMethodRequests {
+
+//    ???AWT: public JFrame createInputMethodJFrame(String title, boolean attachToInputContext);
+
+//    ???AWT: public Window createInputMethodWindow(String title, boolean attachToInputContext);
+
+    public void dispatchInputMethodEvent(int id, AttributedCharacterIterator text, int committedCharacterCount, TextHitInfo caret, TextHitInfo visiblePosition);
+
+    public void enableClientWindowNotification(InputMethod inputMethod, boolean enable);
+
+}
+
diff --git a/awt/java/awt/im/spi/InputMethodDescriptor.java b/awt/java/awt/im/spi/InputMethodDescriptor.java
new file mode 100644
index 0000000..3068cac
--- /dev/null
+++ b/awt/java/awt/im/spi/InputMethodDescriptor.java
@@ -0,0 +1,40 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.im.spi;
+
+import java.awt.AWTException;
+import java.awt.Image;
+import java.util.Locale;
+
+public interface InputMethodDescriptor {
+
+    public Locale[] getAvailableLocales() throws AWTException;
+
+    public InputMethod createInputMethod() throws Exception;
+
+    public String getInputMethodDisplayName(Locale inputLocale, Locale displayLanguage);
+
+    public Image getInputMethodIcon(Locale inputLocale);
+
+    public boolean hasDynamicLocaleList();
+
+}
+
diff --git a/awt/java/awt/image/AffineTransformOp.java b/awt/java/awt/image/AffineTransformOp.java
new file mode 100644
index 0000000..546837a
--- /dev/null
+++ b/awt/java/awt/image/AffineTransformOp.java
@@ -0,0 +1,617 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Oleg V. Khaschansky, Denis M. Kishenko
+ * @version $Revision$
+ */
+
+package java.awt.image;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.NoninvertibleTransformException;
+import java.awt.*;
+import java.util.Arrays;
+
+import org.apache.harmony.awt.gl.AwtImageBackdoorAccessor;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The AffineTransform class translates coordinates from 2D coordinates 
+ * in the source image or Raster to 2D coordinates in the destination 
+ * image or Raster using Affine transformation. The number of bands in 
+ * the source Raster should equal to the number of bands in the destination
+ * Raster.
+ */
+public class AffineTransformOp implements BufferedImageOp, RasterOp {
+    
+    /** 
+     * The Constant TYPE_NEAREST_NEIGHBOR indicates nearest-neighbor 
+     * interpolation type. 
+     */
+    public static final int TYPE_NEAREST_NEIGHBOR = 1;
+    
+    /** 
+     * The Constant TYPE_BILINEAR indicates bilinear interpolation type. 
+     */
+    public static final int TYPE_BILINEAR = 2;
+    
+    /** The Constant TYPE_BICUBIC indicates bicubic interpolation type. */
+    public static final int TYPE_BICUBIC = 3;
+
+    /** The i type. */
+    private int iType; // interpolation type
+    
+    /** The at. */
+    private AffineTransform at;
+    
+    /** The hints. */
+    private RenderingHints hints;
+
+    static {
+        // TODO - uncomment
+        //System.loadLibrary("imageops");
+    }
+
+    /**
+     * Instantiates a new AffineTransformOp with the specified
+     * AffineTransform and RenderingHints object which defines 
+     * the interpolation type.
+     * 
+     * @param xform the AffineTransform.
+     * @param hints the RenderingHints object which defines 
+     * the interpolation type.
+     */
+    public AffineTransformOp(AffineTransform xform, RenderingHints hints) {
+        this(xform, TYPE_NEAREST_NEIGHBOR);
+        this.hints = hints;
+
+        if (hints != null) {
+            Object hint = hints.get(RenderingHints.KEY_INTERPOLATION);
+            if (hint != null) {
+                // Nearest neighbor is default
+                if (hint == RenderingHints.VALUE_INTERPOLATION_BILINEAR) {
+                    this.iType = TYPE_BILINEAR;
+                } else if (hint == RenderingHints.VALUE_INTERPOLATION_BICUBIC) {
+                    this.iType = TYPE_BICUBIC;
+                }
+            } else {
+                hint = hints.get(RenderingHints.KEY_RENDERING);
+                // Determine from rendering quality
+                if (hint == RenderingHints.VALUE_RENDER_QUALITY) {
+                    this.iType = TYPE_BILINEAR;
+                // For speed use nearest neighbor
+                }
+            }
+        }
+    }
+
+    /**
+     * Instantiates a new AffineTransformOp with the specified
+     * AffineTransform and a specified interpolation type from the 
+     * list of predefined interpolation types.
+     * 
+     * @param xform the AffineTransform.
+     * @param interp the one of predefined interpolation types:
+     * TYPE_NEAREST_NEIGHBOR, TYPE_BILINEAR, or TYPE_BICUBIC.
+     */
+    public AffineTransformOp(AffineTransform xform, int interp) {
+        if (Math.abs(xform.getDeterminant()) <= Double.MIN_VALUE) {
+            // awt.24F=Unable to invert transform {0}
+            throw new ImagingOpException(Messages.getString("awt.24F", xform)); //$NON-NLS-1$
+        }
+
+        this.at = (AffineTransform) xform.clone();
+
+        if (interp != TYPE_NEAREST_NEIGHBOR && interp != TYPE_BILINEAR && interp != TYPE_BICUBIC) {
+            // awt.250=Unknown interpolation type: {0}
+            throw new IllegalArgumentException(Messages.getString("awt.250", interp)); //$NON-NLS-1$
+        }
+
+        this.iType = interp;
+    }
+
+    /**
+     * Gets the interpolation type.
+     * 
+     * @return the interpolation type
+     */
+    public final int getInterpolationType() {
+        return iType;
+    }
+
+    public final RenderingHints getRenderingHints() {
+        if (hints == null) {
+            Object value = null;
+
+            switch (iType) {
+                case TYPE_NEAREST_NEIGHBOR:
+                    value = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR;
+                    break;
+                case TYPE_BILINEAR:
+                    value = RenderingHints.VALUE_INTERPOLATION_BILINEAR;
+                    break;
+                case TYPE_BICUBIC:
+                    value = RenderingHints.VALUE_INTERPOLATION_BICUBIC;
+                    break;
+                default:
+                    value = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR;
+            }
+
+            hints = new RenderingHints(RenderingHints.KEY_INTERPOLATION, value);
+        }
+
+        return hints;
+    }
+
+    /**
+     * Gets the affine transform associated with this AffineTransformOp.
+     * 
+     * @return the AffineTransform.
+     */
+    public final AffineTransform getTransform() {
+        return (AffineTransform) at.clone();
+    }
+
+    public final Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
+        return at.transform(srcPt, dstPt);
+    }
+
+    public final Rectangle2D getBounds2D(BufferedImage src) {
+        return getBounds2D(src.getRaster());
+    }
+
+    public final Rectangle2D getBounds2D(Raster src) {
+        // We position source raster to (0,0) even if it is translated child raster.
+        // This means that we need only width and height of the src
+        int width = src.getWidth();
+        int height = src.getHeight();
+
+        float[] corners = {
+            0, 0,
+            width, 0,
+            width, height,
+            0, height
+        };
+
+        at.transform(corners, 0, corners, 0, 4);
+
+        Rectangle2D.Float bounds = new Rectangle2D.Float(corners[0], corners[1], 0 , 0);
+        bounds.add(corners[2], corners[3]);
+        bounds.add(corners[4], corners[5]);
+        bounds.add(corners[6], corners[7]);
+
+        return bounds;
+    }
+
+    public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel destCM) {
+        Rectangle2D newBounds = getBounds2D(src);
+
+        // Destination image should include (0,0) + positive part
+        // of the area bounded by newBounds (in source coordinate system).
+        double dstWidth = newBounds.getX() + newBounds.getWidth();
+        double dstHeight = newBounds.getY() + newBounds.getHeight();
+
+        if (dstWidth <= 0 || dstHeight <= 0) {
+            // awt.251=Transformed width ({0}) and height ({1}) should be greater than 0
+            throw new RasterFormatException(
+                    Messages.getString("awt.251", dstWidth, dstHeight)); //$NON-NLS-1$
+        }
+
+        if (destCM != null) {
+            return new BufferedImage(destCM,
+                    destCM.createCompatibleWritableRaster((int)dstWidth, (int)dstHeight),
+                    destCM.isAlphaPremultiplied(),
+                    null
+            );
+        }
+
+        ColorModel cm = src.getColorModel();
+
+        // Interpolation other than NN doesn't make any sense for index color
+        if (iType != TYPE_NEAREST_NEIGHBOR && cm instanceof IndexColorModel) {
+            return new BufferedImage((int)dstWidth, (int)dstHeight, BufferedImage.TYPE_INT_ARGB);
+        }
+
+        // OK, we can get source color model
+        return new BufferedImage(cm,
+                src.getRaster().createCompatibleWritableRaster((int)dstWidth, (int)dstHeight),
+                cm.isAlphaPremultiplied(),
+                null
+        );
+    }
+
+    public WritableRaster createCompatibleDestRaster (Raster src) {
+        // Here approach is other then in createCompatibleDestImage -
+        // destination should include only
+        // transformed image, but not (0,0) in source coordinate system
+
+        Rectangle2D newBounds = getBounds2D(src);
+        return src.createCompatibleWritableRaster(
+                (int) newBounds.getX(), (int) newBounds.getY(),
+                (int) newBounds.getWidth(), (int)newBounds.getHeight()
+        );
+    }
+
+    public final BufferedImage filter(BufferedImage src, BufferedImage dst) {
+        if (src == dst) {
+            // awt.252=Source can't be same as the destination
+            throw new IllegalArgumentException(Messages.getString("awt.252")); //$NON-NLS-1$
+        }
+
+        ColorModel srcCM = src.getColorModel();
+        BufferedImage finalDst = null;
+
+        if (
+                srcCM instanceof IndexColorModel &&
+                (iType != TYPE_NEAREST_NEIGHBOR || srcCM.getPixelSize() % 8 != 0)
+        ) {
+            src = ((IndexColorModel)srcCM).convertToIntDiscrete(src.getRaster(), true);
+            srcCM = src.getColorModel();
+        }
+
+        if (dst == null) {
+            dst = createCompatibleDestImage(src, srcCM);
+        } else {
+            if (!srcCM.equals(dst.getColorModel())) {
+                // Treat BufferedImage.TYPE_INT_RGB and BufferedImage.TYPE_INT_ARGB as same
+                if (
+                   !(
+                     (src.getType() == BufferedImage.TYPE_INT_RGB ||
+                      src.getType() == BufferedImage.TYPE_INT_ARGB) &&
+                     (dst.getType() == BufferedImage.TYPE_INT_RGB ||
+                      dst.getType() == BufferedImage.TYPE_INT_ARGB)
+                    )
+                ) {
+                    finalDst = dst;
+                    dst = createCompatibleDestImage(src, srcCM);
+                }
+            }
+        }
+
+        // Skip alpha channel for TYPE_INT_RGB images
+        if (slowFilter(src.getRaster(), dst.getRaster()) != 0) {
+            // awt.21F=Unable to transform source
+            throw new ImagingOpException (Messages.getString("awt.21F")); //$NON-NLS-1$
+        // TODO - uncomment
+        //if (ippFilter(src.getRaster(), dst.getRaster(), src.getType()) != 0)
+            //throw new ImagingOpException ("Unable to transform source");
+        }
+
+        if (finalDst != null) {
+            Graphics2D g = finalDst.createGraphics();
+            g.setComposite(AlphaComposite.Src);
+            g.drawImage(dst, 0, 0, null);
+        } else {
+            finalDst = dst;
+        }
+
+        return finalDst;
+    }
+
+    public final WritableRaster filter(Raster src, WritableRaster dst) {
+        if (src == dst) {
+            // awt.252=Source can't be same as the destination
+            throw new IllegalArgumentException(Messages.getString("awt.252")); //$NON-NLS-1$
+        }
+
+        if (dst == null) {
+            dst = createCompatibleDestRaster(src);
+        } else if (src.getNumBands() != dst.getNumBands()) {
+            // awt.253=Different number of bands in source and destination
+            throw new IllegalArgumentException(Messages.getString("awt.253")); //$NON-NLS-1$
+        }
+
+        if (slowFilter(src, dst) != 0) {
+            // awt.21F=Unable to transform source
+            throw new ImagingOpException(Messages.getString("awt.21F")); //$NON-NLS-1$
+        // TODO - uncomment
+        //if (ippFilter(src, dst, BufferedImage.TYPE_CUSTOM) != 0)
+        //    throw new ImagingOpException("Unable to transform source");
+        }
+
+        return dst;
+    }
+
+    // TODO remove when method is used
+    /**
+     * Ipp filter.
+     * 
+     * @param src the src
+     * @param dst the dst
+     * @param imageType the image type
+     * 
+     * @return the int
+     */
+    @SuppressWarnings("unused")
+    private int ippFilter(Raster src, WritableRaster dst, int imageType) {
+        int srcStride, dstStride;
+        boolean skipChannel = false;
+        int channels;
+        int offsets[] = null;
+
+        switch (imageType) {
+            case BufferedImage.TYPE_INT_RGB:
+            case BufferedImage.TYPE_INT_BGR: {
+                channels = 4;
+                srcStride = src.getWidth()*4;
+                dstStride = dst.getWidth()*4;
+                skipChannel = true;
+                break;
+            }
+
+            case BufferedImage.TYPE_INT_ARGB:
+            case BufferedImage.TYPE_INT_ARGB_PRE:
+            case BufferedImage.TYPE_4BYTE_ABGR:
+            case BufferedImage.TYPE_4BYTE_ABGR_PRE: {
+                channels = 4;
+                srcStride = src.getWidth()*4;
+                dstStride = dst.getWidth()*4;
+                break;
+            }
+
+            case BufferedImage.TYPE_BYTE_GRAY:
+            case BufferedImage.TYPE_BYTE_INDEXED: {
+                channels = 1;
+                srcStride = src.getWidth();
+                dstStride = dst.getWidth();
+                break;
+            }
+
+            case BufferedImage.TYPE_3BYTE_BGR: {
+                channels = 3;
+                srcStride = src.getWidth()*3;
+                dstStride = dst.getWidth()*3;
+                break;
+            }
+
+            case BufferedImage.TYPE_USHORT_GRAY: // TODO - could be done in native code?
+            case BufferedImage.TYPE_USHORT_565_RGB:
+            case BufferedImage.TYPE_USHORT_555_RGB:
+            case BufferedImage.TYPE_BYTE_BINARY: {
+                return slowFilter(src, dst);
+            }
+
+            default: {
+                SampleModel srcSM = src.getSampleModel();
+                SampleModel dstSM = dst.getSampleModel();
+
+                if (
+                        srcSM instanceof PixelInterleavedSampleModel &&
+                        dstSM instanceof PixelInterleavedSampleModel
+                ) {
+                    // Check PixelInterleavedSampleModel
+                    if (
+                            srcSM.getDataType() != DataBuffer.TYPE_BYTE ||
+                            dstSM.getDataType() != DataBuffer.TYPE_BYTE
+                    ) {
+                        return slowFilter(src, dst);
+                    }
+
+                    channels = srcSM.getNumBands(); // Have IPP functions for 1, 3 and 4 channels
+                    if (channels != 1 && channels != 3 && channels != 4) {
+                        return slowFilter(src, dst);
+                    }
+
+                    int dataTypeSize = DataBuffer.getDataTypeSize(srcSM.getDataType()) / 8;
+
+                    srcStride = ((ComponentSampleModel) srcSM).getScanlineStride() * dataTypeSize;
+                    dstStride = ((ComponentSampleModel) dstSM).getScanlineStride() * dataTypeSize;
+                } else if (
+                        srcSM instanceof SinglePixelPackedSampleModel &&
+                        dstSM instanceof SinglePixelPackedSampleModel
+                ) {
+                    // Check SinglePixelPackedSampleModel
+                    SinglePixelPackedSampleModel sppsm1 = (SinglePixelPackedSampleModel) srcSM;
+                    SinglePixelPackedSampleModel sppsm2 = (SinglePixelPackedSampleModel) dstSM;
+
+                    // No IPP function for this type
+                    if (sppsm1.getDataType() == DataBuffer.TYPE_USHORT) {
+                        return slowFilter(src, dst);
+                    }
+
+                    channels = sppsm1.getNumBands();
+                    // Have IPP functions for 1, 3 and 4 channels
+                    if (channels != 1 && channels != 3 && channels != 4) {
+                        return slowFilter(src, dst);
+                    }
+
+                    // Check compatibility of sample models
+                    if (
+                            sppsm1.getDataType() != sppsm2.getDataType() ||
+                            !Arrays.equals(sppsm1.getBitOffsets(), sppsm2.getBitOffsets()) ||
+                            !Arrays.equals(sppsm1.getBitMasks(), sppsm2.getBitMasks())
+                    ) {
+                        return slowFilter(src, dst);
+                    }
+
+                    for (int i=0; i<channels; i++) {
+                        if (sppsm1.getSampleSize(i) != 8) {
+                            return slowFilter(src, dst);
+                        }
+                    }
+
+                    if (channels == 3) {
+                        channels = 4;
+                    }
+
+                    int dataTypeSize = DataBuffer.getDataTypeSize(sppsm1.getDataType()) / 8;
+
+                    srcStride = sppsm1.getScanlineStride() * dataTypeSize;
+                    dstStride = sppsm2.getScanlineStride() * dataTypeSize;
+                } else {
+                    return slowFilter(src, dst);
+                }
+
+                // Fill offsets if there's a child raster
+                if (src.getParent() != null || dst.getParent() != null) {
+                    if (
+                            src.getSampleModelTranslateX() != 0 ||
+                            src.getSampleModelTranslateY() != 0 ||
+                            dst.getSampleModelTranslateX() != 0 ||
+                            dst.getSampleModelTranslateY() != 0
+                    ) {
+                        offsets = new int[4];
+                        offsets[0] = -src.getSampleModelTranslateX() + src.getMinX();
+                        offsets[1] = -src.getSampleModelTranslateY() + src.getMinY();
+                        offsets[2] = -dst.getSampleModelTranslateX() + dst.getMinX();
+                        offsets[3] = -dst.getSampleModelTranslateY() + dst.getMinY();
+                    }
+                }
+            }
+        }
+
+        double m00 = at.getScaleX();
+        double m01 = at.getShearX();
+        double m02 = at.getTranslateX();
+        double m10 = at.getShearY();
+        double m11 = at.getScaleY();
+        double m12 = at.getTranslateY();
+
+        Object srcData, dstData;
+        AwtImageBackdoorAccessor dbAccess = AwtImageBackdoorAccessor.getInstance();
+        try {
+            srcData = dbAccess.getData(src.getDataBuffer());
+            dstData = dbAccess.getData(dst.getDataBuffer());
+        } catch (IllegalArgumentException e) {
+            return -1; // Unknown data buffer type
+        }
+
+        return ippAffineTransform(
+            m00, m01, m02, m10, m11, m12,
+            srcData, src.getWidth(), src.getHeight(), srcStride,
+            dstData, dst.getWidth(), dst.getHeight(), dstStride,
+            iType, channels, skipChannel, offsets);
+    }
+
+    /**
+     * Slow filter.
+     * 
+     * @param src the src
+     * @param dst the dst
+     * 
+     * @return the int
+     */
+    private int slowFilter(Raster src, WritableRaster dst) {
+        // TODO: make correct interpolation
+        // TODO: what if there are different data types?
+
+        Rectangle srcBounds = src.getBounds();
+        Rectangle dstBounds = dst.getBounds();
+        Rectangle normDstBounds = new Rectangle(0, 0, dstBounds.width, dstBounds.height);
+        Rectangle bounds = getBounds2D(src).getBounds().intersection(normDstBounds);
+
+        AffineTransform inv = null;
+        try {
+             inv = at.createInverse();
+        } catch (NoninvertibleTransformException e) {
+            return -1;
+        }
+
+        double[] m = new double[6];
+        inv.getMatrix(m);
+
+        int minSrcX = srcBounds.x;
+        int minSrcY = srcBounds.y;
+        int maxSrcX = srcBounds.x + srcBounds.width;
+        int maxSrcY = srcBounds.y + srcBounds.height;
+
+        int minX = bounds.x + dstBounds.x;
+        int minY = bounds.y + dstBounds.y;
+        int maxX = minX + bounds.width;
+        int maxY = minY + bounds.height;
+
+        int hx = (int)(m[0] * 256);
+        int hy = (int)(m[1] * 256);
+        int vx = (int)(m[2] * 256);
+        int vy = (int)(m[3] * 256);
+        int sx = (int)(m[4] * 256) + hx * bounds.x + vx * bounds.y + (srcBounds.x) * 256;
+        int sy = (int)(m[5] * 256) + hy * bounds.x + vy * bounds.y + (srcBounds.y) * 256;
+
+        vx -= hx * bounds.width;
+        vy -= hy * bounds.width;
+
+        if (src.getTransferType() == dst.getTransferType()) {
+            for (int y = minY; y < maxY; y++) {
+                for (int x = minX; x < maxX; x++) {
+                    int px = sx >> 8;
+                    int py = sy >> 8;
+                    if (px >= minSrcX && py >= minSrcY && px < maxSrcX && py < maxSrcY) {
+                        Object val = src.getDataElements(px , py , null);
+                        dst.setDataElements(x, y, val);
+                    }
+                    sx += hx;
+                    sy += hy;
+                }
+                sx += vx;
+                sy += vy;
+            }
+        } else {
+            float pixel[] = null;
+            for (int y = minY; y < maxY; y++) {
+                for (int x = minX; x < maxX; x++) {
+                    int px = sx >> 8;
+                    int py = sy >> 8;
+                    if (px >= minSrcX && py >= minSrcY && px < maxSrcX && py < maxSrcY) {
+                        pixel = src.getPixel(px, py, pixel);
+                        dst.setPixel(x, y, pixel);
+                    }
+                    sx += hx;
+                    sy += hy;
+                }
+                sx += vx;
+                sy += vy;
+            }
+        }
+
+        return 0;
+    }
+
+    /**
+     * Ipp affine transform.
+     * 
+     * @param m00 the m00
+     * @param m01 the m01
+     * @param m02 the m02
+     * @param m10 the m10
+     * @param m11 the m11
+     * @param m12 the m12
+     * @param src the src
+     * @param srcWidth the src width
+     * @param srcHeight the src height
+     * @param srcStride the src stride
+     * @param dst the dst
+     * @param dstWidth the dst width
+     * @param dstHeight the dst height
+     * @param dstStride the dst stride
+     * @param iType the i type
+     * @param channels the channels
+     * @param skipChannel the skip channel
+     * @param offsets the offsets
+     * 
+     * @return the int
+     */
+    private native int ippAffineTransform(
+            double m00, double m01,
+            double m02, double m10,
+            double m11, double m12,
+            Object src, int srcWidth, int srcHeight, int srcStride,
+            Object dst, int dstWidth, int dstHeight, int dstStride,
+            int iType, int channels, boolean skipChannel,
+            int offsets[]);
+}
\ No newline at end of file
diff --git a/awt/java/awt/image/AreaAveragingScaleFilter.java b/awt/java/awt/image/AreaAveragingScaleFilter.java
new file mode 100644
index 0000000..f4933db
--- /dev/null
+++ b/awt/java/awt/image/AreaAveragingScaleFilter.java
@@ -0,0 +1,253 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import java.util.Arrays;
+
+
+/**
+ * The AreaAveragingScaleFilter class scales the source image using
+ * area averaging algorithm. This algorithm provides a source image
+ * with a new image containing the resampled image. 
+ */
+public class AreaAveragingScaleFilter extends ReplicateScaleFilter {
+
+    /** The Constant rgbCM. */
+    private static final ColorModel rgbCM = ColorModel.getRGBdefault();
+    
+    /** The Constant averagingFlags. */
+    private static final int averagingFlags = (ImageConsumer.TOPDOWNLEFTRIGHT |
+            ImageConsumer.COMPLETESCANLINES);
+
+    /** The reset. */
+    private boolean reset = true;   // Flag for used superclass filter
+    
+    /** The inited. */
+    private boolean inited = false; // All data inited
+
+    /** The sum_r. */
+    private int sum_r[]; // Array for average Red samples
+    
+    /** The sum_g. */
+    private int sum_g[]; // Array for average Green samples
+    
+    /** The sum_b. */
+    private int sum_b[]; // Array for average Blue samples
+    
+    /** The sum_a. */
+    private int sum_a[]; // Array for average Alpha samples
+
+    /** The buff. */
+    private int buff[];  // Stride buffer
+    
+    /** The avg factor. */
+    private int avgFactor;  // Global averaging factor
+
+    /** The cached dy. */
+    private int cachedDY;      // Cached number of the destination scanline 
+    
+    /** The cached dv rest. */
+    private int cachedDVRest;  // Cached value of rest src scanlines for sum 
+                               // pixel samples 
+                               // Because data if transfering by whole scanlines
+                               // we are caching only Y coordinate values
+    
+    /**
+     * Instantiates a new AreaAveragingScaleFilter object which scales
+     * a source image with the specified width and height.
+     * 
+     * @param width the scaled width of the image.
+     * @param height the scaled height of the image.
+     */
+    public AreaAveragingScaleFilter(int width, int height) {
+        super(width, height);
+    }
+
+    @Override
+    public void setPixels(int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize) {
+        if(reset) {
+            super.setPixels(x, y, w, h, model, pixels, off, scansize);
+        } else {
+            setFilteredPixels(x, y, w, h, model, pixels, off, scansize);
+        }
+    }
+
+    @Override
+    public void setPixels(int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize) {
+        if(reset) {
+            super.setPixels(x, y, w, h, model, pixels, off, scansize);
+        } else {
+            setFilteredPixels(x, y, w, h, model, pixels, off, scansize);
+        }
+    }
+
+    @Override
+    public void setHints(int hints) {
+        super.setHints(hints);
+        reset = ((hints & averagingFlags) != averagingFlags);
+    }
+
+    /**
+     * This method implements the Area Averaging Scale filter.
+     * The description of algorithm is presented in Java API Specification.
+     * 
+     * Arrays sum_r, sum_g, sum_b, sum_a have length equals width of destination
+     * image. In each array's element is accumulating pixel's component values,
+     * proportional to the area which source pixels will occupy in destination
+     * image. Then that values will divide by Global averaging
+     * factor (area of the destination image) for receiving
+     * average values of destination pixels.
+     * 
+     * @param x - Src pixels X coordinate
+     * @param y - Src pixels Y coordinate
+     * @param w - width of the area of Src pixels
+     * @param h - height of the area of Src pixels
+     * @param model - Color Model of Src pixels
+     * @param pixels - array of Src pixels
+     * @param off - offset into the Src pixels array
+     * @param scansize - length of scanline in the pixels array
+     */
+    private void setFilteredPixels(int x, int y, int w, int h, ColorModel model, Object pixels, int off, int scansize){
+        if(!inited){
+            initialize();
+        }
+
+        int srcX, srcY, dx, dy;
+        int svRest, dvRest, shRest, dhRest, vDif, hDif;
+
+        if(y == 0){
+            dy = 0;
+            dvRest = srcHeight;
+        }else{
+            dy = cachedDY;
+            dvRest = cachedDVRest;
+        }
+
+        srcY = y;
+        svRest = destHeight;
+
+        int srcOff = off;
+        while (srcY < y + h) {
+            if (svRest < dvRest) {
+                vDif = svRest;
+            } else {
+                vDif = dvRest;
+            }
+
+            srcX = 0;
+            dx = 0;
+            shRest = destWidth;
+            dhRest = srcWidth;
+            while (srcX < w) {
+                if (shRest < dhRest) {
+                    hDif = shRest;
+                } else {
+                    hDif = dhRest;
+                }
+                int avg = hDif * vDif; // calculation of contribution factor
+
+                int rgb, pix;
+                if (pixels instanceof int[]) {
+                    pix = ((int[]) pixels)[srcOff + srcX];
+                } else {
+                    pix = ((byte[]) pixels)[srcOff + srcX] & 0xff;
+                }
+
+                rgb = model.getRGB(pix);
+                int a = rgb >>> 24;
+                int r = (rgb >> 16) & 0xff;
+                int g = (rgb >> 8) & 0xff;
+                int b = rgb & 0xff;
+
+                // accumulating pixel's component values
+                sum_a[dx] += a * avg;
+                sum_r[dx] += r * avg;
+                sum_g[dx] += g * avg;
+                sum_b[dx] += b * avg;
+
+                shRest -= hDif;
+                dhRest -= hDif;
+
+                if (shRest == 0) {
+                    srcX++;
+                    shRest = destWidth;
+                }
+
+                if (dhRest == 0) {
+                    dx++;
+                    dhRest = srcWidth;
+                }
+            }
+
+            svRest -= vDif;
+            dvRest -= vDif;
+
+            if (svRest == 0) {
+                svRest = destHeight;
+                srcY++;
+                srcOff += scansize;
+            }
+
+            if (dvRest == 0) {
+                // averaging destination pixel's values
+                for(int i = 0; i < destWidth; i++){
+                    int a = (sum_a[i] / avgFactor) & 0xff;
+                    int r = (sum_r[i] / avgFactor) & 0xff;
+                    int g = (sum_g[i] / avgFactor) & 0xff;
+                    int b = (sum_b[i] / avgFactor) & 0xff;
+                    int frgb = (a << 24) | (r << 16) | (g << 8) | b;
+                    buff[i] = frgb;
+                }
+                consumer.setPixels(0, dy, destWidth, 1, rgbCM, buff, 0,
+                        destWidth);
+                dy++;
+                dvRest = srcHeight;
+                Arrays.fill(sum_a, 0);
+                Arrays.fill(sum_r, 0);
+                Arrays.fill(sum_g, 0);
+                Arrays.fill(sum_b, 0);
+            }
+
+        }
+
+        cachedDY = dy;
+        cachedDVRest = dvRest;
+
+    }
+
+    /**
+     * Initialization of the auxiliary data.
+     */
+    private void initialize(){
+
+        sum_a = new int[destWidth]; 
+        sum_r = new int[destWidth]; 
+        sum_g = new int[destWidth]; 
+        sum_b = new int[destWidth]; 
+
+        buff = new int[destWidth];  
+        outpixbuf = buff;
+        avgFactor = srcWidth * srcHeight; 
+
+        inited = true;
+    }
+}
+
diff --git a/awt/java/awt/image/AwtImageBackdoorAccessorImpl.java b/awt/java/awt/image/AwtImageBackdoorAccessorImpl.java
new file mode 100644
index 0000000..ce85ddd
--- /dev/null
+++ b/awt/java/awt/image/AwtImageBackdoorAccessorImpl.java
@@ -0,0 +1,153 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ * Created on 23.11.2005
+ *
+ */
+package java.awt.image;
+
+import java.awt.Image;
+import java.awt.image.DataBuffer;
+import java.awt.image.DataBufferByte;
+import java.awt.image.DataBufferDouble;
+import java.awt.image.DataBufferFloat;
+import java.awt.image.DataBufferInt;
+import java.awt.image.DataBufferShort;
+import java.awt.image.DataBufferUShort;
+
+import org.apache.harmony.awt.gl.AwtImageBackdoorAccessor;
+import org.apache.harmony.awt.gl.GLVolatileImage;
+import org.apache.harmony.awt.gl.Surface;
+import org.apache.harmony.awt.gl.image.DataBufferListener;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * This class not part of public API. It useful for receiving package private
+ * data from other packages.
+ */
+class AwtImageBackdoorAccessorImpl extends AwtImageBackdoorAccessor {
+
+    static void init(){
+        inst = new AwtImageBackdoorAccessorImpl();
+    }
+
+    @Override
+    public Surface getImageSurface(Image image) {
+        if (image instanceof BufferedImage){
+            return ((BufferedImage)image).getImageSurface();
+        } else if (image instanceof GLVolatileImage){
+            return ((GLVolatileImage)image).getImageSurface();
+        }
+        return null;
+    }
+
+    @Override
+    public boolean isGrayPallete(IndexColorModel icm){
+        return icm.isGrayPallete();
+    }
+
+    @Override
+    public Object getData(DataBuffer db) {
+        if (db instanceof DataBufferByte){
+            return ((DataBufferByte)db).getData();
+        } else if (db instanceof DataBufferUShort){
+            return ((DataBufferUShort)db).getData();
+        } else if (db instanceof DataBufferShort){
+            return ((DataBufferShort)db).getData();
+        } else if (db instanceof DataBufferInt){
+            return ((DataBufferInt)db).getData();
+        } else if (db instanceof DataBufferFloat){
+            return ((DataBufferFloat)db).getData();
+        } else if (db instanceof DataBufferDouble){
+            return ((DataBufferDouble)db).getData();
+        } else {
+            // awt.235=Wrong Data Buffer type : {0}
+            throw new IllegalArgumentException(Messages.getString("awt.235", //$NON-NLS-1$
+                    db.getClass()));
+        }
+    }
+
+    @Override
+    public int[] getDataInt(DataBuffer db) {
+        if (db instanceof DataBufferInt){
+            return ((DataBufferInt)db).getData();
+        }
+        return null;
+    }
+
+    @Override
+    public byte[] getDataByte(DataBuffer db) {
+        if (db instanceof DataBufferByte){
+            return ((DataBufferByte)db).getData();
+        }
+        return null;
+    }
+
+    @Override
+    public short[] getDataShort(DataBuffer db) {
+        if (db instanceof DataBufferShort){
+            return ((DataBufferShort)db).getData();
+        }
+        return null;
+    }
+
+    @Override
+    public short[] getDataUShort(DataBuffer db) {
+        if (db instanceof DataBufferUShort){
+            return ((DataBufferUShort)db).getData();
+        }
+        return null;
+    }
+
+    @Override
+    public double[] getDataDouble(DataBuffer db) {
+        if (db instanceof DataBufferDouble){
+            return ((DataBufferDouble)db).getData();
+        }
+        return null;
+    }
+
+    @Override
+    public float[] getDataFloat(DataBuffer db) {
+        if (db instanceof DataBufferFloat){
+            return ((DataBufferFloat)db).getData();
+        }
+        return null;
+    }
+
+    @Override
+    public void addDataBufferListener(DataBuffer db, DataBufferListener listener) {
+        db.addDataBufferListener(listener);
+    }
+
+    @Override
+    public void removeDataBufferListener(DataBuffer db) {
+        db.removeDataBufferListener();
+    }
+
+    @Override
+    public void validate(DataBuffer db) {
+        db.validate();
+    }
+
+    @Override
+    public void releaseData(DataBuffer db) {
+        db.releaseData();
+    }
+}
diff --git a/awt/java/awt/image/BandCombineOp.java b/awt/java/awt/image/BandCombineOp.java
new file mode 100644
index 0000000..cd77a21
--- /dev/null
+++ b/awt/java/awt/image/BandCombineOp.java
@@ -0,0 +1,610 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ *
+ * @date: Sep 20, 2005
+ */
+
+package java.awt.image;
+
+import java.awt.*;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.util.Arrays;
+
+import org.apache.harmony.awt.gl.AwtImageBackdoorAccessor;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The BandCombineOp class translates coordinates from 
+ * coordinates in the source Raster to coordinates in 
+ * the destination Raster by an arbitrary linear combination 
+ * of the bands in a source Raster, using a specified matrix.
+ * The number of bands in the matrix should equal to 
+ * the number of bands in the source Raster plus 1.
+ */
+public class BandCombineOp implements RasterOp {
+    
+    /** The Constant offsets3c. */
+    static final int offsets3c[] = {16, 8, 0};
+    
+    /** The Constant offsets4ac. */
+    static final int offsets4ac[] = {16, 8, 0, 24};
+    
+    /** The Constant masks3c. */
+    static final int masks3c[] = {0xFF0000, 0xFF00, 0xFF};
+    
+    /** The Constant masks4ac. */
+    static final int masks4ac[] = {0xFF0000, 0xFF00, 0xFF, 0xFF000000};
+    
+    /** The Constant piOffsets. */
+    private static final int piOffsets[] = {0, 1, 2};
+    
+    /** The Constant piInvOffsets. */
+    private static final int piInvOffsets[] = {2, 1, 0};
+
+    /** The Constant TYPE_BYTE3C. */
+    private static final int TYPE_BYTE3C = 0;
+    
+    /** The Constant TYPE_BYTE4AC. */
+    private static final int TYPE_BYTE4AC = 1;
+    
+    /** The Constant TYPE_USHORT3C. */
+    private static final int TYPE_USHORT3C = 2;
+    
+    /** The Constant TYPE_SHORT3C. */
+    private static final int TYPE_SHORT3C = 3;
+
+    /** The mx width. */
+    private int mxWidth;
+    
+    /** The mx height. */
+    private int mxHeight;
+    
+    /** The matrix. */
+    private float matrix[][];
+    
+    /** The r hints. */
+    private RenderingHints rHints;
+
+    static {
+        // XXX - todo
+        //System.loadLibrary("imageops");
+    }
+
+    /**
+     * Instantiates a new BandCombineOp object with the specified
+     * matrix.
+     * 
+     * @param matrix the specified matrix for band combining.
+     * @param hints the RenderingHints.
+     */
+    public BandCombineOp(float matrix[][], RenderingHints hints) {
+        this.mxHeight = matrix.length;
+        this.mxWidth = matrix[0].length;
+        this.matrix = new float[mxHeight][mxWidth];
+
+        for (int i=0; i<mxHeight; i++){
+            System.arraycopy(matrix[i], 0, this.matrix[i], 0, mxWidth);
+        }
+
+        this.rHints = hints;
+    }
+
+    public final RenderingHints getRenderingHints(){
+        return this.rHints;
+    }
+
+    /**
+     * Gets the matrix associated with this BandCombineOp object.
+     * 
+     * @return the matrix associated with this BandCombineOp object.
+     */
+    public final float[][] getMatrix() {
+        float res[][] = new float[mxHeight][mxWidth];
+
+        for (int i=0; i<mxHeight; i++) {
+            System.arraycopy(matrix[i], 0, res[i], 0, mxWidth);
+        }
+
+        return res;
+    }
+
+    public final Point2D getPoint2D (Point2D srcPoint, Point2D dstPoint) {
+        if (dstPoint == null) {
+            dstPoint = new Point2D.Float();
+        }
+
+        dstPoint.setLocation(srcPoint);
+        return dstPoint;
+    }
+
+    public final Rectangle2D getBounds2D(Raster src){
+        return src.getBounds();
+    }
+
+    public WritableRaster createCompatibleDestRaster (Raster src) {
+        int numBands = src.getNumBands();
+        if (mxWidth != numBands && mxWidth != (numBands+1) || numBands != mxHeight) {
+            // awt.254=Number of bands in the source raster ({0}) is
+            //          incompatible with the matrix [{1}x{2}]
+            throw new IllegalArgumentException(Messages.getString("awt.254", //$NON-NLS-1$
+                    new Object[]{numBands, mxWidth, mxHeight}));
+        }
+
+        return src.createCompatibleWritableRaster(src.getWidth(), src.getHeight());
+    }
+
+    public WritableRaster filter(Raster src, WritableRaster dst) {
+        int numBands = src.getNumBands();
+
+        if (mxWidth != numBands && mxWidth != (numBands+1)) {
+            // awt.254=Number of bands in the source raster ({0}) is
+            //          incompatible with the matrix [{1}x{2}]
+            throw new IllegalArgumentException(
+                    Messages.getString("awt.254", //$NON-NLS-1$
+                    new Object[]{numBands, mxWidth, mxHeight}));
+        }
+
+        if (dst == null) {
+            dst = createCompatibleDestRaster(src);
+        } else if (dst.getNumBands() != mxHeight) {
+            // awt.255=Number of bands in the destination raster ({0}) is incompatible with the matrix [{1}x{2}]
+            throw new IllegalArgumentException(Messages.getString("awt.255", //$NON-NLS-1$
+                    new Object[]{dst.getNumBands(), mxWidth, mxHeight}));
+        }
+
+        // XXX - todo
+        //if (ippFilter(src, dst) != 0)
+        if (verySlowFilter(src, dst) != 0) {
+            // awt.21F=Unable to transform source
+            throw new ImagingOpException (Messages.getString("awt.21F")); //$NON-NLS-1$
+        }
+
+        return dst;
+    }
+
+    /**
+     * The Class SampleModelInfo.
+     */
+    private static final class SampleModelInfo {
+        
+        /** The channels. */
+        int channels;
+        
+        /** The channels order. */
+        int channelsOrder[];
+        
+        /** The stride. */
+        int stride;
+    }
+
+    /**
+     * Check sample model.
+     * 
+     * @param sm the sm
+     * 
+     * @return the sample model info
+     */
+    private final SampleModelInfo checkSampleModel(SampleModel sm) {
+        SampleModelInfo ret = new SampleModelInfo();
+
+        if (sm instanceof PixelInterleavedSampleModel) {
+            // Check PixelInterleavedSampleModel
+            if (sm.getDataType() != DataBuffer.TYPE_BYTE) {
+                return null;
+            }
+
+            ret.channels = sm.getNumBands();
+            ret.stride = ((ComponentSampleModel) sm).getScanlineStride();
+            ret.channelsOrder = ((ComponentSampleModel) sm).getBandOffsets();
+
+        } else if (sm instanceof SinglePixelPackedSampleModel) {
+            // Check SinglePixelPackedSampleModel
+            SinglePixelPackedSampleModel sppsm1 = (SinglePixelPackedSampleModel) sm;
+
+            ret.channels = sppsm1.getNumBands();
+            if (sppsm1.getDataType() != DataBuffer.TYPE_INT) {
+                return null;
+            }
+
+            // Check sample models
+            for (int i=0; i<ret.channels; i++) {
+                if (sppsm1.getSampleSize(i) != 8) {
+                    return null;
+                }
+            }
+
+            ret.channelsOrder = new int[ret.channels];
+            int bitOffsets[] = sppsm1.getBitOffsets();
+            for (int i=0; i<ret.channels; i++) {
+                if (bitOffsets[i] % 8 != 0) {
+                    return null;
+                }
+
+                ret.channelsOrder[i] = bitOffsets[i] / 8;
+            }
+
+            ret.channels = 4;
+            ret.stride = sppsm1.getScanlineStride() * 4;
+        } else {
+            return null;
+        }
+
+        return ret;
+    }
+
+    /**
+     * Slow filter.
+     * 
+     * @param src the src
+     * @param dst the dst
+     * 
+     * @return the int
+     */
+    private final int slowFilter(Raster src, WritableRaster dst) {
+        int res = 0;
+
+        SampleModelInfo srcInfo, dstInfo;
+        int offsets[] = null;
+
+        srcInfo = checkSampleModel(src.getSampleModel());
+        dstInfo = checkSampleModel(dst.getSampleModel());
+        if (srcInfo == null || dstInfo == null) {
+            return verySlowFilter(src, dst);
+        }
+
+        // Fill offsets if there's a child raster
+        if (src.getParent() != null || dst.getParent() != null) {
+            if (src.getSampleModelTranslateX() != 0 || src.getSampleModelTranslateY() != 0 ||
+                    dst.getSampleModelTranslateX() != 0 || dst.getSampleModelTranslateY() != 0) {
+                offsets = new int[4];
+                offsets[0] = -src.getSampleModelTranslateX() + src.getMinX();
+                offsets[1] = -src.getSampleModelTranslateY() + src.getMinY();
+                offsets[2] = -dst.getSampleModelTranslateX() + dst.getMinX();
+                offsets[3] = -dst.getSampleModelTranslateY() + dst.getMinY();
+            }
+        }
+
+        int rmxWidth = (srcInfo.channels+1); // width of the reordered matrix
+        float reorderedMatrix[] = new float[rmxWidth*dstInfo.channels];
+        for (int j=0; j<dstInfo.channels; j++) {
+            if (j >= dstInfo.channelsOrder.length) {
+                continue;
+            }
+
+            for (int i=0; i<srcInfo.channels; i++) {
+                if (i >= srcInfo.channelsOrder.length) {
+                    break;
+                }
+
+                reorderedMatrix[dstInfo.channelsOrder[j]*rmxWidth + srcInfo.channelsOrder[i]] =
+                        matrix[j][i];
+            }
+            if (mxWidth == rmxWidth) {
+                reorderedMatrix[(dstInfo.channelsOrder[j]+1)*rmxWidth - 1] = matrix[j][mxWidth-1];
+            }
+        }
+
+        Object srcData, dstData;
+        AwtImageBackdoorAccessor dbAccess = AwtImageBackdoorAccessor.getInstance();
+        try {
+            srcData = dbAccess.getData(src.getDataBuffer());
+            dstData = dbAccess.getData(dst.getDataBuffer());
+        } catch (IllegalArgumentException e) {
+            return -1; // Unknown data buffer type
+        }
+
+        simpleCombineBands(
+                srcData, src.getWidth(), src.getHeight(), srcInfo.stride, srcInfo.channels,
+                dstData, dstInfo.stride, dstInfo.channels,
+                reorderedMatrix, offsets
+        );
+
+        return res;
+    }
+
+    /**
+     * Very slow filter.
+     * 
+     * @param src the src
+     * @param dst the dst
+     * 
+     * @return the int
+     */
+    private int verySlowFilter(Raster src, WritableRaster dst) {
+        int numBands = src.getNumBands();
+
+        int srcMinX = src.getMinX();
+        int srcY = src.getMinY();
+
+        int dstMinX = dst.getMinX();
+        int dstY = dst.getMinY();
+
+        int dX = src.getWidth();//< dst.getWidth() ? src.getWidth() : dst.getWidth();
+        int dY = src.getHeight();//< dst.getHeight() ? src.getHeight() : dst.getHeight();
+
+        float sample;
+        int srcPixels[] = new int[numBands*dX*dY];
+        int dstPixels[] = new int[mxHeight*dX*dY];
+
+        srcPixels = src.getPixels(srcMinX, srcY, dX, dY, srcPixels);
+
+        if (numBands == mxWidth) {
+            for (int i=0, j=0; i<srcPixels.length; i+=numBands) {
+                for (int dstB = 0; dstB < mxHeight; dstB++) {
+                    sample = 0f;
+                    for (int srcB = 0; srcB < numBands; srcB++) {
+                        sample += matrix[dstB][srcB] * srcPixels[i+srcB];
+                    }
+                    dstPixels[j++] = (int) sample;
+                }
+            }
+        } else {
+            for (int i=0, j=0; i<srcPixels.length; i+=numBands) {
+                for (int dstB = 0; dstB < mxHeight; dstB++) {
+                    sample = 0f;
+                    for (int srcB = 0; srcB < numBands; srcB++) {
+                        sample += matrix[dstB][srcB] * srcPixels[i+srcB];
+                    }
+                    dstPixels[j++] = (int) (sample + matrix[dstB][numBands]);
+                }
+            }
+        }
+
+        dst.setPixels(dstMinX, dstY, dX, dY, dstPixels);
+
+        return 0;
+    }
+
+    //TODO remove when method is used
+    /**
+     * Ipp filter.
+     * 
+     * @param src the src
+     * @param dst the dst
+     * 
+     * @return the int
+     */
+    @SuppressWarnings("unused")
+    private int ippFilter(Raster src, WritableRaster dst) {
+        boolean invertChannels;
+        boolean inPlace = (src == dst);
+        int type;
+        int srcStride, dstStride;
+        int offsets[] = null;
+
+        int srcBands = src.getNumBands();
+        int dstBands = dst.getNumBands();
+
+        if (
+                dstBands != 3 ||
+                (srcBands != 3 &&
+                !(srcBands == 4 &&
+                  matrix[0][3] == 0 &&
+                  matrix[1][3] == 0 &&
+                  matrix[2][3] == 0)
+                )
+        ) {
+            return slowFilter(src, dst);
+        }
+
+        SampleModel srcSM = src.getSampleModel();
+        SampleModel dstSM = dst.getSampleModel();
+
+        if (
+                srcSM instanceof SinglePixelPackedSampleModel &&
+                dstSM instanceof SinglePixelPackedSampleModel
+        ) {
+            // Check SinglePixelPackedSampleModel
+            SinglePixelPackedSampleModel sppsm1 = (SinglePixelPackedSampleModel) srcSM;
+            SinglePixelPackedSampleModel sppsm2 = (SinglePixelPackedSampleModel) dstSM;
+
+            if (
+                    sppsm1.getDataType() != DataBuffer.TYPE_INT ||
+                    sppsm2.getDataType() != DataBuffer.TYPE_INT
+            ) {
+                return slowFilter(src, dst);
+            }
+
+            // Check sample models
+            if (
+                    !Arrays.equals(sppsm2.getBitOffsets(), offsets3c) ||
+                    !Arrays.equals(sppsm2.getBitMasks(), masks3c)
+            ) {
+                return slowFilter(src, dst);
+            }
+
+            if (srcBands == 3) {
+                if (
+                        !Arrays.equals(sppsm1.getBitOffsets(), offsets3c) ||
+                        !Arrays.equals(sppsm1.getBitMasks(), masks3c)
+                ) {
+                    return slowFilter(src, dst);
+                }
+            } else if (srcBands == 4) {
+                if (
+                        !Arrays.equals(sppsm1.getBitOffsets(), offsets4ac) ||
+                        !Arrays.equals(sppsm1.getBitMasks(), masks4ac)
+                ) {
+                    return slowFilter(src, dst);
+                }
+            }
+
+            type = TYPE_BYTE4AC;
+            invertChannels = true;
+
+            srcStride = sppsm1.getScanlineStride() * 4;
+            dstStride = sppsm2.getScanlineStride() * 4;
+        } else if (
+            srcSM instanceof PixelInterleavedSampleModel &&
+            dstSM instanceof PixelInterleavedSampleModel
+        ) {
+            if (srcBands != 3) {
+                return slowFilter(src, dst);
+            }
+
+            int srcDataType = srcSM.getDataType();
+
+            switch (srcDataType) {
+                case DataBuffer.TYPE_BYTE:
+                    type = TYPE_BYTE3C;
+                    break;
+                case DataBuffer.TYPE_USHORT:
+                    type = TYPE_USHORT3C;
+                    break;
+                case DataBuffer.TYPE_SHORT:
+                    type = TYPE_SHORT3C;
+                    break;
+                default:
+                    return slowFilter(src, dst);
+            }
+
+            // Check PixelInterleavedSampleModel
+            PixelInterleavedSampleModel pism1 = (PixelInterleavedSampleModel) srcSM;
+            PixelInterleavedSampleModel pism2 = (PixelInterleavedSampleModel) dstSM;
+
+            if (
+                    srcDataType != pism2.getDataType() ||
+                    pism1.getPixelStride() != 3 ||
+                    pism2.getPixelStride() != 3 ||
+                    !Arrays.equals(pism1.getBandOffsets(), pism2.getBandOffsets())
+            ) {
+                return slowFilter(src, dst);
+            }
+
+            if (Arrays.equals(pism1.getBandOffsets(), piInvOffsets)) {
+                invertChannels = true;
+            } else if (Arrays.equals(pism1.getBandOffsets(), piOffsets)) {
+                invertChannels = false;
+            } else {
+                return slowFilter(src, dst);
+            }
+
+            int dataTypeSize = DataBuffer.getDataTypeSize(srcDataType) / 8;
+
+            srcStride = pism1.getScanlineStride() * dataTypeSize;
+            dstStride = pism2.getScanlineStride() * dataTypeSize;
+        } else { // XXX - todo - IPP allows support for planar data also
+            return slowFilter(src, dst);
+        }
+
+        // Fill offsets if there's a child raster
+        if (src.getParent() != null || dst.getParent() != null) {
+            if (src.getSampleModelTranslateX() != 0 || src.getSampleModelTranslateY() != 0 ||
+               dst.getSampleModelTranslateX() != 0 || dst.getSampleModelTranslateY() != 0) {
+                offsets = new int[4];
+                offsets[0] = -src.getSampleModelTranslateX() + src.getMinX();
+                offsets[1] = -src.getSampleModelTranslateY() + src.getMinY();
+                offsets[2] = -dst.getSampleModelTranslateX() + dst.getMinX();
+                offsets[3] = -dst.getSampleModelTranslateY() + dst.getMinY();
+            }
+        }
+
+        Object srcData, dstData;
+        AwtImageBackdoorAccessor dbAccess = AwtImageBackdoorAccessor.getInstance();
+        try {
+            srcData = dbAccess.getData(src.getDataBuffer());
+            dstData = dbAccess.getData(dst.getDataBuffer());
+        } catch (IllegalArgumentException e) {
+            return -1; // Unknown data buffer type
+        }
+
+        float ippMatrix[] = new float[12];
+
+        if (invertChannels) {
+            // IPP treats big endian integers like BGR, so we have to
+            // swap columns 1 and 3 and rows 1 and 3
+            for (int i = 0; i < mxHeight; i++) {
+                ippMatrix[i*4] = matrix[2-i][2];
+                ippMatrix[i*4+1] = matrix[2-i][1];
+                ippMatrix[i*4+2] = matrix[2-i][0];
+
+                if (mxWidth == 4) {
+                    ippMatrix[i*4+3] = matrix[2-i][3];
+                } else if (mxWidth == 5) {
+                    ippMatrix[i*4+3] = matrix[2-i][4];
+                }
+            }
+        } else {
+            for (int i = 0; i < mxHeight; i++) {
+                ippMatrix[i*4] = matrix[i][0];
+                ippMatrix[i*4+1] = matrix[i][1];
+                ippMatrix[i*4+2] = matrix[i][2];
+
+                if (mxWidth == 4) {
+                    ippMatrix[i*4+3] = matrix[i][3];
+                } else if (mxWidth == 5) {
+                    ippMatrix[i*4+3] = matrix[i][4];
+                }
+            }
+        }
+
+        return ippColorTwist(
+                srcData, src.getWidth(), src.getHeight(), srcStride,
+                dstData, dst.getWidth(), dst.getHeight(), dstStride,
+                ippMatrix, type, offsets, inPlace);
+    }
+
+    /**
+     * Ipp color twist.
+     * 
+     * @param srcData the src data
+     * @param srcWidth the src width
+     * @param srcHeight the src height
+     * @param srcStride the src stride
+     * @param dstData the dst data
+     * @param dstWidth the dst width
+     * @param dstHeight the dst height
+     * @param dstStride the dst stride
+     * @param ippMatrix the ipp matrix
+     * @param type the type
+     * @param offsets the offsets
+     * @param inPlace the in place
+     * 
+     * @return the int
+     */
+    private final native int ippColorTwist(
+            Object srcData, int srcWidth, int srcHeight, int srcStride,
+            Object dstData, int dstWidth, int dstHeight, int dstStride,
+            float ippMatrix[], int type, int offsets[], boolean inPlace
+    );
+
+    /**
+     * Simple combine bands.
+     * 
+     * @param srcData the src data
+     * @param srcWidth the src width
+     * @param srcHeight the src height
+     * @param srcStride the src stride
+     * @param srcChannels the src channels
+     * @param dstData the dst data
+     * @param dstStride the dst stride
+     * @param dstChannels the dst channels
+     * @param m the m
+     * @param offsets the offsets
+     * 
+     * @return the int
+     */
+    private final native int simpleCombineBands(
+            Object srcData, int srcWidth, int srcHeight, int srcStride, int srcChannels,
+            Object dstData, int dstStride, int dstChannels,
+            float m[], int offsets[]
+    );
+}
diff --git a/awt/java/awt/image/BandedSampleModel.java b/awt/java/awt/image/BandedSampleModel.java
new file mode 100644
index 0000000..392e44c
--- /dev/null
+++ b/awt/java/awt/image/BandedSampleModel.java
@@ -0,0 +1,426 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The BandedSampleModel class provides samples of pixels in an image 
+ * which is stored in a band interleaved method. Each pixel's sample 
+ * takes one data element of the DataBuffer. The pixel stride for a 
+ * BandedSampleModel is one. 
+ */
+public final class BandedSampleModel extends ComponentSampleModel {
+
+    /**
+     * Creates the indices.
+     * 
+     * @param numBands the num bands
+     * 
+     * @return the int[]
+     */
+    private static int[] createIndices(int numBands) {
+        int indices[] = new int[numBands];
+        for (int i = 0; i < numBands; i++) {
+            indices[i] = i;
+        }
+        return indices;
+    }
+
+    /**
+     * Creates the offsets.
+     * 
+     * @param numBands the num bands
+     * 
+     * @return the int[]
+     */
+    private static int[] createOffsets(int numBands) {
+        int offsets[] = new int[numBands];
+        for (int i = 0; i < numBands; i++) {
+            offsets[i] = 0;
+        }
+        return offsets;
+    }
+
+    /**
+     * Instantiates a new BandedSampleModel object with the specified 
+     * data type of samples, the width, height and bands number
+     * of image data.
+     * 
+     * @param dataType the data type of samples.
+     * @param w the width of image data.
+     * @param h the height of image data.
+     * @param numBands the number of bands.
+     */
+    public BandedSampleModel(int dataType, int w, int h, int numBands) {
+        this(dataType, w, h, w, BandedSampleModel.createIndices(numBands),
+                BandedSampleModel.createOffsets(numBands));
+    }
+
+    /**
+     * Instantiates a new BandedSampleModel object with the specified 
+     * data type of samples, the width, height and bands number
+     * of image data.
+     * 
+     * @param dataType the data type of samples.
+     * @param w the width of image data.
+     * @param h the height of image data.
+     * @param scanlineStride the scanline stride of the of the image data.
+     * @param bankIndices the array of the bank indecies.
+     * @param bandOffsets the array of the band offsets.
+     */
+    public BandedSampleModel(int dataType, int w, int h, int scanlineStride,
+            int bankIndices[], int bandOffsets[]) {
+        super(dataType, w, h, 1, scanlineStride, bankIndices, bandOffsets);
+    }
+
+    @Override
+    public SampleModel createCompatibleSampleModel(int w, int h) {
+        return new BandedSampleModel(dataType, w, h, w, bankIndices,
+                bandOffsets);
+    }
+
+    @Override
+    public DataBuffer createDataBuffer() {
+        DataBuffer data = null;
+        int size = scanlineStride * height;
+
+        switch (dataType) {
+        case DataBuffer.TYPE_BYTE:
+            data = new DataBufferByte(size, numBanks);
+            break;
+        case DataBuffer.TYPE_SHORT:
+        case DataBuffer.TYPE_USHORT:
+            data = new DataBufferShort(size, numBanks);
+            break;
+        case DataBuffer.TYPE_INT:
+            data = new DataBufferInt(size, numBanks);
+            break;
+        case DataBuffer.TYPE_FLOAT:
+            data = new DataBufferFloat(size, numBanks);
+            break;
+        case DataBuffer.TYPE_DOUBLE:
+            data = new DataBufferDouble(size, numBanks);
+            break;
+        }
+
+        return data;
+
+    }
+
+    @Override
+    public SampleModel createSubsetSampleModel(int[] bands) {
+        if (bands.length > numBands) {
+            // awt.64=The number of the bands in the subset is greater than the number of bands in the sample model
+            throw new RasterFormatException(Messages.getString("awt.64")); //$NON-NLS-1$
+        }
+
+        int indices[] = new int[bands.length];
+        int offsets[] = new int[bands.length];
+
+        for (int i = 0; i < bands.length; i++) {
+            indices[i] = bankIndices[bands[i]];
+            offsets[i] = bandOffsets[bands[i]];
+        }
+
+        return new BandedSampleModel(dataType, width, height, scanlineStride,
+                indices, offsets);
+    }
+
+    @Override
+    public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
+        switch (dataType) {
+        case DataBuffer.TYPE_BYTE: {
+            byte bdata[];
+
+            if (obj == null) {
+                bdata = new byte[numBands];
+            } else {
+                bdata = (byte[]) obj;
+            }
+
+            for (int i = 0; i < numBands; i++) {
+                bdata[i] = (byte) getSample(x, y, i, data);
+            }
+
+            obj = bdata;
+            break;
+        }
+        case DataBuffer.TYPE_SHORT:
+        case DataBuffer.TYPE_USHORT: {
+            short sdata[];
+
+            if (obj == null) {
+                sdata = new short[numBands];
+            } else {
+                sdata = (short[]) obj;
+            }
+
+            for (int i = 0; i < numBands; i++) {
+                sdata[i] = (short) getSample(x, y, i, data);
+            }
+
+            obj = sdata;
+            break;
+        }
+        case DataBuffer.TYPE_INT: {
+            int idata[];
+
+            if (obj == null) {
+                idata = new int[numBands];
+            } else {
+                idata = (int[]) obj;
+            }
+
+            for (int i = 0; i < numBands; i++) {
+                idata[i] = getSample(x, y, i, data);
+            }
+
+            obj = idata;
+            break;
+        }
+        case DataBuffer.TYPE_FLOAT: {
+            float fdata[];
+
+            if (obj == null) {
+                fdata = new float[numBands];
+            } else {
+                fdata = (float[]) obj;
+            }
+
+            for (int i = 0; i < numBands; i++) {
+                fdata[i] = getSampleFloat(x, y, i, data);
+            }
+
+            obj = fdata;
+            break;
+        }
+        case DataBuffer.TYPE_DOUBLE: {
+            double ddata[];
+
+            if (obj == null) {
+                ddata = new double[numBands];
+            } else {
+                ddata = (double[]) obj;
+            }
+
+            for (int i = 0; i < numBands; i++) {
+                ddata[i] = getSampleDouble(x, y, i, data);
+            }
+
+            obj = ddata;
+            break;
+        }
+        }
+
+        return obj;
+    }
+
+    @Override
+    public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
+        int pixel[];
+        if (iArray == null) {
+            pixel = new int[numBands];
+        } else {
+            pixel = iArray;
+        }
+
+        for (int i = 0; i < numBands; i++) {
+            pixel[i] = getSample(x, y, i, data);
+        }
+
+        return pixel;
+    }
+
+    @Override
+    public int getSample(int x, int y, int b, DataBuffer data) {
+        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+
+        return data.getElem(bankIndices[b], y * scanlineStride + x +
+               bandOffsets[b]);
+    }
+
+    @Override
+    public double getSampleDouble(int x, int y, int b, DataBuffer data) {
+        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+
+        return data.getElemDouble(bankIndices[b], y * scanlineStride + x +
+               bandOffsets[b]);
+    }
+
+    @Override
+    public float getSampleFloat(int x, int y, int b, DataBuffer data) {
+        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+
+        return data.getElemFloat(bankIndices[b], y * scanlineStride + x +
+               bandOffsets[b]);
+    }
+
+    @Override
+    public int[] getSamples(int x, int y, int w, int h, int b, int iArray[],
+            DataBuffer data) {
+        int samples[];
+        int idx = 0;
+
+        if (iArray == null) {
+            samples = new int[w * h];
+        } else {
+            samples = iArray;
+        }
+
+        for (int i = y; i < y + h; i++) {
+            for (int j = x; j < x + w; j++) {
+                samples[idx++] = getSample(j, i, b, data);
+            }
+        }
+
+        return samples;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = super.hashCode();
+        int tmp = hash >>> 8;
+        hash <<= 8;
+        hash |= tmp;
+
+        return hash ^ 0x55;
+    }
+
+    @Override
+    public void setDataElements(int x, int y, Object obj, DataBuffer data) {
+        switch (dataType) {
+        case DataBuffer.TYPE_BYTE:
+            byte bdata[] = (byte[]) obj;
+            for (int i = 0; i < numBands; i++) {
+                setSample(x, y, i, bdata[i] & 0xff, data);
+            }
+            break;
+
+        case DataBuffer.TYPE_SHORT:
+        case DataBuffer.TYPE_USHORT:
+            short sdata[] = (short[]) obj;
+            for (int i = 0; i < numBands; i++) {
+                setSample(x, y, i, sdata[i] & 0xffff, data);
+            }
+            break;
+
+        case DataBuffer.TYPE_INT:
+            int idata[] = (int[]) obj;
+            for (int i = 0; i < numBands; i++) {
+                setSample(x, y, i, idata[i], data);
+            }
+            break;
+
+        case DataBuffer.TYPE_FLOAT:
+            float fdata[] = (float[]) obj;
+            for (int i = 0; i < numBands; i++) {
+                setSample(x, y, i, fdata[i], data);
+            }
+            break;
+
+        case DataBuffer.TYPE_DOUBLE:
+            double ddata[] = (double[]) obj;
+            for (int i = 0; i < numBands; i++) {
+                setSample(x, y, i, ddata[i], data);
+            }
+            break;
+        }
+    }
+
+    @Override
+    public void setPixel(int x, int y, int iArray[], DataBuffer data) {
+        for (int i = 0; i < numBands; i++) {
+            setSample(x, y, i, iArray[i], data);
+        }
+    }
+
+    @Override
+    public void setPixels(int x, int y, int w, int h, int iArray[],
+            DataBuffer data) {
+        int idx = 0;
+
+        for (int i = y; i < y + h; i++) {
+            for (int j = x; j < x + w; j++) {
+                for (int n = 0; n < numBands; n++) {
+                    setSample(j, i, n, iArray[idx++], data);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void setSample(int x, int y, int b, double s, DataBuffer data) {
+        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+
+        data.setElemDouble(bankIndices[b], y * scanlineStride + x +
+               bandOffsets[b], s);
+    }
+
+    @Override
+    public void setSample(int x, int y, int b, float s, DataBuffer data) {
+        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+
+        data.setElemFloat(bankIndices[b], y * scanlineStride + x +
+               bandOffsets[b], s);
+    }
+
+    @Override
+    public void setSample(int x, int y, int b, int s, DataBuffer data) {
+        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+
+        data.setElem(bankIndices[b], y * scanlineStride + x +
+                       bandOffsets[b], s);
+    }
+
+    @Override
+    public void setSamples(int x, int y, int w, int h, int b, int iArray[],
+            DataBuffer data) {
+        int idx = 0;
+
+        for (int i = y; i < y + h; i++) {
+            for (int j = x; j < x + w; j++) {
+                setSample(j, i, b, iArray[idx++], data);
+            }
+        }
+
+    }
+
+}
+
diff --git a/awt/java/awt/image/BufferStrategy.java b/awt/java/awt/image/BufferStrategy.java
new file mode 100644
index 0000000..e0508f0
--- /dev/null
+++ b/awt/java/awt/image/BufferStrategy.java
@@ -0,0 +1,72 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import java.awt.BufferCapabilities;
+import java.awt.Graphics;
+
+/**
+ * The BufferStrategy abstract class provides an opportunity 
+ * to organize the buffers for a Canvas or Window. The BufferStrategy
+ * implementation depends on hardware and software limitations.
+ * These limitations are detectible through the capabilities 
+ * object which can be obtained by the GraphicsConfiguration of the Canvas 
+ * or Window.
+ */
+public abstract class BufferStrategy {
+
+    /**
+     * Returns true if the drawing buffer was lost since the last call 
+     * of getDrawGraphics. 
+     * 
+     * @return true if the drawing buffer was lost since the last call 
+     * of getDrawGraphics, false otherwise.
+     */
+    public abstract boolean contentsLost();
+
+    /**
+     * Returns true if the drawing buffer is restored from a lost state. 
+     * 
+     * @return true if the drawing buffer is restored from a lost state,
+     * false otherwise.
+     */
+    public abstract boolean contentsRestored();
+
+    /**
+     * Gets the BufferCapabilities of BufferStrategy.
+     * 
+     * @return the BufferCapabilities of BufferStrategy.
+     */
+    public abstract BufferCapabilities getCapabilities();
+
+    /**
+     * Gets the Graphics object to use to draw to the buffer.
+     * 
+     * @return the Graphics object to use to draw to the buffer.
+     */
+    public abstract Graphics getDrawGraphics();
+
+    /**
+     * Shows the next available buffer.
+     */
+    public abstract void show();
+
+}
diff --git a/awt/java/awt/image/BufferedImage.java b/awt/java/awt/image/BufferedImage.java
new file mode 100644
index 0000000..d305d66
--- /dev/null
+++ b/awt/java/awt/image/BufferedImage.java
@@ -0,0 +1,931 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import com.android.internal.awt.AndroidGraphics2D;
+
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsEnvironment;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Transparency;
+import java.awt.color.ColorSpace;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.apache.harmony.awt.gl.ImageSurface;
+import org.apache.harmony.awt.gl.Surface;
+import org.apache.harmony.awt.gl.image.BufferedImageSource;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+
+/**
+ * The BufferedImage class describes an Image which contains a buffer 
+ * of image data and includes a ColorModel and a Raster for this data.
+ * This class provides methods for obtaining and setting the Raster
+ * and for manipulating the ColorModel parameters.
+ */
+public class BufferedImage extends 
+Image implements WritableRenderedImage, Transparency{
+
+    /** 
+     * The Constant TYPE_CUSTOM indicates that Image type 
+     * is unknown. 
+     */
+    public static final int TYPE_CUSTOM = 0;
+
+    /** 
+     * The Constant TYPE_INT_RGB indicates an image with 
+     * 8 bit RGB color components, it has a DirectColorModel 
+     * without alpha. 
+     */
+    public static final int TYPE_INT_RGB = 1;
+
+    /** 
+     * The Constant TYPE_INT_ARGB indicates an image with 
+     * 8 bit RGBA color components, it has a DirectColorModel 
+     * with alpha. 
+     */
+    public static final int TYPE_INT_ARGB = 2;
+
+    /** 
+     * The Constant TYPE_INT_ARGB_PRE indicates an image with 
+     * 8 bit RGBA color components, it has a DirectColorModel 
+     * with alpha, and image data is premultiplied by alpha. 
+     */
+    public static final int TYPE_INT_ARGB_PRE = 3;
+
+    /** 
+     * The Constant TYPE_INT_BGR indicates an image with 
+     * 8 bit RGB color components, BGR color model 
+     * (with the colors Blue, Green, and Red). There is no 
+     * alpha. The image has a DirectColorModel. 
+     */
+    public static final int TYPE_INT_BGR = 4;
+
+    /** 
+     * The Constant TYPE_3BYTE_BGR indicates an image with 
+     * 8 bit RGB color components, BGR color model 
+     * (with the colors Blue, Green, and Red stored in 3 bytes). 
+     * There is no alpha. The image has a ComponentColorModel. 
+     */
+    public static final int TYPE_3BYTE_BGR = 5;
+
+    /** 
+     * The Constant TYPE_4BYTE_ABGR indicates an image with 
+     * 8 bit RGBA color components stored in 3 bytes and 1 byte of alpha.
+     * It has a ComponentColorModel with alpha.  
+     */
+    public static final int TYPE_4BYTE_ABGR = 6;
+
+    /** 
+     * The Constant TYPE_4BYTE_ABGR_PRE indicates an image with 
+     * 8 bit RGBA color components stored in 3 bytes and 1 byte 
+     * for alpha. The image has a ComponentColorModel with alpha. 
+     * The color data is premultiplied with alpha.
+     */
+    public static final int TYPE_4BYTE_ABGR_PRE = 7;
+
+    /** 
+     * The Constant TYPE_USHORT_565_RGB indicates an image with 
+     * 565 RGB color components (5-bits red, 6-bits green, 5-bits blue) 
+     * with no alpha. This image has a DirectColorModel. 
+     */
+    public static final int TYPE_USHORT_565_RGB = 8;
+
+    /** 
+     * The Constant TYPE_USHORT_555_RGB indicates an image with 
+     * 555 RGB color components (5-bits red, 5-bits green, 5-bits blue) 
+     * with no alpha. This image has a DirectColorModel. 
+     */
+    public static final int TYPE_USHORT_555_RGB = 9;
+
+    /** 
+     * The Constant TYPE_BYTE_GRAY indicates a unsigned byte 
+     * image. This image has a ComponentColorModel with 
+     * a CS_GRAY ColorSpace. 
+     */
+    public static final int TYPE_BYTE_GRAY = 10;
+
+    /** 
+     * The Constant TYPE_USHORT_GRAY indicates an unsigned short 
+     * image. This image has a ComponentColorModel with a CS_GRAY 
+     * ColorSpace. 
+     */
+    public static final int TYPE_USHORT_GRAY = 11;
+
+    /** 
+     * The Constant TYPE_BYTE_BINARY indicates an opaque byte-packed
+     * 1, 2 or 4 bit image. The image has an IndexColorModel without 
+     * alpha.  
+     */
+    public static final int TYPE_BYTE_BINARY = 12;
+
+    /** 
+     * The Constant TYPE_BYTE_INDEXED indicates an indexed byte image. 
+     */
+    public static final int TYPE_BYTE_INDEXED = 13;
+
+    /** The Constant ALPHA_MASK. */
+    private static final int ALPHA_MASK = 0xff000000;
+
+    /** The Constant RED_MASK. */
+    private static final int RED_MASK = 0x00ff0000;
+
+    /** The Constant GREEN_MASK. */
+    private static final int GREEN_MASK = 0x0000ff00;
+
+    /** The Constant BLUE_MASK. */
+    private static final int BLUE_MASK = 0x000000ff;
+
+    /** The Constant RED_BGR_MASK. */
+    private static final int RED_BGR_MASK = 0x000000ff;
+
+    /** The Constant GREEN_BGR_MASK. */
+    private static final int GREEN_BGR_MASK = 0x0000ff00;
+
+    /** The Constant BLUE_BGR_MASK. */
+    private static final int BLUE_BGR_MASK = 0x00ff0000;
+
+    /** The Constant RED_565_MASK. */
+    private static final int RED_565_MASK = 0xf800;
+
+    /** The Constant GREEN_565_MASK. */
+    private static final int GREEN_565_MASK = 0x07e0;
+
+    /** The Constant BLUE_565_MASK. */
+    private static final int BLUE_565_MASK = 0x001f;
+
+    /** The Constant RED_555_MASK. */
+    private static final int RED_555_MASK = 0x7c00;
+
+    /** The Constant GREEN_555_MASK. */
+    private static final int GREEN_555_MASK = 0x03e0;
+
+    /** The Constant BLUE_555_MASK. */
+    private static final int BLUE_555_MASK = 0x001f;
+
+    /** The cm. */
+    private ColorModel cm;
+
+    /** The raster. */
+    private final WritableRaster raster;
+
+    /** The image type. */
+    private final int imageType;
+
+    /** The properties. */
+    private Hashtable<?, ?> properties;
+
+    // Surface of the Buffered Image - used for blitting one Buffered Image 
+    // on the other one or on the Component
+    /** The image surf. */
+    private final ImageSurface imageSurf;
+
+    /**
+     * Instantiates a new BufferedImage with the specified ColorModel,
+     * and WritableRaster objects. The Raster data can be
+     * be divided or multiplied by alpha. It depends on the 
+     * alphaPremultiplied state in the ColorModel.
+     * 
+     * @param cm the ColorModel of the new image.
+     * @param raster the WritableRaster of the new image.
+     * @param isRasterPremultiplied if true the data of the specified
+     * Raster is premultiplied by alpha.
+     * @param properties the properties of new Image.
+     */
+    public BufferedImage(ColorModel cm, WritableRaster raster,
+            boolean isRasterPremultiplied, Hashtable<?, ?> properties) {
+        if (!cm.isCompatibleRaster(raster)) {
+            // awt.4D=The raster is incompatible with this ColorModel
+            throw new IllegalArgumentException(Messages.getString("awt.4D")); //$NON-NLS-1$
+        }
+
+        if (raster.getMinX() != 0 || raster.getMinY() != 0) {
+            // awt.228=minX or minY of this raster not equal to zero
+            throw new IllegalArgumentException(Messages.getString("awt.228")); //$NON-NLS-1$
+        }
+
+        this.cm  = cm;
+        this.raster = raster;
+        this.properties = properties;
+
+        coerceData(isRasterPremultiplied);
+
+        imageType = Surface.getType(cm, raster);
+
+        imageSurf = createImageSurface(imageType);
+    }
+
+    /**
+     * Instantiates a new BufferedImage with the specified width, height
+     * predefined image type (TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED) 
+     * and the specified IndexColorModel.
+     * 
+     * @param width the width of new image.
+     * @param height the height of new image.
+     * @param imageType the predefined image type. 
+     * @param cm the specified IndexColorModel.
+     */
+    public BufferedImage(int width, int height, int imageType,
+            IndexColorModel cm) {
+        switch (imageType) {
+        case TYPE_BYTE_BINARY:
+            if (cm.hasAlpha()) {
+                // awt.227=This image type can't have alpha
+                throw new IllegalArgumentException(Messages.getString("awt.227")); //$NON-NLS-1$
+            }
+            int pixel_bits = 0;
+            int mapSize = cm.getMapSize();
+            if (mapSize <= 2) {
+                pixel_bits = 1;
+            } else if (mapSize <= 4) {
+                pixel_bits = 2;
+            } else if (mapSize <= 16) {
+                pixel_bits = 4;
+            } else {
+                // awt.221=The imageType is TYPE_BYTE_BINARY and the color map has more than 16 entries
+                throw new IllegalArgumentException(Messages.getString("awt.221")); //$NON-NLS-1$
+            }
+
+            raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE, width,
+                    height, 1, pixel_bits, null);
+            break;
+
+        case TYPE_BYTE_INDEXED:
+            raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
+                    width, height, 1, null);
+            break;
+
+        default:
+            // awt.222=The imageType is not TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED
+            throw new IllegalArgumentException(Messages.getString("awt.222")); //$NON-NLS-1$
+
+        }
+
+        if (!cm.isCompatibleRaster(raster)) {
+            // awt.223=The imageType is not compatible with ColorModel
+            throw new IllegalArgumentException(Messages.getString("awt.223")); //$NON-NLS-1$
+        }
+
+        this.cm = cm;
+        this.imageType = imageType;
+        imageSurf = createImageSurface(imageType);
+
+    }
+
+    /**
+     * Instantiates a new BufferedImage with the specified width, height
+     * and predefined image type.
+     * 
+     * @param width the width of new image.
+     * @param height the height of new image.
+     * @param imageType the predefined image type. 
+     */
+    public BufferedImage(int width, int height, int imageType) {
+
+        switch (imageType) {
+        case TYPE_INT_RGB:
+            cm = new DirectColorModel(24, RED_MASK, GREEN_MASK, BLUE_MASK);
+            raster = cm.createCompatibleWritableRaster(width, height);
+            break;
+
+        case TYPE_INT_ARGB:
+            cm = ColorModel.getRGBdefault();
+            raster = cm.createCompatibleWritableRaster(width, height);
+            break;
+
+        case TYPE_INT_ARGB_PRE:
+            cm = new DirectColorModel(
+                    ColorSpace.getInstance(ColorSpace.CS_sRGB),
+                    32,
+                    RED_MASK,
+                    GREEN_MASK,
+                    BLUE_MASK,
+                    ALPHA_MASK,
+                    true,
+                    DataBuffer.TYPE_INT);
+
+            raster = cm.createCompatibleWritableRaster(width, height);
+            break;
+
+        case TYPE_INT_BGR:
+            cm = new DirectColorModel(24,
+                    RED_BGR_MASK,
+                    GREEN_BGR_MASK,
+                    BLUE_BGR_MASK);
+
+            raster = cm.createCompatibleWritableRaster(width, height);
+            break;
+
+        case TYPE_3BYTE_BGR: {
+            int bits[] = { 8, 8, 8 };
+            int bandOffsets[] = { 2, 1, 0 };
+            cm = new ComponentColorModel(
+                    ColorSpace.getInstance(ColorSpace.CS_sRGB),
+                    bits, 
+                    false, 
+                    false, 
+                    Transparency.OPAQUE, 
+                    DataBuffer.TYPE_BYTE);
+
+            raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
+                    width, height, width * 3, 3, bandOffsets, null);
+            }
+            break;
+
+        case TYPE_4BYTE_ABGR: {
+            int bits[] = { 8, 8, 8, 8 };
+            int bandOffsets[] = { 3, 2, 1, 0 };
+            cm = new ComponentColorModel(
+                    ColorSpace.getInstance(ColorSpace.CS_sRGB),
+                    bits, 
+                    true, 
+                    false, 
+                    Transparency.TRANSLUCENT, 
+                    DataBuffer.TYPE_BYTE);
+
+            raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
+                    width, height, width * 4, 4, bandOffsets, null);
+            }
+            break;
+
+        case TYPE_4BYTE_ABGR_PRE: {
+            int bits[] = { 8, 8, 8, 8 };
+            int bandOffsets[] = { 3, 2, 1, 0 };
+            cm = new ComponentColorModel(
+                    ColorSpace.getInstance(ColorSpace.CS_sRGB),
+                    bits, 
+                    true, 
+                    true, 
+                    Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
+
+            raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
+                    width, height, width * 4, 4, bandOffsets, null);
+            }
+            break;
+
+        case TYPE_USHORT_565_RGB:
+            cm = new DirectColorModel(
+                    ColorSpace.getInstance(ColorSpace.CS_sRGB),
+                    16,
+                    RED_565_MASK,
+                    GREEN_565_MASK,
+                    BLUE_565_MASK,
+                    0,
+                    false,
+                    DataBuffer.TYPE_USHORT);
+
+            raster = cm.createCompatibleWritableRaster(width, height);
+            break;
+
+        case TYPE_USHORT_555_RGB:
+            cm = new DirectColorModel(
+                    ColorSpace.getInstance(ColorSpace.CS_sRGB),
+                    15,
+                    RED_555_MASK,
+                    GREEN_555_MASK,
+                    BLUE_555_MASK,
+                    0,
+                    false,
+                    DataBuffer.TYPE_USHORT);
+
+            raster = cm.createCompatibleWritableRaster(width, height);
+            break;
+
+        case TYPE_BYTE_GRAY: {
+            int bits[] = { 8 };
+            cm = new ComponentColorModel(
+                    ColorSpace.getInstance(ColorSpace.CS_GRAY),
+                    bits, 
+                    false, 
+                    false, 
+                    Transparency.OPAQUE, 
+                    DataBuffer.TYPE_BYTE);
+
+            raster = cm.createCompatibleWritableRaster(width, height);
+            }
+            break;
+
+        case TYPE_USHORT_GRAY: {
+            int bits[] = { 16 };
+            cm = new ComponentColorModel(
+                    ColorSpace.getInstance(ColorSpace.CS_GRAY),
+                    bits, 
+                    false, 
+                    false, 
+                    Transparency.OPAQUE, 
+                    DataBuffer.TYPE_USHORT);
+            raster = cm.createCompatibleWritableRaster(width, height);
+            }
+            break;
+
+        case TYPE_BYTE_BINARY: {
+            int colorMap[] = { 0, 0xffffff };
+            cm = new IndexColorModel(1, 2, colorMap, 0, false, -1,
+                    DataBuffer.TYPE_BYTE);
+
+            raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE, width,
+                    height, 1, 1, null);
+            }
+            break;
+
+        case TYPE_BYTE_INDEXED: {
+            int colorMap[] = new int[256];
+            int i = 0;
+            for (int r = 0; r < 256; r += 51) {
+                for (int g = 0; g < 256; g += 51) {
+                    for (int b = 0; b < 256; b += 51) {
+                        colorMap[i] = (r << 16) | (g << 8) | b;
+                        i++;
+                    }
+                }
+            }
+
+            int gray = 0x12;
+            for (; i < 256; i++, gray += 6) {
+                colorMap[i] = (gray << 16) | (gray << 8) | gray;
+            }
+            cm = new IndexColorModel(8, 256, colorMap, 0, false, -1,
+                    DataBuffer.TYPE_BYTE);
+            raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
+                    width, height, 1, null);
+
+            }
+            break;
+        default:
+            // awt.224=Unknown image type
+            throw new IllegalArgumentException(Messages.getString("awt.224")); //$NON-NLS-1$
+        }
+        this.imageType = imageType;
+        imageSurf = createImageSurface(imageType);
+    }
+
+    @Override
+    public Object getProperty(String name, ImageObserver observer) {
+        return getProperty(name);
+    }
+
+    public Object getProperty(String name) {
+        if(name == null) {
+            // awt.225=Property name is null
+            throw new NullPointerException(Messages.getString("awt.225")); //$NON-NLS-1$
+        }
+        if (properties == null) {
+            return Image.UndefinedProperty;
+        }
+        Object property = properties.get(name);
+        if (property == null) {
+            property = Image.UndefinedProperty;
+        }
+        return property;
+    }
+
+    public WritableRaster copyData(WritableRaster outRaster) {
+        if (outRaster == null) {
+            outRaster = Raster.createWritableRaster(raster.getSampleModel(),
+                    new Point(raster.getSampleModelTranslateX(),
+                            raster.getSampleModelTranslateY()));
+        }
+
+        int w = outRaster.getWidth();
+        int h = outRaster.getHeight();
+        int minX = outRaster.getMinX();
+        int minY = outRaster.getMinY();
+
+        Object data = null;
+
+        data = raster.getDataElements(minX, minY, w, h, data);
+        outRaster.setDataElements(minX, minY, w, h, data);
+
+        return outRaster;
+    }
+
+    public Raster getData(Rectangle rect) {
+        int minX = rect.x;
+        int minY = rect.y;
+        int w = rect.width;
+        int h = rect.height;
+
+        SampleModel sm = raster.getSampleModel();
+        SampleModel nsm = sm.createCompatibleSampleModel(w, h);
+        WritableRaster outr = Raster.createWritableRaster(nsm, 
+                rect.getLocation());
+        Object data = null;
+
+        data = raster.getDataElements(minX, minY, w, h, data);
+        outr.setDataElements(minX, minY, w, h, data);
+        return outr;
+    }
+
+    public Vector<RenderedImage> getSources() {
+        return null;
+    }
+
+    public String[] getPropertyNames() {
+        if (properties == null) {
+            return null;
+        }
+        Vector<String> v = new Vector<String>();
+        for (Enumeration<?> e = properties.keys(); e.hasMoreElements();) {
+            try {
+                v.add((String) e.nextElement());
+            } catch (ClassCastException ex) {
+            }
+        }
+        int size = v.size();
+        if (size > 0) {
+            String names[] = new String[size];
+            for (int i = 0; i < size; i++) {
+                names[i] = v.elementAt(i);
+            }
+            return names;
+        }
+        return null;
+    }
+
+    /**
+     * Returns the string representation of this BufferedImage object.
+     * 
+     * @return the string representation of this BufferedImage object.
+     */
+    @Override
+    public String toString() {
+        return "BufferedImage@" + Integer.toHexString(hashCode()) + //$NON-NLS-1$
+            ": type = " + imageType + " " + cm + " " + raster; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+    }
+
+    public WritableRaster getWritableTile(int tileX, int tileY) {
+        return raster;
+    }
+
+    /**
+     * Gets the WritableRaster of this BufferedImage.
+     * 
+     * @return the WritableRaster of this BufferedImage.
+     */
+    public WritableRaster getRaster() {
+        return raster;
+    }
+
+    /**
+     * Gets a WritableRaster object which contains the alpha channel of 
+     * BufferedImage object with ColorModel objects that supports 
+     * a separate alpha channel such as ComponentColorModel 
+     * or DirectColorModel.
+     * 
+     * @return the WritableRaster object which contains the alpha 
+     * channel of this BufferedImage. 
+     */
+    public WritableRaster getAlphaRaster() {
+        return cm.getAlphaRaster(raster);
+    }
+
+    public void removeTileObserver(TileObserver to) {
+    }
+
+    public void addTileObserver(TileObserver to) {
+    }
+
+    public SampleModel getSampleModel() {
+        return raster.getSampleModel();
+    }
+
+    public void setData(Raster r) {
+
+        Rectangle from = r.getBounds();
+        Rectangle to = raster.getBounds();
+        Rectangle intersection = to.intersection(from);
+
+        int minX = intersection.x;
+        int minY = intersection.y;
+        int w = intersection.width;
+        int h = intersection.height;
+
+        Object data = null;
+
+        data = r.getDataElements(minX, minY, w, h, data);
+        raster.setDataElements(minX, minY, w, h, data);
+    }
+
+    public Raster getTile(int tileX, int tileY) {
+        if (tileX == 0 && tileY == 0) {
+            return raster;
+        }
+        // awt.226=Both tileX and tileY are not equal to 0
+        throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.226")); //$NON-NLS-1$
+    }
+
+    public Raster getData() {
+        int w = raster.getWidth();
+        int h = raster.getHeight();
+        int minX = raster.getMinX();
+        int minY = raster.getMinY();
+
+        WritableRaster outr = Raster.createWritableRaster(
+                raster.getSampleModel(),
+                new Point(raster.getSampleModelTranslateX(),
+                raster.getSampleModelTranslateY()));
+
+        Object data = null;
+
+        data = raster.getDataElements(minX, minY, w, h, data);
+        outr.setDataElements(minX, minY, w, h, data);
+
+        return outr;
+    }
+
+    @Override
+    public ImageProducer getSource() {
+        return new BufferedImageSource(this, properties);
+    }
+
+    @Override
+    public int getWidth(ImageObserver observer) {
+        return raster.getWidth();
+    }
+
+    @Override
+    public int getHeight(ImageObserver observer) {
+        return raster.getHeight();
+    }
+
+    public ColorModel getColorModel() {
+        return cm;
+    }
+
+    /**
+     * Gets the rectangular area of this BufferedImage as a subimage.
+     * 
+     * @param x the x coordinate.
+     * @param y the y coordinate.
+     * @param w the width of the subimage.
+     * @param h the height of the subimage.
+     * 
+     * @return the BufferedImage.
+     */
+    public BufferedImage getSubimage(int x, int y, int w, int h) {
+        WritableRaster wr = raster.createWritableChild(x, y, w, h, 0, 0, null);
+        return new BufferedImage(cm, wr, cm.isAlphaPremultiplied(), properties);
+    }
+
+    public Point[] getWritableTileIndices() {
+        Point points[] = new Point[1];
+        points[0] = new Point(0, 0);
+        return points;
+    }
+
+    /**
+     * Creates the Graphics2D object which allows to draw into 
+     * this BufferedImage.
+     * 
+     * @return the graphics2D object.
+     */
+    public Graphics2D createGraphics() {
+        GraphicsEnvironment ge = 
+            GraphicsEnvironment.getLocalGraphicsEnvironment();
+        //return ge.createGraphics(this);
+        //???AWT hack, FIXME
+        //return AndroidGraphics2D.getInstance();
+        //throw new RuntimeException("Not implemented!");
+        return null;
+    }
+
+    @Override
+    public Graphics getGraphics() {
+        return createGraphics();
+    }
+
+    /**
+     * Coerces the data to achieve the state which is specified by 
+     * the isAlphaPremultiplied variable. 
+     * 
+     * @param isAlphaPremultiplied the is alpha premultiplied state.
+     */
+    public void coerceData(boolean isAlphaPremultiplied) {
+        if (cm.hasAlpha() && 
+                cm.isAlphaPremultiplied() != isAlphaPremultiplied) {
+            cm = cm.coerceData(raster, isAlphaPremultiplied);
+        }
+    }
+
+    /**
+     * Gets an array of colors in the TYPE_INT_ARGB color model and 
+     * default sRGB colorspace of the specified area of this
+     * BufferedImage. The result array is composed by the following
+     * algirithm:
+     * <p> 
+     * pixel   = rgbArray[offset + (y-startY)*scansize + (x-startX)]
+     * 
+     * @param startX the start X area coordinate. 
+     * @param startY the start Y area coordinate.
+     * @param w the width of the area. 
+     * @param h the height of the area.
+     * @param rgbArray the result array will be stored to this array.
+     * @param offset the offset of the rgbArray array. 
+     * @param scansize the scanline stride for the rgbArray.
+     * 
+     * @return an array of colors for the specified area.
+     */
+    public int[] getRGB(int startX, int startY, int w, int h, int[] rgbArray,
+            int offset, int scansize) {
+        if (rgbArray == null) {
+            rgbArray = new int[offset + h * scansize];
+        }
+
+        int off = offset;
+        for (int y = startY; y < startY + h; y++, off += scansize) {
+            int i = off;
+            for (int x = startX; x < startX + w; x++, i++) {
+                rgbArray[i] = cm.getRGB(raster.getDataElements(x, y, null));
+            }
+        }
+        return rgbArray;
+    }
+
+    /**
+     * Sets RGB values from the specified array to the specified
+     * BufferedImage area. The pixels are in the default RGB color model 
+     * (TYPE_INT_ARGB) and default sRGB color space.
+     * 
+     * @param startX the start X coordinate.
+     * @param startY the start Y coordinate.
+     * @param w the width of the BufferedImage area.
+     * @param h the height of the BufferedImage area.
+     * @param rgbArray the array of RGB values.
+     * @param offset the offset of the rgbArray array. 
+     * @param scansize the scanline stride for the rgbArray.
+     */
+    public void setRGB(int startX, int startY, int w, int h, int[] rgbArray,
+            int offset, int scansize) {
+        int off = offset;
+        for (int y = startY; y < startY + h; y++, off += scansize) {
+            int i = off;
+            for (int x = startX; x < startX + w; x++, i++) {
+                raster.setDataElements(x, y, 
+                        cm.getDataElements(rgbArray[i], null));
+            }
+        }
+    }
+
+    /**
+     * Sets a the specified RGB value to the specified pixel of
+     * this BufferedImage. The pixel should be in the default 
+     * RGB color model (TYPE_INT_ARGB) and default sRGB color space. 
+     *  
+     * @param x the X coordinate of the pixel.
+     * @param y the Y coordinate of the pixel.
+     * @param rgb the RGB value to be set.
+     */
+    public synchronized void setRGB(int x, int y, int rgb) {
+        raster.setDataElements(x, y, cm.getDataElements(rgb, null));
+    }
+
+    public boolean isTileWritable(int tileX, int tileY) {
+        if (tileX == 0 && tileY == 0) {
+            return true;
+        }
+        // awt.226=Both tileX and tileY are not equal to 0
+        throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.226")); //$NON-NLS-1$
+    }
+
+    public void releaseWritableTile(int tileX, int tileY) {
+    }
+
+    /**
+     * Gets a color in the TYPE_INT_ARGB color model and default 
+     * sRGB colorspace of the specified pixel. 
+     * 
+     * @param x the X coordinate of the pixel.
+     * @param y the Y coordinate of the pixel.
+     * 
+     * @return the color of the specified pixel in the TYPE_INT_ARGB 
+     * color model and default sRGB colorspace. 
+     */
+    public int getRGB(int x, int y) {
+        return cm.getRGB(raster.getDataElements(x, y, null));
+    }
+
+    /**
+     * Returnes true if alpha is premultiplied, 
+     * false if alpha is not premultiplied or there is no alpha.
+     * 
+     * @return true if alpha is premultiplied, 
+     * false if alpha is not premultiplied or there is no alpha.
+     */
+    public boolean isAlphaPremultiplied() {
+        return cm.isAlphaPremultiplied();
+    }
+
+    public boolean hasTileWriters() {
+        return true;
+    }
+
+    @Override
+    public void flush() {
+        imageSurf.dispose();
+    }
+
+    public int getWidth() {
+        return raster.getWidth();
+    }
+
+    /**
+     * Gets the image type.
+     * 
+     * @return the image type.
+     */
+    public int getType() {
+        return imageType;
+    }
+
+    public int getTileWidth() {
+        return raster.getWidth();
+    }
+
+    public int getTileHeight() {
+        return raster.getHeight();
+    }
+
+    public int getTileGridYOffset() {
+        return raster.getSampleModelTranslateY();
+    }
+
+    public int getTileGridXOffset() {
+        return raster.getSampleModelTranslateX();
+    }
+
+    public int getNumYTiles() {
+        return 1;
+    }
+
+    public int getNumXTiles() {
+        return 1;
+    }
+
+    public int getMinY() {
+        return raster.getMinY();
+    }
+
+    public int getMinX() {
+        return raster.getMinX();
+    }
+
+    public int getMinTileY() {
+        return 0;
+    }
+
+    public int getMinTileX() {
+        return 0;
+    }
+
+    public int getHeight() {
+        return raster.getHeight();
+    }
+
+    /**
+     * Creates the image surface.
+     * 
+     * @param type the type
+     * 
+     * @return the image surface
+     */
+    private ImageSurface createImageSurface(int type) {
+        return new ImageSurface(getColorModel(), getRaster(), type);
+    }
+
+    /**
+     * Gets the image surface.
+     * 
+     * @return the image surface
+     */
+    ImageSurface getImageSurface() {
+        return imageSurf;
+    }
+
+    public int getTransparency() {
+        return cm.getTransparency();
+    }
+}
+
diff --git a/awt/java/awt/image/BufferedImageFilter.java b/awt/java/awt/image/BufferedImageFilter.java
new file mode 100644
index 0000000..44b3c2e
--- /dev/null
+++ b/awt/java/awt/image/BufferedImageFilter.java
@@ -0,0 +1,375 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+/**
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ */
+
+package java.awt.image;
+
+import org.apache.harmony.awt.gl.AwtImageBackdoorAccessor;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The BufferedImageFilter class provides filtering operations to 
+ * the BufferedImage objects using operators which implement
+ * BufferedImageOp interface.
+ */
+public class BufferedImageFilter extends ImageFilter implements Cloneable {
+    
+    /** The Constant accessor. */
+    private static final AwtImageBackdoorAccessor accessor = AwtImageBackdoorAccessor.getInstance();
+
+    /** The op. */
+    private BufferedImageOp op;
+
+    /** The raster. */
+    private WritableRaster raster;
+
+    /** The i data. */
+    private int iData[];
+    
+    /** The b data. */
+    private byte bData[];
+
+    /** The width. */
+    private int width;
+    
+    /** The height. */
+    private int height;
+
+    /** The cm. */
+    private ColorModel cm;
+
+    /** The forced rgb. */
+    private boolean forcedRGB = false;
+    
+    /** The transfer type. */
+    private int transferType = DataBuffer.TYPE_UNDEFINED;
+
+    /**
+     * Instantiates a new BufferedImageFilter with the specified
+     * BufferedImageOp operator.
+     * 
+     * @param op the specified BufferedImageOp operator.
+     * 
+     * @throws NullPointerException if BufferedImageOp is null.
+     */
+    public BufferedImageFilter(BufferedImageOp op) {
+        if (op == null) {
+            throw new NullPointerException(Messages.getString("awt.05")); //$NON-NLS-1$
+        }
+        this.op = op;
+    }
+
+    /**
+     * Gets the BufferedImageOp operator associated with this 
+     * BufferedImageFilter object.
+     * 
+     * @return the BufferedImageOp associated with this 
+     * BufferedImageFilter object.
+     */
+    public BufferedImageOp getBufferedImageOp() {
+        return op;
+    }
+
+    @Override
+    public void setDimensions(int width, int height) {
+        this.width = width;
+        this.height = height;
+        // Stop image consuming if no pixels expected.
+        if (width <= 0 || height <= 0) {
+            consumer.imageComplete(ImageConsumer.STATICIMAGEDONE);
+            reset();
+        }
+    }
+
+    @Override
+    public void setColorModel(ColorModel model) {
+        if (this.cm != null && this.cm != model && raster != null) {
+            forceRGB();
+        } else {
+            this.cm = model;
+        }
+    }
+
+    @Override
+    public void setPixels(
+            int x, int y, int
+            w, int h,
+            ColorModel model, byte[] pixels,
+            int off, int scansize
+    ) {
+        setPixels(x, y, w, h, model, pixels, off, scansize, true);
+    }
+
+    @Override
+    public void setPixels(
+            int x, int y,
+            int w, int h,
+            ColorModel model, int[] pixels,
+            int off, int scansize
+    ) {
+        setPixels(x, y, w, h, model, pixels, off, scansize, false);
+    }
+
+    @Override
+    public void imageComplete(int status) {
+        if (status == STATICIMAGEDONE || status == SINGLEFRAMEDONE) {
+            BufferedImage bim = new BufferedImage(cm, raster, cm.isAlphaPremultiplied, null);
+            bim = op.filter(bim, null);
+            DataBuffer dstDb = bim.getRaster().getDataBuffer();
+            ColorModel dstCm = bim.getColorModel();
+            int dstW = bim.getWidth();
+            int dstH = bim.getHeight();
+
+            consumer.setDimensions(dstW, dstH);
+
+            if (dstDb.getDataType() == DataBuffer.TYPE_INT) {
+                consumer.setColorModel(dstCm);
+                consumer.setPixels(0, 0, dstW, dstH, dstCm, accessor.getDataInt(dstDb), 0, dstW);
+            } else if (dstDb.getDataType() == DataBuffer.TYPE_BYTE) {
+                consumer.setColorModel(dstCm);
+                consumer.setPixels(0, 0, dstW, dstH, dstCm, accessor.getDataByte(dstDb), 0, dstW);
+            } else {
+                int dstData[] = bim.getRGB(0, 0, dstW, dstH, null, 0, dstW);
+                dstCm = ColorModel.getRGBdefault();
+                consumer.setColorModel(dstCm);
+                consumer.setPixels(0, 0, dstW, dstH, dstCm, dstData, 0, dstW);
+            }
+        } else if (status == IMAGEERROR || status == IMAGEABORTED) {
+            reset();
+        }
+
+        consumer.imageComplete(status);
+    }
+
+    /**
+     * Sets the pixels.
+     * 
+     * @param x the x
+     * @param y the y
+     * @param w the w
+     * @param h the h
+     * @param model the model
+     * @param pixels the pixels
+     * @param off the off
+     * @param scansize the scansize
+     * @param isByteData the is byte data
+     */
+    private void setPixels(
+            int x, int y,
+            int w, int h,
+            ColorModel model, Object pixels,
+            int off, int scansize, boolean isByteData
+    ) {
+        // Check bounds
+        // Need to copy only the pixels that will fit into the destination area
+        if (x < 0) {
+            w -= x;
+            off += x;
+            x = 0;
+        }
+
+        if (y < 0) {
+            h -= y;
+            off += y * scansize;
+            y = 0;
+        }
+
+        if (x + w > width) {
+            w = width - x;
+        }
+
+        if (y + h > height) {
+            h = height - y;
+        }
+
+        if (w <= 0 || h <= 0) {
+            return;
+        }
+
+        // Check model
+        if (this.cm == null) {
+            setColorModel(model);
+        } else if (model == null) {
+            model = this.cm;
+        } else if (!model.equals(this.cm)) {
+            forceRGB();
+        }
+
+        boolean canArraycopy;
+        // Process pixels
+        switch(transferType) {
+            case DataBuffer.TYPE_UNDEFINED: {
+                if (isByteData) {
+                    transferType = DataBuffer.TYPE_BYTE;
+                    createRaster(transferType);
+                    //bData = new byte[width*height];
+                    canArraycopy = !forcedRGB;
+                    break;
+                }
+                transferType = DataBuffer.TYPE_INT;
+                createRaster(transferType);
+                //iData = new int[width*height];
+                canArraycopy = !forcedRGB || model.equals(ColorModel.getRGBdefault());
+                break;
+            } // And proceed to copy the pixels
+            case DataBuffer.TYPE_INT: {
+                if (isByteData) { // There are int data already but the new data are bytes
+                    forceRGB();
+                    canArraycopy = false;
+                    break;
+                } else if (!forcedRGB || model.equals(ColorModel.getRGBdefault())) {
+                    canArraycopy = true;
+                    break;
+                } // Else fallback to the RGB conversion
+            }
+            case DataBuffer.TYPE_BYTE: {
+                if (isByteData && !forcedRGB) {
+                    canArraycopy = true;
+                    break;
+                }
+
+                // RGB conversion
+                canArraycopy = false;
+                break;
+            } default: {
+                throw new IllegalStateException(Messages.getString("awt.06")); //$NON-NLS-1$
+            }
+        }
+
+        off += x;
+        int maxOffset = off + h * scansize;
+        int dstOffset = x + y * width;
+
+        if (canArraycopy) {
+            Object dstArray = isByteData ? (Object) bData : (Object) iData;
+            for (; off < maxOffset; off += scansize, dstOffset += width) {
+                System.arraycopy(pixels, off, dstArray, dstOffset, w);
+            }
+        } else {
+            // RGB conversion
+            for (; off < maxOffset; off += scansize, dstOffset += width) {
+                int srcPos = off;
+                int dstPos = dstOffset;
+                int maxDstPos = dstOffset + w;
+                for (; dstPos < maxDstPos; dstPos++, srcPos++) {
+                    iData[dstPos] = model.getRGB(
+                            isByteData ?
+                            ((byte[])pixels)[srcPos] :
+                            ((int[])pixels)[srcPos]
+                    );
+                }
+            }
+        }
+    }
+
+    /**
+     * Force rgb.
+     */
+    private void forceRGB() {
+        if (!forcedRGB) {
+            forcedRGB = true;
+            int size = width*height;
+            int rgbData[] = new int[size];
+
+            if (bData != null) {
+                for (int i=0; i<size; i++) {
+                    rgbData[i] = cm.getRGB(bData[i]);
+                }
+            } else if (iData != null) {
+                for (int i=0; i<size; i++) {
+                    rgbData[i] = cm.getRGB(iData[i]);
+                }
+            }
+
+            cm = ColorModel.getRGBdefault();
+            DataBufferInt db = new DataBufferInt(rgbData, size);
+            int masks[] = new int[] {0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000};
+            raster = Raster.createPackedRaster(db, width, height, width, masks, null);
+            iData = accessor.getDataInt(db);
+            bData = null;
+            transferType = DataBuffer.TYPE_INT;
+        }
+    }
+
+    /**
+     * Reset.
+     */
+    private void reset() {
+        width = 0;
+        height = 0;
+        forcedRGB = false;
+        cm = null;
+        iData = null;
+        bData = null;
+        transferType = DataBuffer.TYPE_UNDEFINED;
+        raster = null;
+    }
+
+    /**
+     * Creates the raster.
+     * 
+     * @param dataType the data type
+     */
+    private void createRaster(int dataType) {
+        boolean createdValidBuffer = false;
+        try{
+            raster = cm.createCompatibleWritableRaster(width, height);
+            int rasterType = raster.getDataBuffer().getDataType();
+            if (rasterType == dataType) {
+                switch (rasterType) {
+                    case DataBuffer.TYPE_INT: {
+                        iData = accessor.getDataInt(raster.getDataBuffer());
+                        if (iData != null) {
+                            createdValidBuffer = true;
+                        }
+                        break;
+                    }
+                    case DataBuffer.TYPE_BYTE: {
+                        bData = accessor.getDataByte(raster.getDataBuffer());
+                        if (bData != null) {
+                            createdValidBuffer = true;
+                        }
+                        break;
+                    }
+                    default:
+                        createdValidBuffer = false;
+                }
+
+                if(cm == ColorModel.getRGBdefault()){
+                    forcedRGB = true;
+                }
+            } else {
+                createdValidBuffer = false;
+            }
+        } catch(Exception e) {
+            createdValidBuffer = false;
+        }
+
+        if (createdValidBuffer == false) {
+            cm = ColorModel.getRGBdefault();
+            raster = cm.createCompatibleWritableRaster(width, height);
+            iData = accessor.getDataInt(raster.getDataBuffer());
+            bData = null;
+            forcedRGB = true;
+        }
+    }
+}
diff --git a/awt/java/awt/image/BufferedImageOp.java b/awt/java/awt/image/BufferedImageOp.java
new file mode 100644
index 0000000..85b9f4e
--- /dev/null
+++ b/awt/java/awt/image/BufferedImageOp.java
@@ -0,0 +1,86 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Alexey A. Petrenko
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import java.awt.RenderingHints;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * The BufferedImageOp interface provides methods for performing transformations
+ * from source data to destination data for BufferedImage objects. An object
+ * implementing this interface can be passed into a BufferedImageFilter 
+ * to operate on a BufferedImage.
+ */
+public interface BufferedImageOp {
+    
+    /**
+     * Creates a destination image with the specified BufferedImage and
+     * ColorModel; this destination image is empty and has the correct size 
+     * and number of bands.   
+     * 
+     * @param src the source BufferedImage.
+     * @param destCM the destination ColorModel.
+     * 
+     * @return the BufferedImage.
+     */
+    public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel destCM);
+
+    /**
+     * Performs a filter operation on the source BufferedImage and stores 
+     * the resulting BufferedImage to the destination BufferedImage. If 
+     * the destination BufferedImage is null, a BufferedImage with an 
+     * appropriate ColorModel is created.
+     * 
+     * @param src the source BufferedImage.
+     * @param dest the destination BufferedImage, where the result is stored.
+     * 
+     * @return the filtered BufferedImage.
+     */
+    public BufferedImage filter(BufferedImage src, BufferedImage dest);
+
+    /**
+     * Gets the bounds of filtered image.
+     * 
+     * @param src the source BufferedImage to be filtered.
+     * 
+     * @return the rectangle bounds of filtered image.
+     */
+    public Rectangle2D getBounds2D(BufferedImage src);
+
+    /**
+     * Gets the point of the destination image which corresponds
+     * to the specified point in the source image. 
+     * 
+     * @param srcPt the point of the source image.
+     * @param dstPt the point where the result will be stored.
+     * 
+     * @return the destination point.
+     */
+    public Point2D getPoint2D(Point2D srcPt, Point2D dstPt);
+
+    /**
+     * Gets the RenderingHints of the BufferedImageOp.
+     * 
+     * @return the RenderingHints of the BufferedImageOp.
+     */
+    public RenderingHints getRenderingHints();
+}
diff --git a/awt/java/awt/image/ByteLookupTable.java b/awt/java/awt/image/ByteLookupTable.java
new file mode 100644
index 0000000..043b533
--- /dev/null
+++ b/awt/java/awt/image/ByteLookupTable.java
@@ -0,0 +1,134 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ *
+ * @date: Oct 14, 2005
+ */
+
+package java.awt.image;
+
+/**
+ * The ByteLookupTable class provides functionality for lookup operations, 
+ * and is defined by an input byte array for bands or components of 
+ * image and an offset value.
+ * The offset value will be subtracted from the input values before 
+ * indexing the input arrays. The output of a lookup operation is 
+ * represented as an array of unsigned bytes.
+ */
+public class ByteLookupTable extends LookupTable {
+    
+    /** The data. */
+    private byte data[][];
+    
+    /**
+     * Instantiates a new ByteLookupTable with the specified offset value
+     * and the specified byte array which represents the lookup table for
+     * all bands.
+     * 
+     * @param offset the offset value.
+     * @param data the data array of bytes.
+     */
+    public ByteLookupTable(int offset, byte[] data) {
+        super(offset, 1);
+        if (data.length < 1)
+            throw new IllegalArgumentException("Length of data should not be less then one");
+        this.data = new byte[1][data.length];
+        // The data array stored as a reference
+        this.data[0] = data;
+    }
+
+    /**
+     * Instantiates a new ByteLookupTable with the specified offset value
+     * and the specified byte array of arrays which represents the lookup table
+     * for each band.
+     * 
+     * @param offset the offset value.
+     * @param data the data array of bytes array for each band.
+     */
+    public ByteLookupTable(int offset, byte[][] data) {
+        super(offset, data.length);
+        this.data = new byte[data.length][data[0].length];
+        for (int i = 0; i < data.length; i++) {
+            // The data array for each band stored as a reference
+            this.data[i] = data[i];
+        }
+    }
+
+    /**
+     * Gets the lookup table of this ByteLookupTable object. If 
+     * this ByteLookupTable object has one byte array for all bands, 
+     * the returned array length is one.
+     * 
+     * @return the lookup table of this ByteLookupTable object.
+     */
+    public final byte[][] getTable() {
+        // Returns data by reference
+        return data;
+    }
+
+    @Override
+    public int[] lookupPixel(int[] src, int[] dst) {
+        if (dst == null) {
+            dst = new int[src.length];
+        }
+
+        int offset = getOffset();
+        if (getNumComponents() == 1) {
+            for (int i = 0; i < src.length; i++) {
+                dst[i] = data[0][src[i]-offset];
+            }
+        } else {
+            for (int i = 0; i < getNumComponents(); i++) {
+                dst[i] = data[i][src[i]-offset];
+            }
+        }
+
+        return dst;
+    }
+
+    /**
+     * Returns a byte array which contains samples of the specified
+     * pixel which is translated with the lookup table of this 
+     * ByteLookupTable object. The resulted array is stored to
+     * the dst array.
+     * 
+     * @param src the source array.
+     * @param dst the destination array where the result can be stored.
+     * 
+     * @return the byte array of translated samples of a pixel.
+     */
+    public byte[] lookupPixel(byte[] src, byte[] dst) {
+        if (dst == null) {
+            dst = new byte[src.length];
+        }
+
+        int offset = getOffset();
+        if (getNumComponents() == 1) {
+            for (int i = 0; i < src.length; i++) {
+                dst[i] = data[0][src[i]-offset];
+            }
+        } else {
+            for (int i = 0; i < getNumComponents(); i++) {
+                dst[i] = data[i][src[i]-offset];
+            }
+        }
+
+        return dst;
+    }
+}
diff --git a/awt/java/awt/image/ColorConvertOp.java b/awt/java/awt/image/ColorConvertOp.java
new file mode 100644
index 0000000..6d503d7
--- /dev/null
+++ b/awt/java/awt/image/ColorConvertOp.java
@@ -0,0 +1,711 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/** 
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ */  
+package java.awt.image;
+
+
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.awt.RenderingHints;
+import java.awt.color.ColorSpace;
+import java.awt.color.ICC_ColorSpace;
+import java.awt.color.ICC_Profile;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.util.ArrayList;
+
+import org.apache.harmony.awt.gl.color.ColorConverter;
+import org.apache.harmony.awt.gl.color.ColorScaler;
+import org.apache.harmony.awt.gl.color.ICC_Transform;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The ColorConvertOp class converts the pixels of the data in the
+ * source image with the specified ColorSpace objects or an array 
+ * of ICC_Profile objects. The result pixels are scaled to the precision
+ * of the destination image.
+ */
+public class ColorConvertOp implements BufferedImageOp, RasterOp {
+    // Unused but required by interfaces
+    /** The rendering hints. */
+    RenderingHints renderingHints;
+        
+    // Sequence consisting of ColorSpace and ICC_Profile elements
+    /** The conversion sequence. */
+    Object conversionSequence[] = new ICC_Profile[0]; // To eliminate checks for null
+    
+    // Not null if ColorConvertOp is constructed from the array of ICC profiles
+    /** The mid profiles. */
+    private ICC_Profile midProfiles[];   
+
+    /** The cc. */
+    private final ColorConverter cc = new ColorConverter();
+    
+    /** The t creator. */
+    private final ICC_TransfomCreator tCreator = new ICC_TransfomCreator();
+    
+    /** The is icc. */
+    private boolean isICC = true;
+    
+    
+    // Cached ICC_Transform
+    /**
+     * The Class ICC_TransfomCreator.
+     */
+    private class ICC_TransfomCreator {
+        
+        /** The transform. */
+        private ICC_Transform transform;
+        
+        /** The max components. */
+        private int maxComponents;
+        
+        /**
+         * For the full ICC case.
+         * 
+         * @param src the src
+         * @param dst the dst
+         * @param convSeq the conv seq
+         * 
+         * @return the transform
+         */
+        public ICC_Transform getTransform(ICC_Profile src, ICC_Profile dst, ICC_Profile convSeq[]) {
+            if (transform != null &&
+               src == transform.getSrc() && 
+               dst == transform.getDst()) {
+                return transform;
+            }
+            
+            int length = convSeq.length;
+            int srcFlg = 0, dstFlg = 0;
+            
+            if (length == 0 || src != convSeq[0]) {
+                if (src != null) {
+                    srcFlg = 1; // need src profile
+                }
+            }
+            if (length == 0 || dst != convSeq[length-1]) {
+                if (dst != null) {
+                    dstFlg = 1; // need dst profile
+                }
+            }
+            
+            ICC_Profile profiles[];
+            int nProfiles = length + srcFlg + dstFlg;
+            if (nProfiles == length) {
+                profiles = convSeq;
+            } else {
+                profiles = new ICC_Profile[nProfiles];
+                int pos = 0;
+                if (srcFlg != 0) {
+                    profiles[pos++] = src;
+                }
+                for (int i=0; i<length; i++) {
+                    profiles[pos++] = convSeq[i];
+                }
+                if (dstFlg != 0) {
+                    profiles[pos++] = dst;
+                }
+            }
+            
+            return transform = new ICC_Transform(profiles);
+        }
+        
+        /**
+         * Used only when there are non-ICC color spaces.
+         * Returns sequence of non-ICC color spaces and ICC transforms
+         * made from src, dst and conversionSequence.
+         * 
+         * @param src the src
+         * @param dst the dst
+         * 
+         * @return the sequence
+         */
+        public Object[] getSequence(Object src, Object dst) {
+            ArrayList<Object> profiles = new ArrayList<Object>(10);
+            ArrayList<Object> sequence = new ArrayList<Object>(10);         
+
+            // We need this profile anyway
+            ICC_Profile xyzProfile = ICC_Profile.getInstance(ColorSpace.CS_CIEXYZ);
+
+            Object conversionFirst = null, conversionLast = null;
+            int conversionLength = conversionSequence.length;
+            if (conversionLength > 0) {
+                conversionFirst = conversionSequence[0];
+                conversionLast = conversionSequence[conversionLength-1];
+            }
+
+            boolean iccSequenceStarted = false;
+            
+            if (src != conversionFirst && src != null) {
+                if (src instanceof ICC_Profile) {
+                    profiles.add(src);
+                    iccSequenceStarted = true;
+                } else {
+                    profiles.add(xyzProfile);
+                    sequence.add(src); // Add non-ICC color space to the sequence
+                } 
+            } else {
+                profiles.add(xyzProfile);
+            }
+            
+            for (int i=0; i<conversionLength; i++) {
+                if (conversionSequence[i] instanceof ICC_Profile) {
+                    profiles.add(conversionSequence[i]);
+                    iccSequenceStarted = true;
+                } else if (iccSequenceStarted) {
+                    profiles.add(xyzProfile);
+                    
+                    // Eliminate same profiles if there are any
+                    // (e.g. xyzProfile may occur several times)
+                    Object prev = profiles.get(0);
+                    for (int k=1; k<profiles.size(); k++) {                     
+                        if (prev == profiles.get(k)) {
+                            k--;
+                            profiles.remove(k);
+                        }
+                        prev = profiles.get(k);
+                    }
+                    
+                    // If only one profile left we skip the transform -
+                    // it can be only CIEXYZ
+                    if (profiles.size() > 1) {
+                        sequence.add(new ICC_Transform(profiles.toArray(new ICC_Profile[0])));
+
+                        // Add non-ICC color space to the sequence
+                        sequence.add(conversionSequence[i]);
+                    }
+                    
+                    profiles.clear();
+                    profiles.add(xyzProfile);
+                    iccSequenceStarted = false; // Sequence of ICC profiles is processed
+                } else { // Add non-ICC color space to the sequence
+                    sequence.add(conversionSequence[i]); 
+                }               
+            }
+            
+            if (dst != conversionLast && dst != null) { // Add last profile if needed
+                if (dst instanceof ICC_Profile) {
+                    profiles.add(dst);
+                    iccSequenceStarted = true;
+                } else if (iccSequenceStarted) {
+                    profiles.add(xyzProfile);
+                } else {
+                    sequence.add(dst); // Add last non-ICC color space to the sequence
+                }
+            }
+            
+            if (iccSequenceStarted) { // Make last transform if needed
+                sequence.add(new ICC_Transform(profiles.toArray(new ICC_Profile[0])));
+                if (dst != null && !(dst instanceof ICC_Profile)) {
+                    sequence.add(dst); // Add last non-ICC color space to the
+                                        // sequence
+                }
+            }
+
+            // Calculate max number of components
+            // This number will be used for memory allocation
+            maxComponents = 0;
+            Object o;           
+            for (int i=0, size = sequence.size(); i<size; i++) {
+                o = sequence.get(i);
+                if (o instanceof ICC_Transform) {
+                    ICC_Transform t = (ICC_Transform) o; 
+                    maxComponents = 
+                        (maxComponents > t.getNumInputChannels() + 1) ?
+                            maxComponents : 
+                            t.getNumInputChannels() + 1;
+                    maxComponents = 
+                        (maxComponents > t.getNumOutputChannels() + 1) ?
+                            maxComponents : 
+                            t.getNumOutputChannels() + 1;
+                } else {
+                    ColorSpace cs = (ColorSpace) o;
+                    maxComponents = 
+                        (maxComponents > cs.getNumComponents() + 1) ?
+                            maxComponents : 
+                            cs.getNumComponents() + 1;
+                }               
+            }
+            
+            return sequence.toArray();
+        }
+    }
+    
+    /**
+     * Instantiates a new ColorConvertOp object using two specified
+     * ColorSpace objects.
+     * 
+     * @param srcCS the source ColorSpace.
+     * @param dstCS the destination ColorSpace.
+     * @param hints the RenderingHints object used for 
+     * the color conversion, or null.
+     */
+    public ColorConvertOp(ColorSpace srcCS, ColorSpace dstCS, RenderingHints hints) {
+        if (srcCS == null || dstCS == null) {
+            throw new NullPointerException(Messages.getString("awt.25B")); //$NON-NLS-1$
+        }
+        
+        renderingHints = hints;
+        
+        boolean srcICC = srcCS instanceof ICC_ColorSpace;
+        boolean dstICC = dstCS instanceof ICC_ColorSpace;
+        
+        if (srcICC && dstICC) {
+            conversionSequence = new ICC_Profile[2];
+        } else {
+            conversionSequence = new Object[2];
+            isICC = false;
+        }
+        
+        if (srcICC) {
+            conversionSequence[0] = ((ICC_ColorSpace) srcCS).getProfile();
+        } else {
+            conversionSequence[0] = srcCS;
+        }
+        
+        if (dstICC) {
+            conversionSequence[1] = ((ICC_ColorSpace) dstCS).getProfile();
+        } else {
+            conversionSequence[1] = dstCS;
+        }
+    }
+
+    /**
+     * Instantiates a new ColorConvertOp object from the specified 
+     * ICC_Profile objects.
+     * 
+     * @param profiles the array of ICC_Profile objects.
+     * @param hints the RenderingHints object used for 
+     * the color conversion, or null.
+     */
+    public ColorConvertOp(ICC_Profile profiles[], RenderingHints hints) {
+        if (profiles == null) {
+            throw new NullPointerException(Messages.getString("awt.25C")); //$NON-NLS-1$
+        }
+
+        renderingHints = hints;
+        
+        // This array is not used in the program logic, so don't need to copy it
+        // Store it only to return back
+        midProfiles = profiles;  
+        
+        conversionSequence = new ICC_Profile[midProfiles.length];
+        
+        // Add profiles to the conversion sequence
+        for (int i=0, length=midProfiles.length; i<length; i++) {
+            conversionSequence[i] = midProfiles[i];
+        }       
+    }
+
+    /**
+     * Instantiates a new ColorConvertOp object using the specified
+     * ColorSpace object.
+     * 
+     * @param cs the destination ColorSpace or an intermediate ColorSpace.
+     * @param hints the RenderingHints object used for 
+     * the color conversion, or null.
+     */
+    public ColorConvertOp(ColorSpace cs, RenderingHints hints) {
+        if (cs == null) {
+            throw new NullPointerException(Messages.getString("awt.25B")); //$NON-NLS-1$
+        }
+        
+        renderingHints = hints;
+                        
+        if (cs instanceof ICC_ColorSpace) {
+            conversionSequence = new ICC_Profile[1];
+            conversionSequence[0] = ((ICC_ColorSpace) cs).getProfile();
+        } else {
+            conversionSequence = new Object[1];
+            conversionSequence[0] = cs;
+            isICC = false;
+        }
+    }
+
+    /**
+     * Instantiates a new ColorConvertOp object which converts from 
+     * a source color space to a destination color space.
+     * 
+     * @param hints the RenderingHints object used for 
+     * the color conversion, or null.
+     */
+    public ColorConvertOp(RenderingHints hints) {
+        renderingHints = hints;
+    }
+
+    public final WritableRaster filter(Raster src, WritableRaster dst) {
+        if (conversionSequence.length < 2) {
+            throw new IllegalArgumentException(Messages.getString("awt.25D")); //$NON-NLS-1$
+        }
+
+        ICC_Profile srcPf = null, dstPf = null; // unused if isICC is false
+        int nSrcColorComps, nDstColorComps;
+        Object first = conversionSequence[0];
+        Object last = conversionSequence[conversionSequence.length - 1];
+        
+        // Get the number of input/output color components
+        if (isICC) {
+            srcPf = (ICC_Profile) first;
+            dstPf = (ICC_Profile) last;
+            nSrcColorComps = srcPf.getNumComponents();
+            nDstColorComps = dstPf.getNumComponents();
+        } else {
+            if (first instanceof ICC_Profile) {
+                srcPf = (ICC_Profile) first;
+                nSrcColorComps = srcPf.getNumComponents();
+            } else {
+                nSrcColorComps = ((ColorSpace) first).getNumComponents();
+            }
+            
+            if (last instanceof ICC_Profile) {
+                dstPf = (ICC_Profile) last;
+                nDstColorComps = dstPf.getNumComponents();
+            } else {
+                nDstColorComps = ((ColorSpace) last).getNumComponents();
+            }
+        }
+
+        // Check that source and destination rasters are compatible with
+        // transforms and with each other
+        if (src.getNumBands() != nSrcColorComps) {
+            // awt.25E=Incorrect number of source raster bands. Should be equal
+            //          to the number of color components of source colorspace.
+            throw new IllegalArgumentException(Messages.getString("awt.25E")); //$NON-NLS-1$
+        }
+        
+        if (dst != null) { // Check destination raster
+            if (dst.getNumBands() !=
+                nDstColorComps) {
+                // awt.25F=Incorrect number of destination raster bands. Should
+                //          be equal to the number of color components of destination
+                //          colorspace.
+                throw new IllegalArgumentException(Messages.getString("awt.25F")); //$NON-NLS-1$
+            }
+            
+            if (src.getWidth() != dst.getWidth() ||
+               src.getHeight() != dst.getHeight()) {
+                throw new IllegalArgumentException(Messages.getString("awt.260")); //$NON-NLS-1$
+            }
+            
+        } else {
+          dst = createCompatibleDestRaster(src);
+        }
+        
+        if (isICC) {
+            // Create transform
+            ICC_Transform t = tCreator.getTransform(srcPf, dstPf, 
+                    (ICC_Profile[])conversionSequence); 
+            cc.translateColor(t, src, dst);         
+        } else {
+            Object[] sequence = tCreator.getSequence(null, null);
+            
+            // Get data from the source raster
+            ColorScaler scaler = new ColorScaler();
+            scaler.loadScalingData(src, null);
+            float tmpData[][] = scaler.scaleNormalize(src);
+            
+            // Get source and destination color spaces
+            ColorSpace srcCS = (srcPf == null) ? 
+                    (ColorSpace) first:
+                    new ICC_ColorSpace(srcPf);
+            ColorSpace dstCS = (dstPf == null) ? 
+                    (ColorSpace) last:
+                    new ICC_ColorSpace(dstPf);
+                    
+            applySequence(sequence, tmpData, srcCS, dstCS);
+            
+            scaler.loadScalingData(dst, null);
+            scaler.unscaleNormalized(dst, tmpData);
+        }
+
+        return dst;
+    }
+
+    public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel destCM) {
+        // If destination color model is passed only one line needed
+        if (destCM != null) {
+            return new BufferedImage(destCM,
+                    destCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight()),
+                    destCM.isAlphaPremultiplied(), 
+                    null);
+        }
+        
+        int nSpaces = conversionSequence.length;
+        
+        if (nSpaces < 1) {
+            throw new IllegalArgumentException(Messages.getString("awt.261")); //$NON-NLS-1$
+        }
+        
+        // Get destination color space
+        Object destination = conversionSequence[nSpaces-1];
+        ColorSpace dstCS = 
+            (destination instanceof ColorSpace) ? 
+                    (ColorSpace) destination : 
+                    new ICC_ColorSpace((ICC_Profile) destination);
+        
+        ColorModel srcCM = src.getColorModel();     
+        ColorModel dstCM = new ComponentColorModel(dstCS, 
+                srcCM.hasAlpha(), 
+                srcCM.isAlphaPremultiplied(),
+                srcCM.getTransparency(),
+                srcCM.getTransferType());
+        
+        return new BufferedImage(dstCM,
+                destCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight()),
+                destCM.isAlphaPremultiplied(), 
+                null);
+    }
+
+    public final BufferedImage filter(BufferedImage src, BufferedImage dst) {
+        if (dst == null && conversionSequence.length < 1) {
+            throw new IllegalArgumentException(Messages.getString("awt.262")); //$NON-NLS-1$
+        }
+
+        ColorModel srcCM = src.getColorModel();
+        // First handle index color model
+        if (srcCM instanceof IndexColorModel) {            
+            src = ((IndexColorModel) srcCM).convertToIntDiscrete(src.getRaster(), false);
+        }
+        ColorSpace srcCS = srcCM.getColorSpace();        
+                
+        BufferedImage res;
+        boolean isDstIndex = false;
+        if (dst != null) {
+          
+          if (src.getWidth() != dst.getWidth() ||
+             src.getHeight() != dst.getHeight()) {
+              throw new IllegalArgumentException(Messages.getString("awt.263")); //$NON-NLS-1$
+          }
+
+            if (dst.getColorModel() instanceof IndexColorModel) {
+                isDstIndex = true;
+                res = createCompatibleDestImage(src, null);
+            } else {                
+                res = dst;
+            }           
+        } else {
+            res = createCompatibleDestImage(src, null);
+        }
+        ColorModel dstCM = res.getColorModel();
+        ColorSpace dstCS = dstCM.getColorSpace();
+        
+        ICC_Profile srcPf = null, dstPf = null;
+        if (srcCS instanceof ICC_ColorSpace) {
+            srcPf = ((ICC_ColorSpace)srcCS).getProfile();
+        }
+        if (dstCS instanceof ICC_ColorSpace) {
+            dstPf = ((ICC_ColorSpace)dstCS).getProfile();
+        }
+        
+        boolean isFullICC = isICC && srcPf != null && dstPf != null;
+        
+        if (isFullICC) {
+            ICC_Transform t =
+                    tCreator.getTransform(srcPf, dstPf, (ICC_Profile[]) conversionSequence);
+            cc.translateColor(t, src, res);
+        } else { // Perform non-ICC transform
+            Object sequence[] = tCreator.getSequence(
+                    srcPf == null ? (Object) srcCS : srcPf,
+                    dstPf == null ? (Object) dstCS : dstPf);            
+            
+            int srcW = src.getWidth();
+            int srcH = src.getHeight();
+            int numPixels = srcW*srcH;
+
+            // Load all pixel data into array tmpData 
+            float tmpData[][] = 
+                new float[numPixels][tCreator.maxComponents];
+            for (int row=0, dataPos=0; row<srcW; row++) {
+                for (int col=0; col<srcH; col++) {
+                    tmpData[dataPos] = 
+                        srcCM.getNormalizedComponents(
+                                src.getRaster().getDataElements(row, col, null), 
+                                tmpData[dataPos], 0);
+                    dataPos++;
+                }
+            }
+
+            // Copy alpha channel if needed
+            float alpha[] = null;
+            int alphaIdx = srcCM.numComponents - 1;
+            if (srcCM.hasAlpha() && dstCM.hasAlpha()) {
+                alpha = new float[numPixels];
+                for (int i=0; i<numPixels; i++) {
+                    alpha[i] = tmpData[i][alphaIdx];
+                }
+            }
+            
+            // Translate colors
+            applySequence(sequence, tmpData, srcCS, dstCS);
+
+            // Copy alpha if needed
+            if (dstCM.hasAlpha()) {
+                alphaIdx = dstCM.numComponents - 1;
+                if (alpha != null) {
+                    for (int i=0; i<numPixels; i++) {
+                        tmpData[i][alphaIdx] = alpha[i];
+                    }                   
+                } else {
+                    for (int i=0; i<numPixels; i++) {
+                        tmpData[i][alphaIdx] = 1f;
+                    }                                       
+                }
+            }
+            
+            // Store data back to the image            
+            for (int row=0, dataPos=0; row<srcW; row++) {
+                for (int col=0; col<srcH; col++) {
+                    res.getRaster().setDataElements(row, col, 
+                            dstCM.getDataElements(tmpData[dataPos++], 0 , null));
+                }
+            }
+        }               
+
+        if (isDstIndex) { // Convert image into indexed color
+            Graphics2D g2d = dst.createGraphics();
+            g2d.drawImage(res, 0, 0, null);
+            g2d.dispose();
+            return dst;
+        }
+        
+        return res;
+    }
+
+    /**
+     * Apply sequence.
+     * 
+     * @param sequence the sequence
+     * @param tmpData the tmp data
+     * @param srcCS the src cs
+     * @param dstCS the dst cs
+     */
+    private void applySequence(
+            Object sequence[], 
+            float tmpData[][],
+            ColorSpace srcCS, 
+            ColorSpace dstCS
+            ) {
+        ColorSpace xyzCS = ColorSpace.getInstance(ColorSpace.CS_CIEXYZ);
+        
+        int numPixels = tmpData.length;
+        
+        // First transform...
+        if (sequence[0] instanceof ICC_Transform) { // ICC
+            ICC_Transform t = (ICC_Transform)sequence[0];
+            cc.translateColor(t, tmpData, srcCS, xyzCS, numPixels);
+        } else { // non ICC
+            for (int k=0; k<numPixels; k++) {
+                tmpData[k] = srcCS.toCIEXYZ(tmpData[k]); 
+            }
+            cc.loadScalingData(xyzCS); // prepare for scaling XYZ
+        }
+        
+        for (Object element : sequence) {
+            if (element instanceof ICC_Transform) {
+                ICC_Transform t = (ICC_Transform)element;
+                cc.translateColor(t, tmpData, null, null, numPixels);
+            } else {
+                ColorSpace cs = (ColorSpace) element;
+                for (int k=0; k<numPixels; k++) {
+                    tmpData[k] = cs.fromCIEXYZ(tmpData[k]);
+                    tmpData[k] = cs.toCIEXYZ(tmpData[k]); 
+                }
+            }
+        }
+        
+        // Last transform...
+        if (sequence[sequence.length-1] instanceof ICC_Transform) { // ICC
+            ICC_Transform t = (ICC_Transform)sequence[sequence.length-1];
+            cc.translateColor(t, tmpData, xyzCS, dstCS, numPixels);
+        } else { // non ICC
+            for (int k=0; k<numPixels; k++) {
+                tmpData[k] = dstCS.fromCIEXYZ(tmpData[k]); 
+            }
+        }
+    }
+
+    public final Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
+        if (dstPt != null) {
+            dstPt.setLocation(srcPt);
+            return dstPt;
+        }
+        return new Point2D.Float((float) srcPt.getX(), (float) srcPt.getY());
+    }
+
+    public WritableRaster createCompatibleDestRaster(Raster src) {
+        int nComps = 0;
+        int nSpaces = conversionSequence.length;
+        
+        if (nSpaces < 2) {
+            throw new IllegalArgumentException(Messages.getString("awt.261")); //$NON-NLS-1$
+        }
+        
+        Object lastCS = conversionSequence[nSpaces-1];
+        if (lastCS instanceof ColorSpace) {
+            nComps = ((ColorSpace) lastCS).getNumComponents();
+        } else {
+            nComps = ((ICC_Profile) lastCS).getNumComponents(); 
+        }
+        
+        // Calculate correct data type
+        int dstDataType = src.getDataBuffer().getDataType();
+        if (dstDataType != DataBuffer.TYPE_BYTE &&
+           dstDataType != DataBuffer.TYPE_SHORT) {
+                dstDataType = DataBuffer.TYPE_SHORT;
+        }
+        
+        return Raster.createInterleavedRaster(
+                dstDataType, 
+                src.getWidth(),
+                src.getHeight(),
+                nComps,
+                new Point(src.getMinX(), src.getMinY())
+            );
+    }
+
+    public final Rectangle2D getBounds2D(Raster src) {
+        return src.getBounds();
+    }
+
+    public final Rectangle2D getBounds2D(BufferedImage src) {
+        return src.getRaster().getBounds();
+    }
+
+    /**
+     * Gets an array of ICC_Profiles objects which constructs
+     * this ColorConvertOp object or returns null if this ColorConvertOp 
+     * is not constructed from array of ICC_Profiles.
+     * 
+     * @return an array of ICC_Profiles objects which constructs
+     * this ColorConvertOp object or returns null if this ColorConvertOp 
+     * is not constructed from array of ICC_Profiles.
+     */
+    public final ICC_Profile[] getICC_Profiles() {
+        if (midProfiles != null) {
+            return midProfiles;
+        }
+        return null;
+    }
+
+    public final RenderingHints getRenderingHints() {
+        return renderingHints;
+    }    
+}
diff --git a/awt/java/awt/image/ColorModel.java b/awt/java/awt/image/ColorModel.java
new file mode 100644
index 0000000..945c087
--- /dev/null
+++ b/awt/java/awt/image/ColorModel.java
@@ -0,0 +1,911 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import java.awt.Transparency;
+import java.awt.color.ColorSpace;
+import java.util.Arrays;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Class ColorModel.
+ */
+public abstract class ColorModel implements Transparency {
+
+    /** The pixel_bits. */
+    protected int pixel_bits;  // Pixel length in bits
+
+    /** The transfer type. */
+    protected int transferType;
+
+    /** The cs. */
+    ColorSpace cs;
+
+    /** The has alpha. */
+    boolean hasAlpha;
+
+    /** The is alpha premultiplied. */
+    boolean isAlphaPremultiplied;
+
+    /** The transparency. */
+    int transparency;
+
+    /** The num color components. */
+    int numColorComponents;
+
+    /** The num components. */
+    int numComponents;
+
+    /** The bits. */
+    int[] bits;             // Array of components masks 
+
+    /** The max values. */
+    int[] maxValues = null; // Max values that may be represent by color
+                            // components
+
+    /** The max bit length. */
+    int maxBitLength;       // Max length color components in bits
+
+    /** The RG bdefault. */
+    private static ColorModel RGBdefault;
+
+    /**
+     * Instantiates a new color model with the specified values.
+     * 
+     * @param pixel_bits the pixel length in bits
+     * @param bits the array of component masks
+     * @param cspace the colorspace
+     * @param hasAlpha whether the color model has alpha
+     * @param isAlphaPremultiplied whether the alpha is premultiplied
+     * @param transparency the transparency strategy, @see java.awt.Transparency
+     * @param transferType the transfer type (primitive java type 
+     * to use for the components)
+     */
+    protected ColorModel(int pixel_bits, int[] bits, ColorSpace cspace,
+            boolean hasAlpha, boolean isAlphaPremultiplied, int transparency,
+            int transferType) {
+
+        if (pixel_bits < 1) {
+            // awt.26B=The number of bits in the pixel values is less than 1
+            throw new IllegalArgumentException(Messages.getString("awt.26B")); //$NON-NLS-1$
+        }
+
+        if (bits == null) {
+            // awt.26C=bits is null
+            throw new NullPointerException(Messages.getString("awt.26C")); //$NON-NLS-1$
+        }
+
+        int sum = 0;
+        for (int element : bits) {
+            if (element < 0) {
+                // awt.26D=The elements in bits is less than 0
+                throw new IllegalArgumentException(Messages.getString("awt.26D")); //$NON-NLS-1$
+            }
+            sum += element;
+        }
+
+        if (sum < 1) {
+            // awt.26E=The sum of the number of bits in bits is less than 1
+            throw new NullPointerException(Messages.getString("awt.26E")); //$NON-NLS-1$
+        }
+
+        if (cspace == null) {
+            // awt.26F=The cspace is null
+            throw new IllegalArgumentException(Messages.getString("awt.26F")); //$NON-NLS-1$
+        }
+
+        if (transparency < Transparency.OPAQUE ||
+               transparency > Transparency.TRANSLUCENT) {
+            // awt.270=The transparency is not a valid value
+            throw new IllegalArgumentException(Messages.getString("awt.270")); //$NON-NLS-1$
+        }
+
+        this.pixel_bits = pixel_bits;
+        this.bits = bits.clone();
+
+        maxValues = new int[bits.length];
+        maxBitLength = 0;
+        for (int i = 0; i < maxValues.length; i++) {
+            maxValues[i] = (1 << bits[i]) - 1;
+            if (bits[i] > maxBitLength) {
+                maxBitLength = bits[i];
+            }
+        }
+
+        cs = cspace;
+        this.hasAlpha = hasAlpha;
+        this.isAlphaPremultiplied = isAlphaPremultiplied;
+        numColorComponents = cs.getNumComponents();
+
+        if (hasAlpha) {
+            numComponents = numColorComponents + 1;
+        } else {
+            numComponents = numColorComponents;
+        }
+
+        this.transparency = transparency;
+        this.transferType = transferType;
+
+    }
+
+    /**
+     * Instantiates a new color model with the specified pixel bit depth.
+     * The transferType is chosen based on the pixel bits, and the other
+     * data fields are given default values.
+     * 
+     * @param bits the array of component masks
+     */
+    public ColorModel(int bits) {
+
+        if (bits < 1) {
+            // awt.271=The number of bits in bits is less than 1
+            throw new IllegalArgumentException(Messages.getString("awt.271")); //$NON-NLS-1$
+        }
+
+        pixel_bits = bits;
+        transferType = getTransferType(bits);
+        cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
+        hasAlpha = true;
+        isAlphaPremultiplied = false;
+        transparency = Transparency.TRANSLUCENT;
+
+        numColorComponents = 3;
+        numComponents = 4;
+
+        this.bits = null;
+    }
+
+    /**
+     * Gets the data elements from the specified component array, transforming
+     * them according to rules of the color model.
+     * 
+     * @param components the components
+     * @param offset the offset in the normComponents array
+     * @param obj the array that the result is written to: an array of values
+     * whose length must be the number of components used by the color model and 
+     * whose type depends on the transfer type (based on the pixel bit depth),
+     * or null to have the appropriate array created
+     * 
+     * @return the array of data elements
+     */
+    public Object getDataElements(int[] components, int offset, Object obj) {
+        throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
+                "supported by this ColorModel"); //$NON-NLS-1$
+    }
+
+    /**
+     * Gets the data elements from the specified array of normalized components.
+     * 
+     * @param normComponents the array normalized components
+     * @param normOffset the offset in the normComponents array
+     * @param obj the array that the result is written to: an array of values
+     * whose length must be the number of components used by the color model and 
+     * whose type depends on the transfer type (based on the pixel bit depth),
+     * or null to have the appropriate array created
+     * 
+     * @return the array of data elements
+     */
+    public Object getDataElements(float[] normComponents, int normOffset,
+            Object obj) {
+        int unnormComponents[] = getUnnormalizedComponents(normComponents,
+                normOffset, null, 0);
+        return getDataElements(unnormComponents, 0, obj);
+    }
+
+    /**
+     * Gets the data elements corresponding to the pixel determined by the 
+     * RGB data.
+     * 
+     * @param rgb the rgb int that defines the pixel
+     * @param pixel the array that the result is written to: an array of values
+     * whose length must be the number of components used by the color model and 
+     * whose type depends on the transfer type (based on the pixel bit depth),
+     * or null to have the appropriate array created
+     * 
+     * @return the array of data elements
+     */
+    public Object getDataElements(int rgb, Object pixel) {
+        throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
+                "supported by this ColorModel"); //$NON-NLS-1$
+    }
+
+    /**
+     * Gets the child raster corresponding to the alpha channel of the 
+     * specified writable raster, or null if alpha is not supported.
+     * 
+     * @param raster the raster
+     * 
+     * @return the alpha raster
+     */
+    public WritableRaster getAlphaRaster(WritableRaster raster) {
+        return null;
+    }
+
+    /**
+     * Creates a new color model by coercing the data in the writable raster 
+     * in accordance with the alpha strategy of this color model.
+     * 
+     * @param raster the raster
+     * @param isAlphaPremultiplied whether the alpha is premultiplied in this 
+     * color model
+     * 
+     * @return the new color model
+     */
+    public ColorModel coerceData(WritableRaster raster,
+            boolean isAlphaPremultiplied) {
+        throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
+                "supported by this ColorModel"); //$NON-NLS-1$
+    }
+
+    @Override
+    public String toString() {
+        // The output format based on 1.5 release behaviour. 
+        // It could be reveled such way:
+        // ColorModel cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB,
+        // false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
+        // System.out.println(cm.toString());
+        return "ColorModel: Color Space = " + cs.toString() + "; has alpha = " //$NON-NLS-1$ //$NON-NLS-2$
+                + hasAlpha + "; is alpha premultipied = " //$NON-NLS-1$
+                + isAlphaPremultiplied + "; transparency = " + transparency //$NON-NLS-1$
+                + "; number color components = " + numColorComponents //$NON-NLS-1$
+                + "; pixel bits = " + pixel_bits + "; transfer type = " //$NON-NLS-1$ //$NON-NLS-2$
+                + transferType;
+    }
+
+    /**
+     * Gets the components of the pixel determined by the data array.
+     * 
+     * @param pixel the data array that defines the pixel (whose 
+     * primitive type corresponds to the pixel length in bits, 
+     * @see ColorModel#getTransferType()
+     * @param components the the array where the resulting components
+     * are written (or null to prompt the method to create the return array)
+     * @param offset the offset that tells where the results should be written
+     * in the return array
+     * 
+     * @return the array of components
+     */
+    public int[] getComponents(Object pixel, int[] components, int offset) {
+        throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
+                "supported by this ColorModel"); //$NON-NLS-1$
+    }
+
+    /**
+     * Gets the normalized components of the pixel determined by the data array.
+     * 
+     * @param pixel the data array that defines the pixel (whose 
+     * primitive type corresponds to the pixel length in bits, 
+     * @see ColorModel#getTransferType()
+     * @param normComponents the array where the resulting normalised components
+     * are written (or null to prompt the method to create the return array)
+     * @param normOffset the offset that tells where the results should be written
+     * in the return array
+     * 
+     * @return the array of normalized components
+     */
+    public float[] getNormalizedComponents(Object pixel,
+            float[] normComponents, int normOffset) {
+
+        if (pixel == null) {
+            // awt.294=pixel is null
+            throw new NullPointerException(Messages.getString("awt.294")); //$NON-NLS-1$
+        }
+
+        int unnormComponents[] = getComponents(pixel, null, 0);
+        return getNormalizedComponents(unnormComponents, 0, normComponents,
+                normOffset);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof ColorModel)) {
+            return false;
+        }
+        ColorModel cm = (ColorModel) obj;
+
+        return (pixel_bits == cm.getPixelSize() &&
+               transferType == cm.getTransferType() &&
+               cs.getType() == cm.getColorSpace().getType() &&
+               hasAlpha == cm.hasAlpha() &&
+               isAlphaPremultiplied == cm.isAlphaPremultiplied() &&
+               transparency == cm.getTransparency() &&
+               numColorComponents == cm.getNumColorComponents() &&
+               numComponents == cm.getNumComponents() &&
+               Arrays.equals(bits, cm.getComponentSize()));
+    }
+
+    /**
+     * Gets the red component of the pixel determined by the data array.
+     * 
+     * @param inData the data array that defines the pixel (whose 
+     * primitive type corresponds to the pixel length in bits, 
+     * @see ColorModel#getTransferType()
+     * 
+     * @return the red
+     */
+    public int getRed(Object inData) {
+        return getRed(constructPixel(inData));
+    }
+
+    /**
+     * Gets the RGB int corresponding to the pixel defined by the data array.
+     * 
+     * @param inData the data array that defines the pixel (whose 
+     * primitive type corresponds to the pixel length in bits, 
+     * @see ColorModel#getTransferType()
+     * 
+     * @return the int that gives the pixel's colors in RGB format
+     */
+    public int getRGB(Object inData) {
+        return (getAlpha(inData) << 24 | getRed(inData) << 16 |
+               getGreen(inData) << 8 | getBlue(inData));
+    }
+
+    /**
+     * Gets the green component of the pixel defined by the data array.
+     * 
+     * @param inData the data array that defines the pixel (whose 
+     * primitive type corresponds to the pixel length in bits, 
+     * @see ColorModel#getTransferType()
+     * 
+     * @return the green
+     */
+    public int getGreen(Object inData) {
+        return getGreen(constructPixel(inData));
+    }
+
+    /**
+     * Gets the blue component of the pixel defined by the data array.
+     * 
+     * @param inData the data array that defines the pixel (whose 
+     * primitive type corresponds to the pixel length in bits, 
+     * @see ColorModel#getTransferType()
+     * 
+     * @return the blue
+     */
+    public int getBlue(Object inData) {
+        return getBlue(constructPixel(inData));
+    }
+
+    /**
+     * Gets the alpha component of the pixel defined by the data array.
+     * 
+     * @param inData the data array that defines the pixel (whose 
+     * primitive type corresponds to the pixel length in bits, 
+     * @see ColorModel#getTransferType()
+     * 
+     * @return the alpha
+     */
+    public int getAlpha(Object inData) {
+        return getAlpha(constructPixel(inData));
+    }
+
+    /**
+     * Creates a compatible writable raster.
+     * 
+     * @param w the width of the desired writable raster
+     * @param h the height of the desired writable raster
+     * 
+     * @return the writable raster
+     */
+    public WritableRaster createCompatibleWritableRaster(int w, int h) {
+        throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
+                "supported by this ColorModel"); //$NON-NLS-1$
+    }
+
+    /**
+     * Checks if the sample model is compatible with this color model.
+     * 
+     * @param sm the sample model
+     * 
+     * @return true, if the sample model is compatible with this color model
+     */
+    public boolean isCompatibleSampleModel(SampleModel sm) {
+        throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
+                "supported by this ColorModel"); //$NON-NLS-1$
+    }
+
+    /**
+     * Creates the compatible sample model.
+     * 
+     * @param w the width of the desired sample model
+     * @param h the height of the desired sample model
+     * 
+     * @return the sample model
+     */
+    public SampleModel createCompatibleSampleModel(int w, int h) {
+        throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
+                "supported by this ColorModel"); //$NON-NLS-1$
+    }
+
+    /**
+     * Checks if the specified raster is compatible with this color model.
+     * 
+     * @param raster the raster to inspect
+     * 
+     * @return true, if the raster is compatible with this color model
+     */
+    public boolean isCompatibleRaster(Raster raster) {
+        throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
+                "supported by this ColorModel"); //$NON-NLS-1$
+    }
+
+    /**
+     * Gets the color space of this color model.
+     * 
+     * @return the color space
+     */
+    public final ColorSpace getColorSpace() {
+        return cs;
+    }
+
+    /**
+     * Gets the normalized components corresponding to the specified 
+     * unnormalized components.
+     * 
+     * @param components the array of unnormalized components
+     * @param offset the offset where the components should be read 
+     * from the array of unnormalized components
+     * @param normComponents the array where the resulting normalised components
+     * are written (or null to prompt the method to create the return array)
+     * @param normOffset the offset that tells where the results should be written
+     * in the return array
+     * 
+     * @return the normalized components
+     */
+    public float[] getNormalizedComponents(int[] components, int offset,
+            float normComponents[], int normOffset) {
+        if (bits == null) {
+            // awt.26C=bits is null
+            throw new UnsupportedOperationException(Messages.getString("awt.26C")); //$NON-NLS-1$
+        }
+
+        if (normComponents == null) {
+            normComponents = new float[numComponents + normOffset];
+        }
+
+        if (hasAlpha && isAlphaPremultiplied) {
+            float normAlpha =
+                (float) components[offset + numColorComponents] /
+                    maxValues[numColorComponents];
+            if (normAlpha != 0.0f) {
+                for (int i = 0; i < numColorComponents; i++) {
+                    normComponents[normOffset + i] =
+                        components[offset + i] /
+                            (normAlpha * maxValues[i]);
+                }
+                normComponents[normOffset + numColorComponents] = normAlpha;
+            } else {
+                for (int i = 0; i < numComponents; i++) {
+                    normComponents[normOffset + i] = 0.0f;
+                }
+            }
+        } else {
+            for (int i = 0; i < numComponents; i++) {
+                normComponents[normOffset + i] =
+                    (float) components[offset + i] /
+                        maxValues[i];
+            }
+        }
+
+        return normComponents;
+    }
+
+    /**
+     * Gets the data element corresponding to the unnormalized components.
+     * 
+     * @param components the components
+     * @param offset the offset to start reading the components from the 
+     * array of components
+     * 
+     * @return the data element
+     */
+    public int getDataElement(int[] components, int offset) {
+        throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
+                "supported by this ColorModel"); //$NON-NLS-1$
+    }
+
+    /**
+     * Gets the unnormalized components corresponding to the specified 
+     * normalized components.
+     * 
+     * @param normComponents the array of normalized components
+     * @param normOffset the offset where the components should be read 
+     * from the array of normalized components
+     * @param components the array where the resulting unnormalised components
+     * are written (or null to prompt the method to create the return array)
+     * @param offset the offset that tells where the results should be written
+     * in the return array
+     * 
+     * @return the unnormalized components
+     */
+    public int[] getUnnormalizedComponents(float normComponents[],
+            int normOffset, int components[], int offset) {
+
+        if (bits == null) {
+            // awt.26C=bits is null
+            throw new UnsupportedOperationException(Messages.getString("awt.26C")); //$NON-NLS-1$
+        }
+
+        if (normComponents.length - normOffset < numComponents) {
+            // awt.273=The length of normComponents minus normOffset is less than numComponents
+            throw new IllegalArgumentException(Messages.getString("awt.273")); //$NON-NLS-1$
+        }
+
+        if (components == null) {
+            components = new int[numComponents + offset];
+        } else {
+            if (components.length - offset < numComponents) {
+                // awt.272=The length of components minus offset is less than numComponents
+                throw new IllegalArgumentException(Messages.getString("awt.272")); //$NON-NLS-1$
+            }
+        }
+
+        if (hasAlpha && isAlphaPremultiplied) {
+            float alpha = normComponents[normOffset + numColorComponents];
+            for (int i = 0; i < numColorComponents; i++) {
+                components[offset + i] = (int) (normComponents[normOffset + i]
+                        * maxValues[i] * alpha + 0.5f);
+            }
+            components[offset + numColorComponents] =
+                (int) (normComponents[normOffset + numColorComponents] *
+                        maxValues[numColorComponents] + 0.5f);
+        } else {
+            for (int i = 0; i < numComponents; i++) {
+                components[offset + i] =
+                    (int) (normComponents[normOffset + i] *
+                            maxValues[i] + 0.5f);
+            }
+        }
+
+        return components;
+    }
+
+    /**
+     * Gets the data element corresponding to the normalized components.
+     * 
+     * @param normComponents the normalized components
+     * @param normOffset the offset where the normalized components should
+     * be read from the normalized component array
+     * 
+     * @return the data element
+     */
+    public int getDataElement(float normComponents[], int normOffset) {
+        int unnormComponents[] = getUnnormalizedComponents(normComponents,
+                normOffset, null, 0);
+        return getDataElement(unnormComponents, 0);
+    }
+
+    /**
+     * Takes a pixel whose data is defined by an int, and writes the 
+     * corresponding components into the components array, starting 
+     * from the index offset.
+     * 
+     * @param pixel the pixel data
+     * @param components the data array to write the components to (or
+     * null to have the method create the return array)
+     * @param offset the offset that determines where the results are 
+     * written in the components array
+     * 
+     * @return the array of components corresponding to the pixel
+     */
+    public int[] getComponents(int pixel, int components[], int offset) {
+        throw new UnsupportedOperationException("This method is not " + //$NON-NLS-1$
+                "supported by this ColorModel"); //$NON-NLS-1$
+    }
+
+    /**
+     * Gets the red component of the pixel determined by the pixel data.
+     * 
+     * @param pixel the pixel data
+     * 
+     * @return the red component of the pixel
+     */
+    public abstract int getRed(int pixel);
+
+    /**
+     * Takes the pixel data and returns the int corresponding 
+     * to the pixel's color in RGB format.
+     * 
+     * @param pixel the pixel data
+     * 
+     * @return the corresponding RGB int
+     */
+    public int getRGB(int pixel) {
+        return (getAlpha(pixel) << 24 | getRed(pixel) << 16
+                | getGreen(pixel) << 8 | getBlue(pixel));
+    }
+
+    /**
+     * Gets the green component of the pixel determined by the pixel data.
+     * 
+     * @param pixel the pixel data
+     * 
+     * @return the green component of the pixel
+     */
+    public abstract int getGreen(int pixel);
+
+    /**
+     * Gets the size of the desired component of this color model.
+     * 
+     * @param componentIdx the index that determines which component size to get
+     * 
+     * @return the component size corresponding to the index
+     * 
+     * @throws NullPointerException if this color model doesn't support
+     * an array of separate components.
+     * @throws ArrayIndexOutOfBoundsException if the index is negative or
+     * greater than or equal to the number of components
+     */
+    public int getComponentSize(int componentIdx) {
+        if (bits == null) {
+            // awt.26C=bits is null
+            throw new NullPointerException(Messages.getString("awt.26C")); //$NON-NLS-1$
+        }
+
+        if (componentIdx < 0 || componentIdx >= bits.length) {
+            // awt.274=componentIdx is greater than the number of components or less than zero
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.274")); //$NON-NLS-1$
+        }
+
+        return bits[componentIdx];
+    }
+
+    /**
+     * Gets the blue component of the pixel determined by the pixel data.
+     * 
+     * @param pixel the pixel
+     * 
+     * @return the blue component of the pixel
+     */
+    public abstract int getBlue(int pixel);
+
+    /**
+     * Gets the alpha component of the pixel determined by the pixel data.
+     * 
+     * @param pixel the pixel
+     * 
+     * @return the alpha component of the pixel
+     */
+    public abstract int getAlpha(int pixel);
+
+    /**
+     * Gets the array of sizes of the different components.
+     * 
+     * @return the array of sizes of the different components
+     */
+    public int[] getComponentSize() {
+        if (bits != null) {
+            return bits.clone();
+        }
+        return null;
+    }
+
+    /**
+     * Checks if the alpha component is premultiplied.
+     * 
+     * @return true, if the alpha component is premultiplied
+     */
+    public final boolean isAlphaPremultiplied() {
+        return isAlphaPremultiplied;
+    }
+
+    /**
+     * Checks whether this color model supports alpha.
+     * 
+     * @return true, if this color model has alpha
+     */
+    public final boolean hasAlpha() {
+        return hasAlpha;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 0;
+        int tmp;
+
+        if (hasAlpha) {
+            hash ^= 1;
+            hash <<= 8;
+        }
+        if (isAlphaPremultiplied) {
+            hash ^= 1;
+            hash <<= 8;
+        }
+
+        tmp = hash >>> 24;
+        hash ^= numColorComponents;
+        hash <<= 8;
+        hash |= tmp;
+
+        tmp = hash >>> 24;
+        hash ^= transparency;
+        hash <<= 8;
+        hash |= tmp;
+
+        tmp = hash >>> 24;
+        hash ^= cs.getType();
+        hash <<= 8;
+        hash |= tmp;
+
+        tmp = hash >>> 24;
+        hash ^= pixel_bits;
+        hash <<= 8;
+        hash |= tmp;
+
+        tmp = hash >>> 24;
+        hash ^= transferType;
+        hash <<= 8;
+        hash |= tmp;
+
+        if (bits != null) {
+
+            for (int element : bits) {
+                tmp = hash >>> 24;
+                hash ^= element;
+                hash <<= 8;
+                hash |= tmp;
+            }
+
+        }
+
+        return hash;
+    }
+
+    public int getTransparency() {
+        return transparency;
+    }
+
+    /**
+     * Gets the transfer type, which is the type of Java primitive
+     * value that corresponds to the bit length per pixel: either 
+     * {@link DataBuffer#TYPE_BYTE}, {@link DataBuffer#TYPE_USHORT}, 
+     * {@link DataBuffer#TYPE_INT}, or {@link DataBuffer#TYPE_UNDEFINED}.
+     * 
+     * @return the transfer type
+     */
+    public final int getTransferType() {
+        return transferType;
+    }
+
+    /**
+     * Gets the pixel size in bits.
+     * 
+     * @return the pixel size
+     */
+    public int getPixelSize() {
+        return pixel_bits;
+    }
+
+    /**
+     * Gets the number of components of this color model.
+     * 
+     * @return the number of components
+     */
+    public int getNumComponents() {
+        return numComponents;
+    }
+
+    /**
+     * Gets the number of color components of this color model.
+     * 
+     * @return the number color components
+     */
+    public int getNumColorComponents() {
+        return numColorComponents;
+    }
+
+    /**
+     * Gets the default RGB color model.
+     * 
+     * @return the default RGB color model
+     */
+    public static ColorModel getRGBdefault() {
+        if (RGBdefault == null) {
+            RGBdefault = new DirectColorModel(32, 0x00ff0000, 0x0000ff00,
+                    0x000000ff, 0xff000000);
+        }
+        return RGBdefault;
+    }
+
+    /*
+     * Construct INT pixel representation from Object
+     * @param obj
+     *
+     * @return
+     */
+    /**
+     * Construct pixel.
+     * 
+     * @param obj the obj
+     * 
+     * @return the int
+     */
+    private int constructPixel(Object obj) {
+        int pixel = 0;
+
+        switch (getTransferType()) {
+
+        case DataBuffer.TYPE_BYTE:
+            byte[] bPixel = (byte[]) obj;
+            if(bPixel.length > 1) {
+                // awt.275=This pixel representation is not suuported by tis Color Model
+                throw new UnsupportedOperationException(Messages.getString("awt.275")); //$NON-NLS-1$
+            }
+            pixel = bPixel[0] & 0xff;
+            break;
+
+        case DataBuffer.TYPE_USHORT:
+            short[] sPixel = (short[]) obj;
+            if(sPixel.length > 1) {
+                // awt.275=This pixel representation is not suuported by tis Color Model
+                throw new UnsupportedOperationException(Messages.getString("awt.275")); //$NON-NLS-1$
+            }
+            pixel = sPixel[0] & 0xffff;
+            break;
+
+        case DataBuffer.TYPE_INT:
+            int[] iPixel = (int[]) obj;
+            if(iPixel.length > 1) {
+                // awt.275=This pixel representation is not suuported by tis Color Model
+                throw new UnsupportedOperationException(Messages.getString("awt.275")); //$NON-NLS-1$
+            }
+            pixel = iPixel[0];
+            break;
+
+        default:
+            // awt.22D=This transferType ( {0} ) is not supported by this color model
+            throw new UnsupportedOperationException(Messages.getString("awt.22D", //$NON-NLS-1$
+                   transferType));
+
+        }
+        return pixel;
+    }
+
+    /**
+     * Gets the transfer type, which is the type of Java primitive
+     * value that corresponds to the bit length per pixel: either 
+     * {@link DataBuffer#TYPE_BYTE}, {@link DataBuffer#TYPE_USHORT}, 
+     * {@link DataBuffer#TYPE_INT}, or {@link DataBuffer#TYPE_UNDEFINED}.
+     * 
+     * @param bits the array of component masks
+     * 
+     * @return the transfer type
+     */
+    static int getTransferType(int bits) {
+        if (bits <= 8) {
+            return DataBuffer.TYPE_BYTE;
+        } else if (bits <= 16) {
+            return DataBuffer.TYPE_USHORT;
+        } else if (bits <= 32) {
+            return DataBuffer.TYPE_INT;
+        } else {
+            return DataBuffer.TYPE_UNDEFINED;
+        }
+    }
+
+    @Override
+    public void finalize() {
+        // This method is added for the API compatibility
+        // Don't need to call super since Object's finalize is always empty
+    }
+}
diff --git a/awt/java/awt/image/ComponentColorModel.java b/awt/java/awt/image/ComponentColorModel.java
new file mode 100644
index 0000000..a152f55
--- /dev/null
+++ b/awt/java/awt/image/ComponentColorModel.java
@@ -0,0 +1,1471 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import java.awt.color.ColorSpace;
+
+import org.apache.harmony.awt.gl.color.LUTColorConverter;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Class ComponentColorModel represents a color model that is defined 
+ * in terms of its components.
+ */
+public class ComponentColorModel extends ColorModel {
+
+    /** The signed. */
+    private boolean signed;   // Pixel samples are signed.
+                              // Samples with TransferType DataBuffer.TYPE_BYTE,
+                              // DataBuffer.TYPE_USHORT, DataBuffer.TYPE_INT - 
+                              // unsigned. Samples with others TransferType - 
+                              // signed.
+
+    /** The integral. */
+    private boolean integral; // Pixel samples are integral.
+                              // Samples with TransferType DataBuffer.TYPE_BYTE,
+                              // DataBuffer.TYPE_USHORT, DataBuffer.Short and 
+                              // DataBuffer.TYPE_INT - integral.
+
+    /** The scale factors. */
+    private float scaleFactors[]; // Array of factors for reduction components 
+                                  // values into the form scaled from 0 to 255
+
+    /** The donot support unnormalized. */
+    private boolean donotSupportUnnormalized; // This Color Model don't support
+                                              // unnormolized form 
+
+    /** The need alpha divide. */
+    private boolean needAlphaDivide; // hasAlpha && isAlphaPremultiplied
+
+    /** The calc value. */
+    private boolean calcValue;       // Value was culculated
+
+    /** The need scale. */
+    private boolean needScale;       // Normalized value need to scale
+
+    /** The min vals. */
+    private float minVals[];         // Array of Min normalized values
+
+    /** The ranges. */
+    private float ranges[];          // Array of range normalized values  
+
+    /** The alpha lut. */
+    private byte alphaLUT[];         // Lookup table for scale alpha value
+
+    /** The color lu ts. */
+    private byte colorLUTs[][];      // Lookup tables for scale color values
+
+    /** The from_ linea r_ rg b_ lut. */
+    private byte from_LINEAR_RGB_LUT[];  // Lookup table for conversion from
+                                         // Linear RGB Color Space into sRGB
+
+    /** The to_ linea r_8 rg b_ lut. */
+    private byte to_LINEAR_8RGB_LUT[];   // Lookup table for conversion from
+                                         // sRGB Color Space into Linear RGB 
+                                         // 8 bit 
+
+    /** The to_ linea r_16 rg b_ lut. */
+    private short to_LINEAR_16RGB_LUT[]; // Lookup table for conversion from
+                                         // sRGB Color Space into Linear RGB 
+                                         // 16 bit 
+
+    /** The LINEA r_ rg b_ length. */
+    private int LINEAR_RGB_Length;       // Linear RGB bit length
+
+    /** The factor. */
+    private float fFactor;               // Scale factor
+
+    /** The is_s rgb. */
+    private boolean is_sRGB;             // ColorModel has sRGB ColorSpace  
+
+    /** The is_ linea r_ rgb. */
+    private boolean is_LINEAR_RGB;       // Color Model has Linear RGB Color 
+                                         // Space 
+
+    /**
+     * Instantiates a new component color model.
+     * 
+     * @param colorSpace the color space
+     * @param bits the array of component masks
+     * @param hasAlpha whether the color model has alpha
+     * @param isAlphaPremultiplied whether the alpha is premultiplied
+     * @param transparency the transparency strategy, @see java.awt.Transparency
+     * @param transferType the transfer type (primitive java type 
+     * to use for the components)
+     */
+     public ComponentColorModel(ColorSpace colorSpace, int bits[],
+            boolean hasAlpha, boolean isAlphaPremultiplied, int transparency,
+            int transferType) {
+        super(createPixelBits(colorSpace, hasAlpha, transferType),
+                validateBits(bits, colorSpace, hasAlpha, transferType),
+                colorSpace, hasAlpha, isAlphaPremultiplied, transparency,
+                transferType);
+
+        needScale = false;
+        switch (transferType) {
+        case DataBuffer.TYPE_BYTE:
+        case DataBuffer.TYPE_USHORT:
+        case DataBuffer.TYPE_INT:
+            signed = false;
+            integral = true;
+            donotSupportUnnormalized = false;
+            scaleFactors = new float[numComponents];
+            for (int i = 0; i < numColorComponents; i++) {
+                scaleFactors[i] = 1.0f / maxValues[i];
+                if (cs.getMinValue(i) != 0.0f || cs.getMaxValue(i) != 1.0f) {
+                    donotSupportUnnormalized = true;
+                }
+            }
+            if (hasAlpha) {
+                maxValues[numColorComponents] =
+                    (1 << bits[numColorComponents]) - 1;
+                scaleFactors[numColorComponents] =
+                    1.0f / maxValues[numColorComponents];
+            }
+            break;
+        case DataBuffer.TYPE_SHORT:
+            signed = true;
+            integral = true;
+            donotSupportUnnormalized = true;
+            scaleFactors = new float[numComponents];
+            for (int i = 0; i < numComponents; i++) {
+                maxValues[i] = Short.MAX_VALUE;
+                scaleFactors[i] = 1.0f / maxValues[i];
+                if (cs.getMinValue(i) != 0.0f || cs.getMaxValue(i) != 1.0f) {
+                    needScale = true;
+                }
+            }
+            if (needScale) {
+                minVals = new float[numColorComponents];
+                ranges = new float[numColorComponents];
+                for (int i = 0; i < numColorComponents; i++) {
+                    minVals[i] = cs.getMinValue(i);
+                    ranges[i] = cs.getMaxValue(i) - minVals[i];
+                }
+            }
+            break;
+        case DataBuffer.TYPE_FLOAT:
+        case DataBuffer.TYPE_DOUBLE:
+            signed = true;
+            integral = false;
+            donotSupportUnnormalized = true;
+            break;
+        default:
+            // awt.215=transferType is not one of DataBuffer.TYPE_BYTE,
+            //          DataBuffer.TYPE_USHORT, DataBuffer.TYPE_INT,
+            //          DataBuffer.TYPE_SHORT, DataBuffer.TYPE_FLOAT, or
+            //          DataBuffer.TYPE_DOUBLE
+            throw new IllegalArgumentException(Messages.getString("awt.215")); //$NON-NLS-1$
+        }
+
+        needAlphaDivide = hasAlpha && isAlphaPremultiplied;
+        initLUTs();
+    }
+
+    /**
+     * Instantiates a new component color model.
+     * 
+     * @param colorSpace the color space
+     * @param hasAlpha whether the color model has alpha
+     * @param isAlphaPremultiplied whether the alpha is premultiplied
+     * @param transparency the transparency strategy, @see java.awt.Transparency
+     * @param transferType the transfer type (primitive java type 
+     * to use for the components)
+     */
+    public ComponentColorModel(ColorSpace colorSpace, boolean hasAlpha,
+            boolean isAlphaPremultiplied, int transparency, int transferType) {
+        
+        this(colorSpace, 
+                createPixelBitsArray(colorSpace, hasAlpha, transferType), 
+                hasAlpha, 
+                isAlphaPremultiplied, 
+                transparency,
+                transferType);
+    }
+
+    /**
+     * Validate bits.
+     * 
+     * @param bits the bits
+     * @param colorSpace the color space
+     * @param hasAlpha the has alpha
+     * @param transferType the transfer type
+     * 
+     * @return the int[]
+     */
+    private static int[] validateBits(int bits[], ColorSpace colorSpace,
+            boolean hasAlpha, int transferType) {
+        if (bits != null) {
+            return bits;
+        }
+
+        int numComponents = colorSpace.getNumComponents();
+        if (hasAlpha) {
+            numComponents++;
+        }
+        bits = new int[numComponents];
+
+        int componentLength = DataBuffer.getDataTypeSize(transferType);
+
+        for (int i = 0; i < numComponents; i++) {
+            bits[i] = componentLength;
+        }
+
+        return bits;
+    }
+
+    /**
+     * Creates the pixel bits.
+     * 
+     * @param colorSpace the color space
+     * @param hasAlpha the has alpha
+     * @param transferType the transfer type
+     * 
+     * @return the int
+     */
+    private static int createPixelBits(ColorSpace colorSpace, boolean hasAlpha,
+            int transferType) {
+        int numComponents = colorSpace.getNumComponents();
+        if (hasAlpha) {
+            numComponents++;
+        }
+        int componentLength = DataBuffer.getDataTypeSize(transferType);
+        return numComponents * componentLength;
+    }
+
+    /**
+     * Creates the pixel bits array.
+     * 
+     * @param colorSpace the color space
+     * @param hasAlpha the has alpha
+     * @param transferType the transfer type
+     * 
+     * @return the int[]
+     */
+    private static int[] createPixelBitsArray(ColorSpace colorSpace, 
+            boolean hasAlpha, int transferType) {
+        
+        int numComponents = colorSpace.getNumComponents();
+        if (hasAlpha) {
+            numComponents++;
+        }
+
+        int bits[] = new int[numComponents];
+        for(int i = 0; i < numComponents; i++){
+            bits[i] = DataBuffer.getDataTypeSize(transferType);
+        }
+        return bits;
+    }
+
+    @Override
+    public Object getDataElements(int components[], int offset, Object obj) {
+        if (donotSupportUnnormalized) {
+            // awt.213=This ComponentColorModel does not support the unnormalized form
+            throw new IllegalArgumentException(Messages.getString("awt.213")); //$NON-NLS-1$
+        }
+
+        if (offset + numComponents > components.length) {
+            // awt.216=The components array is not large enough to hold all the color and alpha components
+            throw new IllegalArgumentException(Messages.getString("awt.216")); //$NON-NLS-1$
+        }
+
+        switch (transferType) {
+        case DataBuffer.TYPE_BYTE:
+            byte ba[];
+            if (obj == null) {
+                ba = new byte[numComponents];
+            } else {
+                ba = (byte[]) obj;
+            }
+            for (int i = 0, idx = offset; i < numComponents; i++, idx++) {
+                ba[i] = (byte) components[idx];
+            }
+            return ba;
+        case DataBuffer.TYPE_USHORT:
+            short sa[];
+            if (obj == null) {
+                sa = new short[numComponents];
+            } else {
+                sa = (short[]) obj;
+            }
+            for (int i = 0, idx = offset; i < numComponents; i++, idx++) {
+                sa[i] = (short) components[idx];
+            }
+            return sa;
+        case DataBuffer.TYPE_INT:
+            int ia[];
+            if (obj == null) {
+                ia = new int[numComponents];
+            } else {
+                ia = (int[]) obj;
+            }
+            for (int i = 0, idx = offset; i < numComponents; i++, idx++) {
+                ia[i] = components[idx];
+            }
+            return ia;
+        default:
+            // awt.217=The transfer type of this ComponentColorModel is not one
+            //          of the following transfer types: DataBuffer.TYPE_BYTE,
+            //          DataBuffer.TYPE_USHORT, or DataBuffer.TYPE_INT
+            throw new UnsupportedOperationException(Messages
+                    .getString("awt.217")); //$NON-NLS-1$
+        }
+    }
+
+    @Override
+    public Object getDataElements(float normComponents[], int normOffset,
+            Object obj) {
+        if (needScale) {
+            for (int i = 0, idx = 0; i < numColorComponents; i++, idx++) {
+                normComponents[idx] =
+                    (normComponents[idx] - minVals[i]) / ranges[i];
+            }
+        }
+
+        switch (transferType) {
+        case DataBuffer.TYPE_BYTE:
+            byte ba[];
+            if (obj == null) {
+                ba = new byte[numComponents];
+            } else {
+                ba = (byte[]) obj;
+            }
+
+            if (needAlphaDivide) {
+                float alpha = normComponents[normOffset + numColorComponents];
+                for (int i = 0, idx = normOffset; i < numColorComponents;
+                    i++, idx++) {
+                    ba[i] = (byte) (normComponents[idx] * alpha *
+                            maxValues[i] + 0.5f);
+                }
+                ba[numColorComponents] =
+                    (byte) (normComponents[normOffset + numColorComponents] *
+                            maxValues[numColorComponents] + 0.5f);
+            } else {
+                for (int i = 0, idx = normOffset; i < numComponents;
+                    i++, idx++) {
+                    ba[idx] =
+                        (byte) (normComponents[idx] * maxValues[i] + 0.5f);
+                }
+            }
+            return ba;
+
+        case DataBuffer.TYPE_USHORT:
+            short usa[];
+            if (obj == null) {
+                usa = new short[numComponents];
+            } else {
+                usa = (short[]) obj;
+            }
+
+            if (needAlphaDivide) {
+                float alpha = normComponents[normOffset + numColorComponents];
+                for (int i = 0, idx = 0; i < numColorComponents; i++, idx++) {
+                    usa[i] = (short) (normComponents[idx] * alpha *
+                            maxValues[i] + 0.5f);
+                }
+                usa[numColorComponents] = (short) (alpha *
+                        maxValues[numColorComponents] + 0.5f);
+            } else {
+                for (int i = 0, idx = normOffset; i < numComponents;
+                    i++, idx++) {
+                    usa[i] = (short) (normComponents[idx] *
+                            maxValues[i] + 0.5f);
+                }
+            }
+            return usa;
+
+        case DataBuffer.TYPE_INT:
+            int ia[];
+            if (obj == null) {
+                ia = new int[numComponents];
+            } else {
+                ia = (int[]) obj;
+            }
+
+            if (needAlphaDivide) {
+                float alpha = normComponents[normOffset + numColorComponents];
+                for (int i = 0, idx = 0; i < numColorComponents; i++, idx++) {
+                    ia[i] = (int) (normComponents[idx] * alpha *
+                            maxValues[i] + 0.5f);
+                }
+                ia[numColorComponents] = (int) (alpha *
+                        maxValues[numColorComponents] + 0.5f);
+            } else {
+                for (int i = 0, idx = normOffset; i < numComponents;
+                    i++, idx++) {
+                    ia[i] = (int) (normComponents[idx] * maxValues[i] + 0.5f);
+                }
+            }
+            return ia;
+
+        case DataBuffer.TYPE_SHORT:
+            short sa[];
+            if (obj == null) {
+                sa = new short[numComponents];
+            } else {
+                sa = (short[]) obj;
+            }
+
+            if (needAlphaDivide) {
+                float alpha = normComponents[normOffset + numColorComponents];
+                for (int i = 0, idx = 0; i < numColorComponents; i++, idx++) {
+                    sa[i] = (short) (normComponents[idx] * alpha *
+                            maxValues[i] + 0.5f);
+                }
+                sa[numColorComponents] = (short) (alpha *
+                        maxValues[numColorComponents] + 0.5f);
+            } else {
+                for (int i = 0, idx = normOffset; i < numComponents;
+                    i++, idx++) {
+                    sa[i] = (short) (normComponents[idx] *
+                            maxValues[i] + 0.5f);
+                }
+            }
+            return sa;
+
+        case DataBuffer.TYPE_FLOAT:
+            float fa[];
+            if (obj == null) {
+                fa = new float[numComponents];
+            } else {
+                fa = (float[]) obj;
+            }
+
+            if (needAlphaDivide) {
+                float alpha = normComponents[normOffset + numColorComponents];
+                for (int i = 0, idx = 0; i < numColorComponents; i++, idx++) {
+                    fa[i] = normComponents[idx] * alpha;
+                }
+                fa[numColorComponents] = alpha;
+            } else {
+                for (int i = 0, idx = normOffset; i < numComponents;
+                    i++, idx++) {
+                    fa[i] = normComponents[idx];
+                }
+            }
+            return fa;
+
+        case DataBuffer.TYPE_DOUBLE:
+            double da[];
+            if (obj == null) {
+                da = new double[numComponents];
+            } else {
+                da = (double[]) obj;
+            }
+
+            if (needAlphaDivide) {
+                double alpha = normComponents[normOffset + numColorComponents];
+                for (int i = 0, idx = 0; i < numColorComponents; i++, idx++) {
+                    da[i] = normComponents[idx] * alpha;
+                }
+                da[numColorComponents] = alpha;
+            } else {
+                for (int i = 0, idx = normOffset; i < numComponents;
+                    i++, idx++) {
+                    da[i] = normComponents[idx];
+                }
+            }
+            return da;
+
+        default:
+            // awt.213=This ComponentColorModel does not support the unnormalized form
+            throw new IllegalArgumentException(Messages.getString("awt.213")); //$NON-NLS-1$
+        }
+    }
+
+    @Override
+    public Object getDataElements(int rgb, Object pixel) {
+        float normComp[];
+        float comp[];
+
+        int red = (rgb >> 16) & 0xff;
+        int green = (rgb >> 8) & 0xff;
+        int blue = rgb & 0xff;
+        int alpha = (rgb >> 24) & 0xff;
+
+        comp = new float[3];
+        if (is_sRGB || is_LINEAR_RGB) {
+            if (is_LINEAR_RGB) {
+                if (LINEAR_RGB_Length == 8) {
+                    red = to_LINEAR_8RGB_LUT[red] & 0xff;
+                    green = to_LINEAR_8RGB_LUT[green] & 0xff;
+                    blue = to_LINEAR_8RGB_LUT[blue] & 0xff;
+                } else {
+                    red = to_LINEAR_16RGB_LUT[red] & 0xffff;
+                    green = to_LINEAR_16RGB_LUT[green] & 0xffff;
+                    blue = to_LINEAR_16RGB_LUT[blue] & 0xffff;
+                }
+            }
+            comp[0] = red / fFactor;
+            comp[1] = green / fFactor;
+            comp[2] = blue / fFactor;
+            if (!hasAlpha) {
+                normComp = comp;
+            } else {
+                float normAlpha = alpha / 255.0f;
+                normComp = new float[numComponents];
+                for (int i = 0; i < numColorComponents; i++) {
+                    normComp[i] = comp[i];
+                }
+                normComp[numColorComponents] = normAlpha;
+            }
+        } else {
+            comp[0] = red / fFactor;
+            comp[1] = green / fFactor;
+            comp[2] = blue / fFactor;
+            float[] defComp = cs.fromRGB(comp);
+            if (!hasAlpha) {
+                normComp = defComp;
+            } else {
+                float normAlpha = alpha / 255.0f;
+                normComp = new float[numComponents];
+                for (int i = 0; i < numColorComponents; i++) {
+                    normComp[i] = defComp[i];
+                }
+                normComp[numColorComponents] = normAlpha;
+            }
+        }
+        if(hasAlpha && isAlphaPremultiplied){
+            normComp[0] *= normComp[numColorComponents];
+            normComp[1] *= normComp[numColorComponents];
+            normComp[2] *= normComp[numColorComponents];
+        }
+
+        return getDataElements(normComp, 0, pixel);
+    }
+
+    @Override
+    public WritableRaster getAlphaRaster(WritableRaster raster) {
+        if(!hasAlpha) {
+            return null;
+        }
+
+        int x = raster.getMinX();
+        int y = raster.getMinY();
+        int bandList[] = new int[1];
+        bandList[0] = raster.getNumBands() - 1;
+
+        return raster.createWritableChild(x, y, raster.getWidth(),
+                raster.getHeight(), x, y, bandList);
+    }
+
+    @Override
+    public ColorModel coerceData(WritableRaster raster,
+            boolean isAlphaPremultiplied) {
+        if (!hasAlpha || this.isAlphaPremultiplied == isAlphaPremultiplied) {
+            return this;
+        }
+
+        int minX = raster.getMinX();
+        int minY = raster.getMinY();
+        int w = raster.getWidth();
+        int h = raster.getHeight();
+
+        if (isAlphaPremultiplied) {
+            switch (transferType) {
+            case DataBuffer.TYPE_BYTE:
+            case DataBuffer.TYPE_USHORT:
+            case DataBuffer.TYPE_INT:
+                float alphaFactor = maxValues[numColorComponents];
+                int iComponents[] = null;
+                int iTransparentComponents[] = new int[numComponents];
+                for (int i = 0; i < h; i++, minY++) {
+                    for (int j = 0, x = minX; j < w; j++, x++) {
+                        iComponents = raster.getPixel(x, minY,
+                                iComponents);
+                        if (iComponents[numColorComponents] == 0) {
+                            raster.setPixel(x, minY, iTransparentComponents);
+                        } else {
+                            float alpha =
+                                iComponents[numColorComponents] /
+                                    alphaFactor;
+                            for (int n = 0; n < numColorComponents; n++) {
+                                iComponents[n] =
+                                    (int) (alpha * iComponents[n] + 0.5f);
+                            }
+                            raster.setPixel(x, minY, iComponents);
+                        }
+                    }
+
+                }
+                break;
+
+            case DataBuffer.TYPE_SHORT:
+                float sAlphaFactor = maxValues[numColorComponents];
+                short sComponents[] = null;
+                short sTransparentComponents[] = new short[numComponents];
+                for (int i = 0; i < h; i++, minY++) {
+                    for (int j = 0, x = minX; j < w; j++, x++) {
+                        sComponents = (short[]) raster.getDataElements(x, minY,
+                                sComponents);
+                        if (sComponents[numColorComponents] == 0) {
+                            raster.setDataElements(x, minY,
+                                    sTransparentComponents);
+                        } else {
+                            float alpha =
+                                sComponents[numColorComponents] /
+                                sAlphaFactor;
+                            for (int n = 0; n < numColorComponents; n++) {
+                                sComponents[n] =
+                                    (byte) (alpha * sComponents[n] + 0.5f);
+                            }
+                            raster.setDataElements(x, minY, sComponents);
+                        }
+                    }
+
+                }
+                break;
+
+            case DataBuffer.TYPE_FLOAT:
+                float fComponents[] = null;
+                float fTransparentComponents[] = new float[numComponents];
+                for (int i = 0; i < h; i++, minY++) {
+                    for (int j = 0, x = minX; j < w; j++, x++) {
+                        fComponents = raster.getPixel(x, minY, fComponents);
+                        if (fComponents[numColorComponents] == 0.0f) {
+                            raster.setDataElements(x, minY,
+                                    fTransparentComponents);
+                        } else {
+                            float alpha = fComponents[numColorComponents];
+                            for (int n = 0; n < numColorComponents; n++) {
+                                fComponents[n] = fComponents[n] * alpha;
+                            }
+                            raster.setPixel(x, minY, fComponents);
+                        }
+                    }
+
+                }
+                break;
+
+            case DataBuffer.TYPE_DOUBLE:
+                double dComponents[] = null;
+                double dTransparentComponents[] = new double[numComponents];
+                for (int i = 0; i < h; i++, minY++) {
+                    for (int j = 0, x = minX; j < w; j++, x++) {
+                        dComponents = raster.getPixel(x, minY, dComponents);
+                        if (dComponents[numColorComponents] == 0.0) {
+                            raster.setPixel(x, minY, dTransparentComponents);
+                        } else {
+                            double alpha = dComponents[numColorComponents];
+                            for (int n = 0; n < numColorComponents; n++) {
+                                dComponents[n] = dComponents[n] * alpha;
+                            }
+                            raster.setPixel(x, minY, dComponents);
+                        }
+                    }
+
+                }
+                break;
+
+            default:
+                // awt.219=This transferType is not supported by this color model
+                throw new UnsupportedOperationException(Messages.getString("awt.219")); //$NON-NLS-1$
+            }
+        } else {
+            switch (transferType) {
+            case DataBuffer.TYPE_BYTE:
+            case DataBuffer.TYPE_USHORT:
+            case DataBuffer.TYPE_INT:
+                float alphaFactor = maxValues[numColorComponents];
+                int iComponents[] = null;
+                int iTransparentComponents[] = new int[numComponents];
+                for (int i = 0; i < h; i++, minY++) {
+                    for (int j = 0, x = minX; j < w; j++, x++) {
+                        iComponents = raster.getPixel(x, minY,
+                                iComponents);
+                        if (iComponents[numColorComponents] == 0) {
+                            raster.setPixel(x, minY, iTransparentComponents);
+                        } else {
+                            float alpha =
+                                iComponents[numColorComponents] /
+                                    alphaFactor;
+                            for (int n = 0; n < numColorComponents; n++) {
+                                iComponents[n] =
+                                    (int) (iComponents[n] /
+                                            alpha + 0.5f);
+                            }
+                            raster.setPixel(x, minY, iComponents);
+                        }
+                    }
+
+                }
+                break;
+
+            case DataBuffer.TYPE_SHORT:
+                float sAlphaFactor = maxValues[numColorComponents];
+                short sComponents[] = null;
+                short sTransparentComponents[] = new short[numComponents];
+                for (int i = 0; i < h; i++, minY++) {
+                    for (int j = 0, x = minX; j < w; j++, x++) {
+                        sComponents = (short[]) raster.getDataElements(x, minY,
+                                sComponents);
+                        if (sComponents[numColorComponents] == 0) {
+                            raster.setDataElements(x, minY,
+                                    sTransparentComponents);
+                        } else {
+                            float alpha =
+                                sComponents[numColorComponents] /
+                                    sAlphaFactor;
+                            for (int n = 0; n < numColorComponents; n++) {
+                                sComponents[n] =
+                                    (byte) (sComponents[n] /
+                                            alpha + 0.5f);
+                            }
+                            raster.setDataElements(x, minY, sComponents);
+                        }
+                    }
+
+                }
+                break;
+
+            case DataBuffer.TYPE_FLOAT:
+                float fComponents[] = null;
+                float fTransparentComponents[] = new float[numComponents];
+                for (int i = 0; i < h; i++, minY++) {
+                    for (int j = 0, x = minX; j < w; j++, x++) {
+                        fComponents = raster.getPixel(x, minY, fComponents);
+                        if (fComponents[numColorComponents] == 0.0f) {
+                            raster.setDataElements(x, minY,
+                                    fTransparentComponents);
+                        } else {
+                            float alpha = fComponents[numColorComponents];
+                            for (int n = 0; n < numColorComponents; n++) {
+                                fComponents[n] = fComponents[n] / alpha;
+                            }
+                            raster.setPixel(x, minY, fComponents);
+                        }
+                    }
+
+                }
+                break;
+
+            case DataBuffer.TYPE_DOUBLE:
+                double dComponents[] = null;
+                double dTransparentComponents[] = new double[numComponents];
+                for (int i = 0; i < h; i++, minY++) {
+                    for (int j = 0, x = minX; j < w; j++, x++) {
+                        dComponents = raster.getPixel(x, minY, dComponents);
+                        if (dComponents[numColorComponents] == 0.0) {
+                            raster.setPixel(x, minY, dTransparentComponents);
+                        } else {
+                            double alpha = dComponents[numColorComponents];
+                            for (int n = 0; n < numColorComponents; n++) {
+                                dComponents[n] = dComponents[n] / alpha;
+                            }
+                            raster.setPixel(x, minY, dComponents);
+                        }
+                    }
+
+                }
+                break;
+            default:
+                // awt.219=This transferType is not supported by this color model
+                throw new UnsupportedOperationException(Messages.getString("awt.219")); //$NON-NLS-1$
+            }
+        }
+
+        if (!signed) {
+            return new ComponentColorModel(cs, bits, hasAlpha,
+                    isAlphaPremultiplied, transparency, transferType);
+        }
+
+        return new ComponentColorModel(cs, null, hasAlpha,
+                isAlphaPremultiplied, transparency, transferType);
+    }
+
+    @Override
+    public int[] getComponents(Object pixel, int[] components, int offset) {
+        if (donotSupportUnnormalized) {
+            // awt.213=This ComponentColorModel does not support the unnormalized form
+            throw new IllegalArgumentException(Messages.getString("awt.213")); //$NON-NLS-1$
+        }
+
+        if (components == null) {
+            components = new int[offset + numComponents];
+        } else if (offset + numComponents > components.length) {
+            // awt.218=The components array is not large enough to hold all the color and alpha components
+            throw new IllegalArgumentException(Messages.getString("awt.218")); //$NON-NLS-1$
+        }
+
+        switch (transferType) {
+        case DataBuffer.TYPE_BYTE:
+            byte ba[] = (byte[]) pixel;
+
+            for (int i = 0, idx = offset; i < numComponents; i++, idx++) {
+                components[idx] = ba[i] & 0xff;
+            }
+            return components;
+
+        case DataBuffer.TYPE_USHORT:
+            short sa[] = (short[]) pixel;
+            for (int i = 0, idx = offset; i < numComponents; i++, idx++) {
+                components[idx] = sa[i] & 0xffff;
+            }
+            return components;
+
+        case DataBuffer.TYPE_INT:
+            int ia[] = (int[]) pixel;
+            for (int i = 0, idx = offset; i < numComponents; i++, idx++) {
+                components[idx] = ia[i];
+            }
+            return components;
+
+        default:
+            // awt.217=The transfer type of this ComponentColorModel is not one
+            //          of the following transfer types: DataBuffer.TYPE_BYTE,
+            //          DataBuffer.TYPE_USHORT, or DataBuffer.TYPE_INT
+            throw new UnsupportedOperationException(Messages
+                    .getString("awt.217")); //$NON-NLS-1$
+        }
+
+    }
+
+    @Override
+    public float[] getNormalizedComponents(Object pixel,
+            float normComponents[], int normOffset) {
+
+        if (normComponents == null) {
+            normComponents = new float[numComponents + normOffset];
+        }
+
+        switch (transferType) {
+        case DataBuffer.TYPE_BYTE:
+            byte ba[] = (byte[]) pixel;
+            for (int i = 0, idx = normOffset; i < numComponents; i++, idx++) {
+                normComponents[idx] = (ba[i] & 0xff) * scaleFactors[i];
+            }
+            break;
+
+        case DataBuffer.TYPE_USHORT:
+            short usa[] = (short[]) pixel;
+            for (int i = 0, idx = normOffset; i < numComponents; i++, idx++) {
+                normComponents[idx] = (usa[i] & 0xffff)
+                        * scaleFactors[i];
+            }
+            break;
+
+        case DataBuffer.TYPE_INT:
+            int ia[] = (int[]) pixel;
+            for (int i = 0, idx = normOffset; i < numComponents; i++, idx++) {
+                normComponents[idx] = ia[i] * scaleFactors[i];
+            }
+            break;
+
+        case DataBuffer.TYPE_SHORT:
+            short sa[] = (short[]) pixel;
+            for (int i = 0, idx = normOffset; i < numComponents; i++, idx++) {
+                normComponents[idx] = sa[i] * scaleFactors[i];
+            }
+            break;
+
+        case DataBuffer.TYPE_FLOAT:
+            float fa[] = (float[]) pixel;
+            for (int i = 0, idx = normOffset; i < numComponents; i++, idx++) {
+                normComponents[idx] = fa[i];
+            }
+            break;
+
+        case DataBuffer.TYPE_DOUBLE:
+            double da[] = (double[]) pixel;
+            for (int i = 0, idx = normOffset; i < numComponents; i++, idx++) {
+                normComponents[idx] = (float) da[i];
+            }
+            break;
+
+        default:
+            // awt.21A=This ComponentColorModel does not support this transferType
+            throw new IllegalArgumentException(Messages.getString("awt.21A")); //$NON-NLS-1$
+        }
+
+        if (needAlphaDivide) {
+            float alpha = normComponents[normOffset + numColorComponents];
+            for (int i = 0, idx = normOffset; i < numColorComponents;
+                i++, idx++) {
+                normComponents[idx] /= alpha;
+            }
+        }
+
+        if (needScale) {
+            for (int i = 0, idx = normOffset; i < numColorComponents;
+                i++, idx++) {
+                normComponents[idx] = minVals[i] +
+                    ranges[i] * normComponents[idx];
+            }
+        }
+        return normComponents;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof ComponentColorModel)) {
+            return false;
+        }
+        return super.equals(obj);
+    }
+
+    @Override
+    public int getRed(Object inData) {
+        return getRGBComponent(inData, 0);
+    }
+
+    @Override
+    public int getRGB(Object inData) {
+        int alpha = getAlpha(inData);
+        if (cs.getType() == ColorSpace.TYPE_GRAY) {
+            int gray = getRed(inData);
+            return (alpha << 24 | gray << 16 | gray << 8 | gray);
+        }
+        return (alpha << 24 | getRed(inData) << 16 | getGreen(inData) << 8 |
+                getBlue(inData));
+    }
+
+    @Override
+    public int getGreen(Object inData) {
+        return getRGBComponent(inData, 1);
+    }
+
+    @Override
+    public int getBlue(Object inData) {
+        return getRGBComponent(inData, 2);
+    }
+
+    @Override
+    public int getAlpha(Object inData) {
+        if (!hasAlpha) {
+            return 255;
+        }
+        int alpha = 0;
+
+        switch (transferType) {
+        case DataBuffer.TYPE_BYTE: {
+            byte ba[] = (byte[]) inData;
+            alpha = ba[numColorComponents] & 0xff;
+            if (bits[numColorComponents] != 8) {
+                return alphaLUT[alpha] & 0xff;
+            }
+            return alpha;
+        }
+        case DataBuffer.TYPE_USHORT: {
+            short usa[] = (short[]) inData;
+            alpha = usa[numColorComponents] & 0xffff;
+            if (bits[numColorComponents] != 8) {
+                return alphaLUT[alpha] & 0xff;
+            }
+            return alpha;
+        }
+        case DataBuffer.TYPE_INT: {
+            int ia[] = (int[]) inData;
+            alpha = ia[numColorComponents];
+            if (bits[numColorComponents] != 8) {
+                return alphaLUT[alpha] & 0xff;
+            }
+            return alpha;
+        }
+        case DataBuffer.TYPE_SHORT: {
+            short sa[] = (short[]) inData;
+            alpha = sa[numColorComponents];
+            if (bits[numColorComponents] != 8) {
+                return alphaLUT[alpha] & 0xff;
+            }
+            return alpha;
+        }
+        case DataBuffer.TYPE_FLOAT: {
+            float fa[] = (float[]) inData;
+            return (int) (fa[numColorComponents] * 255.0f + 0.5f);
+        }
+        case DataBuffer.TYPE_DOUBLE: {
+            double da[] = (double[]) inData;
+            return (int) (da[numColorComponents] * 255.0 + 0.5);
+        }
+        default: {
+            // awt.214=This Color Model doesn't support this transferType
+            throw new UnsupportedOperationException(Messages.getString("awt.214")); //$NON-NLS-1$
+        }
+        }
+    }
+
+    @Override
+    public WritableRaster createCompatibleWritableRaster(int w, int h) {
+        SampleModel sm = createCompatibleSampleModel(w, h);
+        DataBuffer db = sm.createDataBuffer();
+        return Raster.createWritableRaster(sm, db, null);
+    }
+
+    @Override
+    public boolean isCompatibleSampleModel(SampleModel sm) {
+        if (!(sm instanceof ComponentSampleModel)) {
+            return false;
+        }
+        if (numComponents != sm.getNumBands()) {
+            return false;
+        }
+        if (transferType != sm.getTransferType()) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public SampleModel createCompatibleSampleModel(int w, int h) {
+        int bandOffsets[] = new int[numComponents];
+        for (int i = 0; i < numComponents; i++) {
+            bandOffsets[i] = i;
+        }
+
+        switch (transferType) {
+        case DataBuffer.TYPE_BYTE:
+        case DataBuffer.TYPE_USHORT:
+            return new PixelInterleavedSampleModel(transferType, w, h,
+                    numComponents, w * numComponents, bandOffsets);
+
+        default:
+            return new ComponentSampleModel(transferType, w, h, numComponents,
+                    w * numComponents, bandOffsets);
+        }
+    }
+
+    @Override
+    public boolean isCompatibleRaster(Raster raster) {
+        SampleModel sm = raster.getSampleModel();
+        if (!(sm instanceof ComponentSampleModel)) {
+            return false;
+        }
+
+        if (sm.getNumBands() != numComponents) {
+            return false;
+        }
+        if (raster.getTransferType() != transferType) {
+            return false;
+        }
+
+        int sampleSizes[] = sm.getSampleSize();
+        for (int i = 0; i < numComponents; i++) {
+            if (bits[i] != sampleSizes[i]) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public float[] getNormalizedComponents(int components[], int offset,
+            float normComponents[], int normOffset) {
+        if (donotSupportUnnormalized) {
+            // awt.213=This ComponentColorModel does not support the unnormalized form
+            throw new IllegalArgumentException(Messages.getString("awt.213")); //$NON-NLS-1$
+        }
+
+        return super.getNormalizedComponents(components, offset,
+                normComponents, normOffset);
+    }
+
+    @Override
+    public int getDataElement(int[] components, int offset) {
+        if (numComponents > 1) {
+            // awt.212=There is more than one component in this ColorModel
+            throw new IllegalArgumentException(Messages.getString("awt.212")); //$NON-NLS-1$
+        }
+        if (donotSupportUnnormalized) {
+            // awt.213=This ComponentColorModel does not support the unnormalized form
+            throw new IllegalArgumentException(Messages.getString("awt.213")); //$NON-NLS-1$
+        }
+        return components[offset];
+    }
+
+    @Override
+    public int[] getUnnormalizedComponents(float[] normComponents,
+            int normOffset, int[] components, int offset) {
+
+        if (donotSupportUnnormalized) {
+            // awt.213=This ComponentColorModel does not support the unnormalized form
+            throw new IllegalArgumentException(Messages.getString("awt.213")); //$NON-NLS-1$
+        }
+
+        if (normComponents.length - normOffset < numComponents) {
+            // awt.21B=The length of normComponents minus normOffset is less than numComponents
+            throw new IllegalArgumentException(Messages.getString("awt.21B")); //$NON-NLS-1$
+        }
+
+        return super.getUnnormalizedComponents(normComponents, normOffset,
+                components, offset);
+    }
+
+    @Override
+    public int getDataElement(float normComponents[], int normOffset) {
+        if (numComponents > 1) {
+            // awt.212=There is more than one component in this ColorModel
+            throw new IllegalArgumentException(Messages.getString("awt.212")); //$NON-NLS-1$
+        }
+        if (signed) {
+            // awt.210=The component value for this ColorModel is signed
+            throw new IllegalArgumentException(Messages.getString("awt.210")); //$NON-NLS-1$
+        }
+
+        Object pixel = getDataElements(normComponents, normOffset, null);
+
+        switch (transferType) {
+        case DataBuffer.TYPE_BYTE:
+            byte ba[] = (byte[]) pixel;
+            return ba[0] & 0xff;
+        case DataBuffer.TYPE_USHORT:
+            short sa[] = (short[]) pixel;
+            return sa[0] & 0xffff;
+        case DataBuffer.TYPE_INT:
+            int ia[] = (int[]) pixel;
+            return ia[0];
+        default:
+            // awt.211=Pixel values for this ColorModel are not conveniently
+            //          representable as a single int
+            throw new IllegalArgumentException(Messages.getString("awt.211")); //$NON-NLS-1$
+        }
+    }
+
+    @Override
+    public int[] getComponents(int pixel, int components[], int offset) {
+        if (numComponents > 1) {
+            // awt.212=There is more than one component in this ColorModel
+            throw new IllegalArgumentException(Messages.getString("awt.212")); //$NON-NLS-1$
+        }
+        if (donotSupportUnnormalized) {
+            // awt.213=This ComponentColorModel does not support the unnormalized form
+            throw new IllegalArgumentException(Messages.getString("awt.213")); //$NON-NLS-1$
+        }
+
+        if (components == null) {
+            components = new int[offset + 1];
+        }
+
+        components[offset] = pixel & maxValues[0];
+        return components;
+    }
+
+    @Override
+    public int getRed(int pixel) {
+        float rgb[] = toRGB(pixel);
+        return (int) (rgb[0] * 255.0f + 0.5f);
+    }
+
+    @Override
+    public int getRGB(int pixel) {
+        return (getAlpha(pixel) << 24) | (getRed(pixel) << 16) |
+               (getGreen(pixel) << 8) | getBlue(pixel);
+    }
+
+    @Override
+    public int getGreen(int pixel) {
+        float rgb[] = toRGB(pixel);
+        return (int) (rgb[1] * 255.0f + 0.5f);
+    }
+
+    @Override
+    public int getBlue(int pixel) {
+        float rgb[] = toRGB(pixel);
+        return (int) (rgb[2] * 255.0f + 0.5f);
+    }
+
+    @Override
+    public int getAlpha(int pixel) {
+
+        // This method throw IllegalArgumentException according to 
+        // Java API Spacification
+        if (signed) {
+            // awt.210=The component value for this ColorModel is signed
+            throw new IllegalArgumentException(Messages.getString("awt.210")); //$NON-NLS-1$
+        }
+
+        if (numComponents > 1) {
+            // awt.212=There is more than one component in this ColorModel
+            throw new IllegalArgumentException(Messages.getString("awt.212")); //$NON-NLS-1$
+        }
+
+        return 255;
+    }
+
+    /**
+     * Initialization of Lookup tables.
+     */
+    private void initLUTs() {
+        is_sRGB = cs.isCS_sRGB();
+        is_LINEAR_RGB = (cs == LUTColorConverter.LINEAR_RGB_CS);
+
+        if (hasAlpha && bits[numColorComponents] != 8 && integral) {
+            alphaLUT = new byte[maxValues[numColorComponents] + 1];
+            for (int i = 0; i <= maxValues[numColorComponents]; i++) {
+                alphaLUT[i] = (byte) (scaleFactors[numColorComponents] * i + 
+                        0.5f);
+            }
+        }
+
+        if (is_LINEAR_RGB) {
+            if (maxBitLength > 8) {
+                LINEAR_RGB_Length = 16;
+                from_LINEAR_RGB_LUT =
+                    LUTColorConverter.getFrom16lRGBtosRGB_LUT();
+                to_LINEAR_16RGB_LUT =
+                    LUTColorConverter.getFromsRGBto16lRGB_LUT();
+            } else {
+                LINEAR_RGB_Length = 8;
+                from_LINEAR_RGB_LUT =
+                    LUTColorConverter.getFrom8lRGBtosRGB_LUT();
+                to_LINEAR_8RGB_LUT =
+                    LUTColorConverter.getFromsRGBto8lRGB_LUT();
+            }
+            fFactor = ((1 << LINEAR_RGB_Length) - 1);
+        } else {
+            fFactor = 255.0f;
+        }
+
+        if (!isAlphaPremultiplied && integral) {
+            colorLUTs = new byte[3][];
+
+            if (is_sRGB) {
+                for (int i = 0; i < numColorComponents; i++) {
+                    if (bits[i] != 8) {
+                        for (int j = 0; j < i; j++) {
+                            if (bits[i] == bits[j]) {
+                                colorLUTs[i] = colorLUTs[j];
+                                break;
+                            }
+                        }
+                        colorLUTs[i] = new byte[maxValues[i] + 1];
+                        for (int j = 0; j <= maxValues[0]; j++) {
+                            colorLUTs[i][j] =
+                                (byte) (scaleFactors[i] * j + 0.5f);
+                        }
+                    }
+                }
+            }
+
+            if (is_LINEAR_RGB) {
+
+                for (int i = 0; i < numColorComponents; i++) {
+                    if (bits[i] != LINEAR_RGB_Length) {
+                        for (int j = 0; j < i; j++) {
+                            if (bits[i] == bits[j]) {
+                                colorLUTs[i] = colorLUTs[j];
+                                break;
+                            }
+                        }
+                        colorLUTs[i] = new byte[maxValues[i] + 1];
+                        for (int j = 0; j <= maxValues[0]; j++) {
+                            int idx;
+                            if (LINEAR_RGB_Length == 8) {
+                                idx = (int) (scaleFactors[i] * j + 0.5f);
+                            } else {
+                                idx = (int) (scaleFactors[i] * j * 257.0f +
+                                        0.5f);
+                            }
+                            colorLUTs[i][j] = from_LINEAR_RGB_LUT[idx];
+                        }
+                    }
+                }
+            }
+
+        }
+    }
+
+    /**
+     * To rgb.
+     * 
+     * @param pixel - int representation of pixel
+     * 
+     * @return - array of normalized sRGB components
+     */
+    private float[] toRGB(int pixel) {
+        
+        // This method throw IllegalArgumentException according to 
+        // Java API Spacification
+        if (signed) {
+            // awt.210=The component value for this ColorModel is signed
+            throw new IllegalArgumentException(Messages.getString("awt.210")); //$NON-NLS-1$
+        }
+
+        if (numComponents > 1) {
+            // awt.212=There is more than one component in this ColorModel
+            throw new IllegalArgumentException(Messages.getString("awt.212")); //$NON-NLS-1$
+        }
+
+        Object obj = null;
+
+        switch (transferType) {
+        case DataBuffer.TYPE_BYTE:
+            byte ba[] = new byte[1];
+            ba[0] = (byte) pixel;
+            obj = ba;
+            break;
+
+        case DataBuffer.TYPE_USHORT:
+            short sa[] = new short[1];
+            sa[0] = (short) pixel;
+            obj = sa;
+            break;
+
+        case DataBuffer.TYPE_INT:
+            int ia[] = new int[1];
+            ia[0] = pixel;
+            obj = ia;
+            break;
+
+        }
+
+        return cs.toRGB(getNormalizedComponents(obj, null, 0));
+    }
+
+    /**
+     * Gets the rgb component.
+     * 
+     * @param pixel - pixel
+     * @param idx - index of component
+     * 
+     * @return - RGB value from 0 to 255 pixel's component
+     */
+    private int getRGBComponent(Object pixel, int idx) {
+        if (is_sRGB) {
+            int comp = getDefComponent(pixel, idx);
+            if (calcValue || bits[idx] == 8) {
+                return comp;
+            }
+            return colorLUTs[idx][comp] & 0xff;
+        } else if (is_LINEAR_RGB) {
+            int comp = getDefComponent(pixel, idx);
+            if (calcValue || bits[idx] == LINEAR_RGB_Length) {
+                return from_LINEAR_RGB_LUT[comp] & 0xff;
+            }
+            return colorLUTs[idx][comp] & 0xff;
+        }
+
+        float normComp[] = getNormalizedComponents(pixel, null, 0);
+        float rgbComp[] = cs.toRGB(normComp);
+        return (int) (rgbComp[idx] * 255.0f + 0.5f);
+    }
+
+    /**
+     * Gets the def component.
+     * 
+     * @param pixel - pixel
+     * @param idx - index of component
+     * 
+     * @return - tentative value of the pixel component
+     */
+    private int getDefComponent(Object pixel, int idx) {
+        int comp = 0;
+        calcValue = false;
+
+        switch (transferType) {
+        case DataBuffer.TYPE_BYTE:
+            byte ba[] = (byte[]) pixel;
+            comp = ba[idx] & 0xff;
+            if (needAlphaDivide) {
+                int alpha = ba[numColorComponents] & 0xff;
+                if (alpha == 0) {
+                    comp = 0;
+                } else {
+                    float normAlpha = scaleFactors[numColorComponents] * alpha;
+                    comp = (int) (comp * fFactor / normAlpha + 0.5f);
+                }
+                calcValue = true;
+            }
+            return comp;
+
+        case DataBuffer.TYPE_USHORT:
+            short usa[] = (short[]) pixel;
+            comp = usa[idx] & 0xffff;
+            if (needAlphaDivide) {
+                int alpha = usa[numColorComponents] & 0xffff;
+                if (alpha == 0) {
+                    comp = 0;
+                } else {
+                    float normAlpha = scaleFactors[numColorComponents] * alpha;
+                    comp = (int) (comp * fFactor / normAlpha + 0.5f);
+                }
+                calcValue = true;
+            }
+            return comp;
+
+        case DataBuffer.TYPE_INT:
+            int ia[] = (int[]) pixel;
+            comp = ia[idx];
+            if (needAlphaDivide) {
+                int alpha = ia[numColorComponents];
+                if (alpha == 0) {
+                    comp = 0;
+                } else {
+                    float normAlpha = scaleFactors[numColorComponents] * alpha;
+                    comp = (int) (comp * fFactor / normAlpha + 0.5f);
+                }
+                calcValue = true;
+            }
+            return comp;
+
+        case DataBuffer.TYPE_SHORT:
+            short sa[] = (short[]) pixel;
+            comp = sa[idx];
+            if (needAlphaDivide) {
+                int alpha = sa[numColorComponents];
+                if (alpha == 0) {
+                    comp = 0;
+                } else {
+                    float normAlpha = scaleFactors[numColorComponents] * alpha;
+                    comp = (int) (comp * fFactor / normAlpha + 0.5f);
+                }
+                calcValue = true;
+            }
+            return comp;
+
+        case DataBuffer.TYPE_FLOAT:
+            float fa[] = (float[]) pixel;
+            if (needAlphaDivide) {
+                float alpha = fa[numColorComponents];
+                if (fa[numColorComponents] == 0.0f) {
+                    comp = 0;
+                } else {
+                    comp = (int) (fa[idx] * fFactor / alpha + 0.5f);
+                }
+            } else {
+                comp = (int) (fa[idx] * fFactor + 0.5f);
+            }
+            calcValue = true;
+            return comp;
+
+        case DataBuffer.TYPE_DOUBLE:
+            double da[] = (double[]) pixel;
+            if (needAlphaDivide) {
+                if (da[numColorComponents] == 0.0) {
+                    comp = 0;
+                } else {
+                    comp = (int) (da[idx] * fFactor / da[numColorComponents] + 
+                            0.5);
+                }
+            } else {
+                comp = (int) (da[idx] * fFactor + 0.5);
+            }
+            calcValue = true;
+            return comp;
+
+        default:
+            // awt.214=This Color Model doesn't support this transferType
+            throw new UnsupportedOperationException(Messages.getString("awt.214")); //$NON-NLS-1$
+        }
+    }
+
+}
+
diff --git a/awt/java/awt/image/ComponentSampleModel.java b/awt/java/awt/image/ComponentSampleModel.java
new file mode 100644
index 0000000..2ff4f1a
--- /dev/null
+++ b/awt/java/awt/image/ComponentSampleModel.java
@@ -0,0 +1,690 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import java.util.Arrays;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The ComponentSampleModel class represents a set of image data whose 
+ * each element - the sample of a pixel - takes one data element of 
+ * the DataBuffer. 
+ * <p>
+ * The Bank indices denote the correspondence between the bank of data 
+ * buffers and a band of image data. The Pixel stride is the number of data 
+ * array elements between two samples for the same band on the same 
+ * scanline. The pixel stride for a BandedSampleModel is one. The Scanline 
+ * stride represents the number of data array elements between a  
+ * specified sample and the corresponding sample in the same column in 
+ * the next scanline. The array of band offsets gives the starting 
+ * offsets within each data banks of the in the DataBuffer. The bank 
+ * indices represents the indices within each bank of the DataBuffer 
+ * corresponding to a band of image data.
+ */
+public class ComponentSampleModel extends SampleModel {
+
+    /** The band offsets array of this ComponentSampleModel. */
+    protected int bandOffsets[];
+
+    /** The bank indices array of this ComponentSampleModel. */
+    protected int bankIndices[];
+
+    /** The number of bands in this ComponentSampleModel. */
+    protected int numBands;
+
+    /** The number banks of this ComponentSampleModel. */
+    protected int numBanks;
+
+    /** The scanline stride of this ComponentSampleModel. */
+    protected int scanlineStride;
+
+    /** The pixel stride of this ComponentSampleModel. */
+    protected int pixelStride;
+
+    /**
+     * Instantiates a new ComponentSampleModel with the specified
+     * properties.
+     * 
+     * @param dataType the data type of samples.
+     * @param w the width of the image data.
+     * @param h the height of the image data.
+     * @param pixelStride the pixel stride of the image data.
+     * @param scanlineStride the scanline stride of the image data.
+     * @param bankIndices the array of the bank indices.
+     * @param bandOffsets the array of the band offsets.
+     */
+    public ComponentSampleModel(int dataType, int w, int h, int pixelStride,
+            int scanlineStride, int bankIndices[], int bandOffsets[]) {
+
+        super(dataType, w, h, bandOffsets.length);
+
+        if (pixelStride < 0) {
+            // awt.24B=Pixel stride must be >= 0
+            throw new IllegalArgumentException(Messages.getString("awt.24B")); //$NON-NLS-1$
+        }
+
+        if (scanlineStride < 0) {
+            // awt.24C=Scanline stride must be >= 0
+            throw new IllegalArgumentException(Messages.getString("awt.24C")); //$NON-NLS-1$
+        }
+
+        if (bankIndices.length != bandOffsets.length) {
+            // awt.24D=Bank Indices length must be equal Bank Offsets length
+            throw new IllegalArgumentException(Messages.getString("awt.24D")); //$NON-NLS-1$
+        }
+
+        this.pixelStride = pixelStride;
+        this.scanlineStride = scanlineStride;
+        this.bandOffsets = bandOffsets.clone();
+        this.bankIndices = bankIndices.clone();
+        this.numBands = bandOffsets.length;
+
+        int maxBank = 0;
+        for (int i = 0; i < bankIndices.length; i++) {
+            if (bankIndices[i] < 0) {
+                // awt.24E=Index of {0} bank must be >= 0
+                throw new IllegalArgumentException(Messages.getString("awt.24E", i)); //$NON-NLS-1$
+            }
+            if (bankIndices[i] > maxBank) {
+                maxBank = bankIndices[i];
+            }
+        }
+        this.numBanks = maxBank + 1;
+
+    }
+
+    /**
+     * Instantiates a new ComponentSampleModel with the specified
+     * properties.
+     * 
+     * @param dataType the data type of the samples.
+     * @param w the width of the image data.
+     * @param h the height of the image data.
+     * @param pixelStride the pixel stride of the image data.
+     * @param scanlineStride the scanline stride of the image data.
+     * @param bandOffsets the band offsets.
+     */
+    public ComponentSampleModel(int dataType, int w, int h, int pixelStride,
+            int scanlineStride, int bandOffsets[]) {
+
+        super(dataType, w, h, bandOffsets.length);
+        if (pixelStride < 0) {
+            // awt.24B=Pixel stride must be >= 0
+            throw new IllegalArgumentException(Messages.getString("awt.24B")); //$NON-NLS-1$
+        }
+
+        if (scanlineStride < 0) {
+            // awt.24C=Scanline stride must be >= 0
+            throw new IllegalArgumentException(Messages.getString("awt.24C")); //$NON-NLS-1$
+        }
+
+        this.pixelStride = pixelStride;
+        this.scanlineStride = scanlineStride;
+        this.bandOffsets = bandOffsets.clone();
+        this.numBands = bandOffsets.length;
+        this.numBanks = 1;
+
+        this.bankIndices = new int[numBands];
+        for (int i = 0; i < numBands; i++) {
+            bankIndices[i] = 0;
+        }
+    }
+
+    @Override
+    public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
+        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+        switch (dataType) {
+        case DataBuffer.TYPE_BYTE:
+            byte bdata[];
+            if (obj == null) {
+                bdata = new byte[numBands];
+            } else {
+                bdata = (byte[]) obj;
+            }
+
+            for (int i = 0; i < numBands; i++) {
+                bdata[i] = (byte) getSample(x, y, i, data);
+            }
+
+            obj = bdata;
+            break;
+
+        case DataBuffer.TYPE_SHORT:
+        case DataBuffer.TYPE_USHORT:
+            short sdata[];
+            if (obj == null) {
+                sdata = new short[numBands];
+            } else {
+                sdata = (short[]) obj;
+            }
+
+            for (int i = 0; i < numBands; i++) {
+                sdata[i] = (short) getSample(x, y, i, data);
+            }
+
+            obj = sdata;
+            break;
+
+        case DataBuffer.TYPE_INT:
+            int idata[];
+            if (obj == null) {
+                idata = new int[numBands];
+            } else {
+                idata = (int[]) obj;
+            }
+
+            for (int i = 0; i < numBands; i++) {
+                idata[i] = getSample(x, y, i, data);
+            }
+
+            obj = idata;
+            break;
+
+        case DataBuffer.TYPE_FLOAT:
+            float fdata[];
+            if (obj == null) {
+                fdata = new float[numBands];
+            } else {
+                fdata = (float[]) obj;
+            }
+
+            for (int i = 0; i < numBands; i++) {
+                fdata[i] = getSampleFloat(x, y, i, data);
+            }
+
+            obj = fdata;
+            break;
+
+        case DataBuffer.TYPE_DOUBLE:
+            double ddata[];
+            if (obj == null) {
+                ddata = new double[numBands];
+            } else {
+                ddata = (double[]) obj;
+            }
+
+            for (int i = 0; i < numBands; i++) {
+                ddata[i] = getSampleDouble(x, y, i, data);
+            }
+
+            obj = ddata;
+            break;
+        }
+
+        return obj;
+    }
+
+    @Override
+    public void setDataElements(int x, int y, Object obj, DataBuffer data) {
+        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+        switch (dataType) {
+        case DataBuffer.TYPE_BYTE:
+            byte barr[] = (byte[]) obj;
+            for (int i = 0; i < numBands; i++) {
+                setSample(x, y, i, barr[i] & 0xff, data);
+            }
+            break;
+
+        case DataBuffer.TYPE_SHORT:
+        case DataBuffer.TYPE_USHORT:
+            short sarr[] = (short[]) obj;
+            for (int i = 0; i < numBands; i++) {
+                setSample(x, y, i, sarr[i] & 0xffff, data);
+            }
+            break;
+
+        case DataBuffer.TYPE_INT:
+            int iarr[] = (int[]) obj;
+            for (int i = 0; i < numBands; i++) {
+                setSample(x, y, i, iarr[i], data);
+            }
+            break;
+
+        case DataBuffer.TYPE_FLOAT:
+            float farr[] = (float[]) obj;
+            for (int i = 0; i < numBands; i++) {
+                setSample(x, y, i, farr[i], data);
+            }
+            break;
+
+        case DataBuffer.TYPE_DOUBLE:
+            double darr[] = (double[]) obj;
+            for (int i = 0; i < numBands; i++) {
+                setSample(x, y, i, darr[i], data);
+            }
+            break;
+        }
+    }
+
+    /**
+     * Compares this ComponentSampleModel with the specified Object.
+     * 
+     * @param o the Object.
+     * 
+     * @return true, if the object is a ComponentSampleModel with 
+     * identical data values to this ComponentSampleModel, false otherwise. 
+     */
+    @Override
+    public boolean equals(Object o) {
+        if ((o == null) || !(o instanceof ComponentSampleModel)) {
+            return false;
+        }
+        ComponentSampleModel model = (ComponentSampleModel) o;
+        return this.width == model.width && this.height == model.height &&
+               this.numBands == model.numBands &&
+               this.dataType == model.dataType &&
+               Arrays.equals(this.bandOffsets, model.bandOffsets) &&
+               Arrays.equals(this.bankIndices, model.bankIndices) &&
+               this.numBands == model.numBands &&
+               this.numBanks == model.numBanks &&
+               this.scanlineStride == model.scanlineStride &&
+               this.pixelStride == model.pixelStride;
+    }
+
+    /** 
+     * @see java.awt.image.SampleModel#createSubsetSampleModel(int[])
+     */
+    @Override
+    public SampleModel createSubsetSampleModel(int bands[]) {
+        if (bands.length > this.numBands) {
+            // awt.64=The number of the bands in the subset is greater than the number of bands in the sample model
+            throw new RasterFormatException(Messages.getString("awt.64")); //$NON-NLS-1$
+        }
+
+        int indices[] = new int[bands.length];
+        int offsets[] = new int[bands.length];
+
+        for (int i = 0; i < bands.length; i++) {
+            indices[i] = bankIndices[bands[i]];
+            offsets[i] = bandOffsets[bands[i]];
+        }
+
+        return new ComponentSampleModel(dataType, width, height, pixelStride,
+                scanlineStride, indices, offsets);
+
+    }
+
+    @Override
+    public SampleModel createCompatibleSampleModel(int w, int h) {
+        return new ComponentSampleModel(dataType, w, h, pixelStride,
+                pixelStride * w, bankIndices, bandOffsets);
+    }
+
+    @Override
+    public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
+        int pixel[];
+
+        if (iArray == null) {
+            pixel = new int[numBands];
+        } else {
+            pixel = iArray;
+        }
+
+        for (int i = 0; i < numBands; i++) {
+            pixel[i] = getSample(x, y, i, data);
+        }
+
+        return pixel;
+    }
+
+    @Override
+    public void setPixel(int x, int y, int iArray[], DataBuffer data) {
+        for (int i = 0; i < numBands; i++) {
+            setSample(x, y, i, iArray[i], data);
+        }
+    }
+
+    @Override
+    public int getSample(int x, int y, int b, DataBuffer data) {
+        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+
+        return data.getElem(bankIndices[b], y * scanlineStride +
+                x * pixelStride + bandOffsets[b]);
+    }
+
+    @Override
+    public float getSampleFloat(int x, int y, int b, DataBuffer data) {
+        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+
+        return data.getElemFloat(bankIndices[b], y * scanlineStride +
+                x * pixelStride + bandOffsets[b]);
+    }
+
+    @Override
+    public double getSampleDouble(int x, int y, int b, DataBuffer data) {
+        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+
+        return data.getElemDouble(bankIndices[b], y * scanlineStride +
+                x * pixelStride + bandOffsets[b]);
+    }
+
+    @Override
+    public int[] getPixels(int x, int y, int w, int h, int iArray[],
+            DataBuffer data) {
+        if (x < 0 || y < 0 || x > this.width || x + w > this.width
+                || y > this.height || y + h > this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+        int pixels[] = null;
+        int idx = 0;
+
+        if (iArray == null) {
+            pixels = new int[w * h * numBands];
+        } else {
+            pixels = iArray;
+        }
+
+        for (int i = y; i < y + h; i++) {
+            for (int j = x; j < x + w; j++) {
+                for (int n = 0; n < numBands; n++) {
+                    pixels[idx++] = getSample(j, i, n, data);
+                }
+            }
+        }
+
+        return pixels;
+    }
+
+    @Override
+    public void setPixels(int x, int y, int w, int h, int iArray[],
+            DataBuffer data) {
+        if (x < 0 || y < 0 || x + w > this.width || y + h > this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+        int idx = 0;
+        for (int i = y; i < y + h; i++) {
+            for (int j = x; j < x + w; j++) {
+                for (int n = 0; n < numBands; n++) {
+                    setSample(j, i, n, iArray[idx++], data);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void setSample(int x, int y, int b, int s, DataBuffer data) {
+        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+
+        data.setElem(bankIndices[b], y * scanlineStride + x * pixelStride
+                + bandOffsets[b], s);
+    }
+
+    @Override
+    public int[] getSamples(int x, int y, int w, int h, int b, int iArray[],
+            DataBuffer data) {
+        if (x < 0 || y < 0 || x + w > this.width || y + h > this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+        int samples[];
+        int idx = 0;
+
+        if (iArray == null) {
+            samples = new int[w * h];
+        } else {
+            samples = iArray;
+        }
+        
+        if (data == null) {
+            // awt.295=data is null
+            throw new NullPointerException(Messages.getString("awt.295")); //$NON-NLS-1$
+        }
+
+        for (int i = y; i < y + h; i++) {
+            for (int j = x; j < x + w; j++) {
+                samples[idx++] = getSample(j, i, b, data);
+            }
+        }
+
+        return samples;
+    }
+
+    @Override
+    public void setSamples(int x, int y, int w, int h, int b, int iArray[],
+            DataBuffer data) {
+        if (x < 0 || y < 0 || x + w > this.width || y + h > this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+        int idx = 0;
+        for (int i = y; i < y + h; i++) {
+            for (int j = x; j < x + w; j++) {
+                setSample(j, i, b, iArray[idx++], data);
+            }
+        }
+    }
+
+    @Override
+    public void setSample(int x, int y, int b, float s, DataBuffer data) {
+        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+
+        data.setElemFloat(bankIndices[b], y * scanlineStride +
+                x * pixelStride + bandOffsets[b], s);
+    }
+
+    @Override
+    public void setSample(int x, int y, int b, double s, DataBuffer data) {
+        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+
+        data.setElemDouble(bankIndices[b], y * scanlineStride +
+                x * pixelStride + bandOffsets[b], s);
+    }
+
+    @Override
+    public DataBuffer createDataBuffer() {
+        DataBuffer data = null;
+
+        int maxOffset = bandOffsets[0];
+        for (int i = 1; i < bandOffsets.length; i++) {
+            if (bandOffsets[i] > maxOffset) {
+                maxOffset = bandOffsets[i];
+            }
+        }
+        int size = (height - 1) * scanlineStride +
+        (width - 1) * pixelStride + maxOffset + 1;
+
+        switch (dataType) {
+        case DataBuffer.TYPE_BYTE:
+            data = new DataBufferByte(size, numBanks);
+            break;
+        case DataBuffer.TYPE_SHORT:
+            data = new DataBufferShort(size, numBanks);
+            break;
+        case DataBuffer.TYPE_USHORT:
+            data = new DataBufferUShort(size, numBanks);
+            break;
+        case DataBuffer.TYPE_INT:
+            data = new DataBufferInt(size, numBanks);
+            break;
+        case DataBuffer.TYPE_FLOAT:
+            data = new DataBufferFloat(size, numBanks);
+            break;
+        case DataBuffer.TYPE_DOUBLE:
+            data = new DataBufferDouble(size, numBanks);
+            break;
+        }
+
+        return data;
+
+    }
+
+    /**
+     * Gets the offset of the specified band of the specified pixel.
+     * 
+     * @param x the X coordinate of the pixel. 
+     * @param y the Y coordinate of the pixel.
+     * @param b the band.
+     * 
+     * @return the offset of the specified band of the specified pixel.
+     */
+    public int getOffset(int x, int y, int b) {
+        return y * scanlineStride + x * pixelStride + bandOffsets[b];
+    }
+
+    /**
+     * Gets the offset of the first band of the specified pixel.
+     * 
+     * @param x the X coordinate of pixel. 
+     * @param y the Y coordinate of pixel.
+     * 
+     * @return the offset of the first band of the specified pixel.
+     */
+    public int getOffset(int x, int y) {
+        return y * scanlineStride + x * pixelStride + bandOffsets[0];
+    }
+
+    @Override
+    public final int getSampleSize(int band) {
+        return DataBuffer.getDataTypeSize(dataType);
+    }
+
+    @Override
+    public final int[] getSampleSize() {
+        int sampleSizes[] = new int[numBands];
+        int size = DataBuffer.getDataTypeSize(dataType);
+
+        for (int i = 0; i < numBands; i++) {
+            sampleSizes[i] = size;
+        }
+        return sampleSizes;
+    }
+
+    /**
+     * Gets an array of bank indices corresponding to this 
+     * ComponentSampleModel.
+     * 
+     * @return the array of bank indices.
+     */
+    public final int[] getBankIndices() {
+        return bankIndices.clone();
+    }
+
+    /**
+     * Gets an array of the band offsets corresponding to this 
+     * ComponentSampleModel.
+     * 
+     * @return the array of band offsets.
+     */
+    public final int[] getBandOffsets() {
+        return bandOffsets.clone();
+    }
+
+    /**
+     * Gets a hash code of this ComponentSampleModel object.
+     * 
+     * @return a hash code of this ComponentSampleModel object.
+     */
+    @Override
+    public int hashCode() {
+        int hash = 0;
+        int tmp = 0;
+
+        hash = width;
+        tmp = hash >>> 24;
+        hash <<= 8;
+        hash |= tmp;
+        hash ^= height;
+        tmp = hash >>> 24;
+        hash <<= 8;
+        hash |= tmp;
+        hash ^= numBands;
+        tmp = hash >>> 24;
+        hash <<= 8;
+        hash |= tmp;
+        hash ^= dataType;
+        tmp = hash >>> 24;
+        hash <<= 8;
+        hash |= tmp;
+        for (int element : bandOffsets) {
+            hash ^= element;
+            tmp = hash >>> 24;
+            hash <<= 8;
+            hash |= tmp;
+        }
+        for (int element : bankIndices) {
+            hash ^= element;
+            tmp = hash >>> 24;
+            hash <<= 8;
+            hash |= tmp;
+        }
+        hash ^= pixelStride;
+        tmp = hash >>> 24;
+        hash <<= 8;
+        hash |= tmp;
+
+        hash ^= scanlineStride;
+        return hash;
+    }
+
+    /**
+     * Gets the scanline stride of this ComponentSampleModel.
+     * 
+     * @return the scanline stride of this ComponentSampleModel.
+     */
+    public final int getScanlineStride() {
+        return scanlineStride;
+    }
+
+    /**
+     * Gets the pixel stride.
+     * 
+     * @return the pixel stride
+     */
+    public final int getPixelStride() {
+        return pixelStride;
+    }
+
+    @Override
+    public final int getNumDataElements() {
+        return numBands;
+    }
+
+}
+
+
+
diff --git a/awt/java/awt/image/ConvolveOp.java b/awt/java/awt/image/ConvolveOp.java
new file mode 100644
index 0000000..bb588bc
--- /dev/null
+++ b/awt/java/awt/image/ConvolveOp.java
@@ -0,0 +1,545 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ *
+ * @date: Sep 29, 2005
+ */
+
+package java.awt.image;
+
+import java.awt.*;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.util.Arrays;
+
+import org.apache.harmony.awt.gl.AwtImageBackdoorAccessor;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The ConvolveOp class convolves from the source data
+ * to the destination using a convolution kernel. 
+ * Each output pixel is represented as the result of multiplying 
+ * the kernel and the surround of the input pixel.
+ */
+public class ConvolveOp implements BufferedImageOp, RasterOp {
+
+    /** 
+     * The Constant EDGE_ZERO_FILL indicates that pixels at the edge of 
+     * the destination image are set to zero. 
+     */
+    public static final int EDGE_ZERO_FILL = 0;
+
+    /** 
+     * The Constant EDGE_NO_OP indicates that pixels at the edge of 
+     * the source image are converted to the edge pixels in the 
+     * destination without modification.
+     */
+    public static final int EDGE_NO_OP = 1;
+
+    /** The kernel. */
+    private Kernel kernel;
+    
+    /** The edge cond. */
+    private int edgeCond;
+    
+    /** The rhs. */
+    private RenderingHints rhs = null;
+
+    static {
+        // TODO
+        //System.loadLibrary("imageops");
+    }
+
+    /**
+     * Instantiates a new ConvolveOp object with the specified Kernel
+     * and specified edges condition.
+     * 
+     * @param kernel the specified Kernel.
+     * @param edgeCondition the specified edge condition.
+     * @param hints the RenderingHints object, or null.
+     */
+    public ConvolveOp(Kernel kernel, int edgeCondition, RenderingHints hints) {
+        this.kernel = kernel;
+        this.edgeCond = edgeCondition;
+        this.rhs = hints;
+    }
+
+    /**
+     * Instantiates a new ConvolveOp object with the specified Kernel
+     * and EDGE_ZERO_FILL edge condition.
+     * 
+     * @param kernel the specified Kernel.
+     */
+    public ConvolveOp(Kernel kernel) {
+        this.kernel = kernel;
+        this.edgeCond = EDGE_ZERO_FILL;
+    }
+
+    /**
+     * Gets the Kernel object of this ConvolveOp.
+     * 
+     * @return the Kernel object of this ConvolveOp.
+     */
+    public final Kernel getKernel() {
+        return (Kernel) kernel.clone();
+    }
+
+    public final RenderingHints getRenderingHints() {
+        return rhs;
+    }
+
+    /**
+     * Gets the edge condition of this ConvolveOp.
+     * 
+     * @return the edge condition: EDGE_NO_OP or EDGE_ZERO_FILL.
+     */
+    public int getEdgeCondition() {
+        return edgeCond;
+    }
+
+    public final Rectangle2D getBounds2D(Raster src) {
+        return src.getBounds();
+    }
+
+    public final Rectangle2D getBounds2D(BufferedImage src) {
+        return getBounds2D(src.getRaster());
+    }
+
+    public final Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
+        if (dstPt == null) {
+            dstPt = new Point2D.Float();
+        }
+
+        dstPt.setLocation(srcPt);
+        return dstPt;
+    }
+
+    public WritableRaster createCompatibleDestRaster(Raster src) {
+        return src.createCompatibleWritableRaster();
+    }
+
+    public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM) {
+        if (dstCM == null) {
+            dstCM = src.getColorModel();
+        }
+
+        if (dstCM instanceof IndexColorModel) {
+            dstCM = ColorModel.getRGBdefault();
+        }
+
+        WritableRaster r =
+                dstCM.isCompatibleSampleModel(src.getSampleModel()) ?
+                src.getRaster().createCompatibleWritableRaster(src.getWidth(), src.getHeight()) :
+                dstCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight());
+
+        return new BufferedImage(
+                dstCM,
+                r,
+                dstCM.isAlphaPremultiplied(),
+                null
+        );
+    }
+
+    public final WritableRaster filter(Raster src, WritableRaster dst) {
+        if (src == null) { // Should throw according to spec
+            // awt.256=Source raster is null
+            throw new NullPointerException(Messages.getString("awt.256")); //$NON-NLS-1$
+        }
+
+        if (src == dst){
+            // awt.257=Source raster is equal to destination
+            throw new IllegalArgumentException(Messages.getString("awt.257")); //$NON-NLS-1$
+        }
+
+        if (dst == null) {
+            dst = createCompatibleDestRaster(src);
+        } else if (src.getNumBands() != dst.getNumBands()) {
+            // awt.258=Number of source bands ({0}) is not equal to number of destination bands ({1})
+            throw new IllegalArgumentException(
+                Messages.getString("awt.258", src.getNumBands(), dst.getNumBands())); //$NON-NLS-1$
+        }
+
+        // TODO
+        //if (ippFilter(src, dst, BufferedImage.TYPE_CUSTOM) != 0)
+            if (slowFilter(src, dst) != 0) {
+                // awt.21F=Unable to transform source
+                throw new ImagingOpException (Messages.getString("awt.21F")); //$NON-NLS-1$
+            }
+
+        return dst;
+    }
+
+    /**
+     * Slow filter.
+     * 
+     * @param src the src
+     * @param dst the dst
+     * 
+     * @return the int
+     */
+    private int slowFilter(Raster src, WritableRaster dst) {
+        try {
+            SampleModel sm = src.getSampleModel();
+
+            int numBands = src.getNumBands();
+            int srcHeight = src.getHeight();
+            int srcWidth = src.getWidth();
+
+            int xOrigin = kernel.getXOrigin();
+            int yOrigin = kernel.getYOrigin();
+            int kWidth = kernel.getWidth();
+            int kHeight = kernel.getHeight();
+            float[] data = kernel.getKernelData(null);
+
+            int srcMinX = src.getMinX();
+            int srcMinY = src.getMinY();
+            int dstMinX = dst.getMinX();
+            int dstMinY = dst.getMinY();
+
+            int srcConvMaxX = srcWidth - (kWidth - xOrigin - 1);
+            int srcConvMaxY = srcHeight - (kHeight - yOrigin - 1);
+
+            int[] maxValues = new int[numBands];
+            int[] masks = new int[numBands];
+            int[] sampleSizes = sm.getSampleSize();
+
+            for (int i=0; i < numBands; i++){
+                maxValues[i] = (1 << sampleSizes[i]) - 1;
+                masks[i] = ~(maxValues[i]);
+            }
+
+            // Processing bounds
+            float[] pixels = null;
+            pixels = src.getPixels(srcMinX, srcMinY, srcWidth, srcHeight, pixels);
+            float[] newPixels = new float[pixels.length];
+            int rowLength = srcWidth*numBands;
+            if (this.edgeCond == ConvolveOp.EDGE_NO_OP){
+                // top
+                int start = 0;
+                int length = yOrigin*rowLength;
+                System.arraycopy(pixels, start, newPixels, start, length);
+                // bottom
+                start = (srcHeight - (kHeight - yOrigin - 1))*rowLength;
+                length = (kHeight - yOrigin - 1)*rowLength;
+                System.arraycopy(pixels, start, newPixels, start, length);
+                // middle
+                length = xOrigin*numBands;
+                int length1 = (kWidth - xOrigin - 1)*numBands;
+                start = yOrigin*rowLength;
+                int start1 = (yOrigin+1)*rowLength - length1;
+                for (int i = yOrigin; i < (srcHeight - (kHeight - yOrigin - 1)); i ++) {
+                    System.arraycopy(pixels, start, newPixels, start, length);
+                    System.arraycopy(pixels, start1, newPixels, start1, length1);
+                    start +=rowLength;
+                    start1 +=rowLength;
+                }
+
+            }
+
+            // Cycle over pixels to be calculated
+            for (int i = yOrigin; i < srcConvMaxY; i++){
+                for (int j = xOrigin; j < srcConvMaxX; j++){
+
+                    // Take kernel data in backward direction, convolution
+                    int kernelIdx = data.length - 1;
+
+                    int pixelIndex = i * rowLength + j * numBands;
+                    for (int hIdx = 0, rasterHIdx = i - yOrigin;
+                         hIdx < kHeight;
+                         hIdx++, rasterHIdx++
+                            ){
+                        for (int wIdx = 0, rasterWIdx = j - xOrigin;
+                             wIdx < kWidth;
+                             wIdx++, rasterWIdx++
+                                ){
+                            int curIndex = rasterHIdx * rowLength + rasterWIdx * numBands;
+                            for (int idx=0; idx < numBands; idx++){
+                                newPixels[pixelIndex+idx] += data[kernelIdx] * pixels[curIndex+idx];
+                            }
+                            kernelIdx--;
+                        }
+                    }
+
+                    // Check for overflow now
+                    for (int idx=0; idx < numBands; idx++){
+                        if (((int)newPixels[pixelIndex+idx] & masks[idx]) != 0) {
+                            if (newPixels[pixelIndex+idx] < 0) {
+                                newPixels[pixelIndex+idx] = 0;
+                            } else {
+                                newPixels[pixelIndex+idx] = maxValues[idx];
+                            }
+                        }
+                    }
+                }
+            }
+
+            dst.setPixels(dstMinX, dstMinY, srcWidth, srcHeight, newPixels);
+        } catch (Exception e) { // Something goes wrong, signal error
+            return 1;
+        }
+        return 0;
+    }
+
+    public final BufferedImage filter(BufferedImage src, BufferedImage dst) {
+        if (src == null) {
+            // awt.259=Source image is null
+            throw new NullPointerException(Messages.getString("awt.259")); //$NON-NLS-1$
+        }
+
+        if (src == dst){
+            // awt.25A=Source equals to destination
+            throw new IllegalArgumentException(Messages.getString("awt.25A")); //$NON-NLS-1$
+        }
+
+        ColorModel srcCM = src.getColorModel();
+        BufferedImage finalDst = null;
+
+        if (srcCM instanceof IndexColorModel) {
+            src = ((IndexColorModel)srcCM).convertToIntDiscrete(src.getRaster(), true);
+            srcCM = src.getColorModel();
+        }
+
+        if (dst == null) {
+            dst = createCompatibleDestImage(src, srcCM);
+        } else {
+            if (!srcCM.equals(dst.getColorModel())) {
+                // Treat BufferedImage.TYPE_INT_RGB and BufferedImage.TYPE_INT_ARGB as same
+                if (
+                        !((src.getType() == BufferedImage.TYPE_INT_RGB ||
+                           src.getType() == BufferedImage.TYPE_INT_ARGB) &&
+                          (dst.getType() == BufferedImage.TYPE_INT_RGB ||
+                           dst.getType() == BufferedImage.TYPE_INT_ARGB))
+                ) {
+                    finalDst = dst;
+                    dst = createCompatibleDestImage(src, srcCM);
+                }
+            }
+        }
+
+        // Skip alpha channel for TYPE_INT_RGB images
+        // TODO
+        //if (ippFilter(src.getRaster(), dst.getRaster(), src.getType()) != 0)
+            if (slowFilter(src.getRaster(), dst.getRaster()) != 0) {
+                // awt.21F=Unable to transform source
+                throw new ImagingOpException (Messages.getString("awt.21F")); //$NON-NLS-1$
+            }
+
+        if (finalDst != null) {
+            Graphics2D g = finalDst.createGraphics();
+            g.setComposite(AlphaComposite.Src);
+            g.drawImage(dst, 0, 0, null);
+        } else {
+            finalDst = dst;
+        }
+
+        return finalDst;
+    }
+
+    // TODO remove when this method is used
+    /**
+     * Ipp filter.
+     * 
+     * @param src the src
+     * @param dst the dst
+     * @param imageType the image type
+     * 
+     * @return the int
+     */
+    @SuppressWarnings("unused")
+    private int ippFilter(Raster src, WritableRaster dst, int imageType) {
+        int srcStride, dstStride;
+        boolean skipChannel = false;
+        int channels;
+        int offsets[] = null;
+
+        switch (imageType) {
+            case BufferedImage.TYPE_INT_RGB:
+            case BufferedImage.TYPE_INT_BGR: {
+                channels = 4;
+                srcStride = src.getWidth()*4;
+                dstStride = dst.getWidth()*4;
+                skipChannel = true;
+                break;
+            }
+
+            case BufferedImage.TYPE_INT_ARGB:
+            case BufferedImage.TYPE_INT_ARGB_PRE:
+            case BufferedImage.TYPE_4BYTE_ABGR:
+            case BufferedImage.TYPE_4BYTE_ABGR_PRE: {
+                channels = 4;
+                srcStride = src.getWidth()*4;
+                dstStride = dst.getWidth()*4;
+                break;
+            }
+
+            case BufferedImage.TYPE_BYTE_GRAY: {
+                channels = 1;
+                srcStride = src.getWidth();
+                dstStride = dst.getWidth();
+                break;
+            }
+
+            case BufferedImage.TYPE_3BYTE_BGR: {
+                channels = 3;
+                srcStride = src.getWidth()*3;
+                dstStride = dst.getWidth()*3;
+                break;
+            }
+
+            case BufferedImage.TYPE_USHORT_GRAY: // TODO - could be done in native code?
+            case BufferedImage.TYPE_USHORT_565_RGB:
+            case BufferedImage.TYPE_USHORT_555_RGB:
+            case BufferedImage.TYPE_BYTE_BINARY: {
+                return slowFilter(src, dst);
+            }
+
+            default: {
+                SampleModel srcSM = src.getSampleModel();
+                SampleModel dstSM = dst.getSampleModel();
+
+                if (
+                        srcSM instanceof PixelInterleavedSampleModel &&
+                        dstSM instanceof PixelInterleavedSampleModel
+                ) {
+                    // Check PixelInterleavedSampleModel
+                    if (
+                            srcSM.getDataType() != DataBuffer.TYPE_BYTE ||
+                            dstSM.getDataType() != DataBuffer.TYPE_BYTE
+                    ) {
+                        return slowFilter(src, dst);
+                    }
+
+                    channels = srcSM.getNumBands(); // Have IPP functions for 1, 3 and 4 channels
+                    if (!(channels == 1 || channels == 3 || channels == 4)) {
+                        return slowFilter(src, dst);
+                    }
+
+                    srcStride = ((ComponentSampleModel) srcSM).getScanlineStride();
+                    dstStride = ((ComponentSampleModel) dstSM).getScanlineStride();
+                } else if (
+                        srcSM instanceof SinglePixelPackedSampleModel &&
+                        dstSM instanceof SinglePixelPackedSampleModel
+                ) {
+                    // Check SinglePixelPackedSampleModel
+                    SinglePixelPackedSampleModel sppsm1 = (SinglePixelPackedSampleModel) srcSM;
+                    SinglePixelPackedSampleModel sppsm2 = (SinglePixelPackedSampleModel) dstSM;
+
+                    channels = sppsm1.getNumBands();
+
+                     // TYPE_INT_RGB, TYPE_INT_ARGB...
+                    if (
+                            sppsm1.getDataType() != DataBuffer.TYPE_INT ||
+                            sppsm2.getDataType() != DataBuffer.TYPE_INT ||
+                            !(channels == 3 || channels == 4)
+                    ) {
+                        return slowFilter(src, dst);
+                    }
+
+                    // Check compatibility of sample models
+                    if (
+                            !Arrays.equals(sppsm1.getBitOffsets(), sppsm2.getBitOffsets()) ||
+                            !Arrays.equals(sppsm1.getBitMasks(), sppsm2.getBitMasks())
+                    ) {
+                        return slowFilter(src, dst);
+                    }
+
+                    for (int i=0; i<channels; i++) {
+                        if (sppsm1.getSampleSize(i) != 8) {
+                            return slowFilter(src, dst);
+                        }
+                    }
+
+                    if (channels == 3) { // Cannot skip channel, don't know which is alpha...
+                        channels = 4;
+                    }
+
+                    srcStride = sppsm1.getScanlineStride() * 4;
+                    dstStride = sppsm2.getScanlineStride() * 4;
+                } else {
+                    return slowFilter(src, dst);
+                }
+
+                // Fill offsets if there's a child raster
+                if (src.getParent() != null || dst.getParent() != null) {
+                    if (
+                            src.getSampleModelTranslateX() != 0 ||
+                            src.getSampleModelTranslateY() != 0 ||
+                            dst.getSampleModelTranslateX() != 0 ||
+                            dst.getSampleModelTranslateY() != 0
+                    ) {
+                        offsets = new int[4];
+                        offsets[0] = -src.getSampleModelTranslateX() + src.getMinX();
+                        offsets[1] = -src.getSampleModelTranslateY() + src.getMinY();
+                        offsets[2] = -dst.getSampleModelTranslateX() + dst.getMinX();
+                        offsets[3] = -dst.getSampleModelTranslateY() + dst.getMinY();
+                    }
+                }
+            }
+        }
+
+        Object srcData, dstData;
+        AwtImageBackdoorAccessor dbAccess = AwtImageBackdoorAccessor.getInstance();
+        try {
+            srcData = dbAccess.getData(src.getDataBuffer());
+            dstData = dbAccess.getData(dst.getDataBuffer());
+        } catch (IllegalArgumentException e) {
+            return -1; // Unknown data buffer type
+        }
+
+        return ippFilter32f(
+            kernel.data, kernel.getWidth(), kernel.getHeight(),
+            kernel.getXOrigin(), kernel.getYOrigin(), edgeCond,
+            srcData, src.getWidth(), src.getHeight(), srcStride,
+            dstData, dst.getWidth(), dst.getHeight(), dstStride,
+            channels, skipChannel, offsets
+        );
+    }
+
+    /**
+     * Ipp filter32f.
+     * 
+     * @param kernel the kernel
+     * @param kWidth the k width
+     * @param kHeight the k height
+     * @param anchorX the anchor x
+     * @param anchorY the anchor y
+     * @param borderType the border type
+     * @param src the src
+     * @param srcWidth the src width
+     * @param srcHeight the src height
+     * @param srcStride the src stride
+     * @param dst the dst
+     * @param dstWidth the dst width
+     * @param dstHeight the dst height
+     * @param dstStride the dst stride
+     * @param channels the channels
+     * @param skipChannel the skip channel
+     * @param offsets the offsets
+     * 
+     * @return the int
+     */
+    private native int ippFilter32f(
+                float kernel[], int kWidth, int kHeight,
+                int anchorX, int anchorY, int borderType,
+                Object src, int srcWidth, int srcHeight, int srcStride,
+                Object dst, int dstWidth, int dstHeight, int dstStride,
+                int channels, boolean skipChannel, int offsets[]
+            );
+}
+
diff --git a/awt/java/awt/image/CropImageFilter.java b/awt/java/awt/image/CropImageFilter.java
new file mode 100644
index 0000000..e90c44a
--- /dev/null
+++ b/awt/java/awt/image/CropImageFilter.java
@@ -0,0 +1,193 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import java.util.Hashtable;
+
+/**
+ * The CropImageFilter class crops a rectangular region of an source
+ * Image and provides a source for a new image containing the extracted 
+ * region.
+ */
+public class CropImageFilter extends ImageFilter {
+
+    /** The HEIGHT. */
+    private final int X, Y, WIDTH, HEIGHT;
+
+    /**
+     * Instantiates a new CropImageFilter object with the specified
+     * rectangular area.
+     * 
+     * @param x the X coordinate of rectangular area. 
+     * @param y the Y coordinate of rectangular area.
+     * @param w the width of rectangular area.
+     * @param h the height of rectangular area.
+     */
+    public CropImageFilter(int x, int y, int w, int h) {
+        X = x;
+        Y = y;
+        WIDTH = w;
+        HEIGHT = h;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public void setProperties(Hashtable<?, ?> props) {
+        Hashtable<Object, Object> fprops;
+        if(props == null) {
+            fprops = new Hashtable<Object, Object>();
+        } else {
+            fprops = (Hashtable<Object, Object>) props.clone();
+        }
+        String propName = "Crop Filters"; //$NON-NLS-1$
+        String prop = "x=" + X + "; y=" + Y + "; width=" + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+        WIDTH + "; height=" + HEIGHT; //$NON-NLS-1$
+        Object o = fprops.get(propName);
+        if(o != null){
+            if(o instanceof String){
+                prop = (String)o + "; " + prop; //$NON-NLS-1$
+            }else{
+                prop =  o.toString() + "; " + prop; //$NON-NLS-1$
+            }
+        }
+        fprops.put(propName, prop);
+        consumer.setProperties(fprops);
+    }
+
+    @Override
+    public void setPixels(int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize) {
+
+        if(x + w < X || X + WIDTH < x ||
+                y + h < Y || Y + HEIGHT < y) {
+            return;
+        }
+
+        int destX, destY, destWidth, destHeight, endX, endY,
+        srcEndX, srcEndY;
+
+        int newOffset = off;
+
+        endX = X + WIDTH;
+        endY = Y + HEIGHT;
+
+        srcEndX = x + w;
+        srcEndY = y + h;
+
+        if(x <= X){
+            destX = 0;
+            newOffset += X;
+            if(endX >= srcEndX){
+                destWidth = srcEndX - X;
+            }else{
+                destWidth = WIDTH;
+            }
+        }else{
+            destX = x - X;
+            if(endX >= srcEndX){
+                destWidth = w;
+            }else{
+                destWidth = endX - x;
+            }
+        }
+
+
+        if(y <= Y){
+            newOffset += scansize * (Y - y);
+            destY = 0;
+            if(endY >= srcEndY){
+                destHeight = srcEndY - Y;
+            }else{
+                destHeight = HEIGHT;
+            }
+        }else{
+            destY = y - Y;
+            if(endY >= srcEndY){
+                destHeight = h;
+            }else{
+                destHeight = endY - y;
+            }
+        }
+        consumer.setPixels(destX, destY, destWidth, destHeight, model, pixels, newOffset, scansize);
+    }
+
+    @Override
+    public void setPixels(int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize) {
+
+        if(x + w < X || X + WIDTH < x ||
+                y + h < Y || Y + HEIGHT < y) {
+            return;
+        }
+
+        int destX, destY, destWidth, destHeight, endX, endY,
+        srcEndX, srcEndY;
+
+        int newOffset = off;
+
+        endX = X + WIDTH;
+        endY = Y + HEIGHT;
+
+        srcEndX = x + w;
+        srcEndY = y + h;
+
+        if(x <= X){
+            destX = 0;
+            newOffset += X;
+            if(endX >= srcEndX){
+                destWidth = srcEndX - X;
+            }else{
+                destWidth = WIDTH;
+            }
+        }else{
+            destX = x - X;
+            if(endX >= srcEndX){
+                destWidth = w;
+            }else{
+                destWidth = endX - x;
+            }
+        }
+
+
+        if(y <= Y){
+            newOffset += scansize * (Y - y);
+            destY = 0;
+            if(endY >= srcEndY){
+                destHeight = srcEndY - Y;
+            }else{
+                destHeight = HEIGHT;
+            }
+        }else{
+            destY = y - Y;
+            if(endY >= srcEndY){
+                destHeight = h;
+            }else{
+                destHeight = endY - y;
+            }
+        }
+        consumer.setPixels(destX, destY, destWidth, destHeight, model, pixels, newOffset, scansize);
+    }
+
+    @Override
+    public void setDimensions(int w, int h) {
+        consumer.setDimensions(WIDTH, HEIGHT);
+    }
+
+}
+
diff --git a/awt/java/awt/image/DataBuffer.java b/awt/java/awt/image/DataBuffer.java
new file mode 100644
index 0000000..6856aee
--- /dev/null
+++ b/awt/java/awt/image/DataBuffer.java
@@ -0,0 +1,442 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import org.apache.harmony.awt.gl.image.DataBufferListener;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Class DataBuffer is a wrapper class for a data array
+ * to be used for the situation where a suite of functionality
+ * acts on a set of data in a consistent way even though the 
+ * primitive type of the data may vary from one use to the next. 
+ */
+public abstract class DataBuffer {
+
+    /** The Constant TYPE_BYTE. */
+    public static final int TYPE_BYTE = 0;
+
+    /** The Constant TYPE_USHORT. */
+    public static final int TYPE_USHORT = 1;
+
+    /** The Constant TYPE_SHORT. */
+    public static final int TYPE_SHORT = 2;
+
+    /** The Constant TYPE_INT. */
+    public static final int TYPE_INT = 3;
+
+    /** The Constant TYPE_FLOAT. */
+    public static final int TYPE_FLOAT = 4;
+
+    /** The Constant TYPE_DOUBLE. */
+    public static final int TYPE_DOUBLE = 5;
+
+    /** The Constant TYPE_UNDEFINED. */
+    public static final int TYPE_UNDEFINED = 32;
+
+    /** The data type indicates the primitive type of the 
+     * data in this DataBuffer. */
+    protected int dataType;
+
+    /** The number of data arrays in this DataBuffer. */
+    protected int banks;
+
+    /** The starting index for reading the 
+     * data from the first (or only) internal data array. */
+    protected int offset;
+
+    /** The length (number of elements) of the data arrays. */
+    protected int size;
+
+    /** The starting indices for reading the 
+     * data from the internal data arrays. */
+    protected int offsets[];
+    
+    /** The data changed. */
+    boolean dataChanged = true;
+    
+    /** The data taken. */
+    boolean dataTaken = false;
+    
+    /** The listener. */
+    DataBufferListener listener;
+
+    static {
+        AwtImageBackdoorAccessorImpl.init();
+    }
+
+    /**
+     * Instantiates a new data buffer.
+     * 
+     * @param dataType the data type
+     * @param size the length (number of elements) of the data arrays
+     * @param numBanks the number of data arrays to create
+     * @param offsets the starting indices for reading the 
+     * data from the internal data arrays
+     */
+    protected DataBuffer(int dataType, int size, int numBanks, int[] offsets) {
+        this.dataType = dataType;
+        this.size = size;
+        this.banks = numBanks;
+        this.offsets = offsets.clone();
+        this.offset = offsets[0];
+    }
+
+    /**
+     * Instantiates a new data buffer with all of the 
+     * data arrays starting at the same index.
+     * 
+     * @param dataType the data type
+     * @param size the length (number of elements) of the data arrays
+     * @param numBanks the number of data arrays to create
+     * @param offset the offset to use for all of the data arrays
+     */
+    protected DataBuffer(int dataType, int size, int numBanks, int offset) {
+        this.dataType = dataType;
+        this.size = size;
+        this.banks = numBanks;
+        this.offset = offset;
+        this.offsets = new int[numBanks];
+        int i = 0;
+        while (i < numBanks) {
+            offsets[i++] = offset;
+        }
+    }
+
+    /**
+     * Instantiates a new data buffer with all of the 
+     * data arrays read from the beginning (at offset zero).
+     * 
+     * @param dataType the data type
+     * @param size the length (number of elements) of the data arrays
+     * @param numBanks the number of data arrays to create
+     */
+    protected DataBuffer(int dataType, int size, int numBanks) {
+        this.dataType = dataType;
+        this.size = size;
+        this.banks = numBanks;
+        this.offset = 0;
+        this.offsets = new int[numBanks];
+    }
+
+    /**
+     * Instantiates a new data buffer with one internal data array
+     * read from the beginning (at offset zero).
+     * 
+     * @param dataType the data type
+     * @param size the length (number of elements) of the data arrays
+     */
+    protected DataBuffer(int dataType, int size) {
+        this.dataType = dataType;
+        this.size = size;
+        this.banks = 1;
+        this.offset = 0;
+        this.offsets = new int[1];
+    }
+
+    /**
+     * Sets the data value in the specified array at the 
+     * specified index.
+     * 
+     * @param bank the internal array to the data to
+     * @param i the index within the array where the data
+     * should be written
+     * @param val the value to write into the array
+     */
+    public abstract void setElem(int bank, int i, int val);
+
+    /**
+     * Sets the float data value in the specified array at the 
+     * specified index.
+     * 
+     * @param bank the internal array to the data to
+     * @param i the index within the array where the data
+     * should be written
+     * @param val the value to write into the array
+     */
+    public void setElemFloat(int bank, int i, float val) {
+        setElem(bank, i, (int) val);
+    }
+
+    /**
+     * Sets the double data value in the specified array at the 
+     * specified index.
+     * 
+     * @param bank the internal array to the data to
+     * @param i the index within the array where the data
+     * should be written
+     * @param val the value to write into the array
+     */
+    public void setElemDouble(int bank, int i, double val) {
+        setElem(bank, i, (int) val);
+    }
+
+    /**
+     * Sets the data value in the first array at the 
+     * specified index.
+     * 
+     * @param i the index within the array where the data
+     * should be written
+     * @param val the value to write into the array
+     */
+    public void setElem(int i, int val) {
+        setElem(0, i, val);
+    }
+
+    /**
+     * Gets the data value from the specified data array at the 
+     * specified index.
+     * 
+     * @param bank the data array to read from
+     * @param i the index within the array where the data
+     * should be read
+     * 
+     * @return the data element
+     */
+    public abstract int getElem(int bank, int i);
+
+    /**
+     * Gets the float-type data value from the specified 
+     * data array at the specified index.
+     * 
+     * @param bank the data array to read from
+     * @param i the index within the array where the data
+     * should be read
+     * 
+     * @return the data element
+     */
+    public float getElemFloat(int bank, int i) {
+        return getElem(bank, i);
+    }
+
+    /**
+     * Gets the double-type data value from the specified 
+     * data array at the specified index.
+     * 
+     * @param bank the data array to read from
+     * @param i the index within the array where the data
+     * should be read
+     * 
+     * @return the data element
+     */
+    public double getElemDouble(int bank, int i) {
+        return getElem(bank, i);
+    }
+
+    /**
+     * Sets the float data value in the first array at the 
+     * specified index.
+     * 
+     * @param i the index within the array where the data
+     * should be written
+     * @param val the value to write into the array
+     */
+    public void setElemFloat(int i, float val) {
+        setElemFloat(0, i, val);
+    }
+
+    /**
+     * Sets the double data value in the first array at the 
+     * specified index.
+     * 
+     * @param i the index within the array where the data
+     * should be written
+     * @param val the value to write into the array
+     */
+    public void setElemDouble(int i, double val) {
+        setElemDouble(0, i, val);
+    }
+
+    /**
+     * Gets the data value from the first 
+     * data array at the specified index and returns it
+     * as an int.
+     * 
+     * @param i the index within the array where the data
+     * should be read
+     * 
+     * @return the data element
+     */
+    public int getElem(int i) {
+        return getElem(0, i);
+    }
+
+    /**
+     * Gets the data value from the first 
+     * data array at the specified index and returns it
+     * as a float.
+     * 
+     * @param i the index within the array where the data
+     * should be read
+     * 
+     * @return the data element
+     */
+    public float getElemFloat(int i) {
+        return getElem(0, i);
+    }
+
+    /**
+     * Gets the data value from the first 
+     * data array at the specified index and returns it
+     * as a double.
+     * 
+     * @param i the index within the array where the data
+     * should be read
+     * 
+     * @return the data element
+     */
+    public double getElemDouble(int i) {
+        return getElem(i);
+    }
+
+    /**
+     * Gets the array giving the offsets corresponding 
+     * to the internal data arrays.
+     * 
+     * @return the array of offsets
+     */
+    public int[] getOffsets() {
+        return offsets;
+    }
+
+    /**
+     * Gets the size in bits of the primitive data type.
+     * 
+     * @return the size in bits of the primitive data type
+
+     */
+    public int getSize() {
+        return size;
+    }
+
+    /**
+     * Gets the offset corresponding to the first internal 
+     * data array.
+     * 
+     * @return the offset
+     */
+    public int getOffset() {
+        return offset;
+    }
+
+    /**
+     * Gets the number of data arrays in this DataBuffer.
+     * 
+     * @return the number of data arrays
+     */
+    public int getNumBanks() {
+        return banks;
+    }
+
+    /**
+     * Gets the primitive type of this buffer's data.
+     * 
+     * @return the data type
+     */
+    public int getDataType() {
+        return this.dataType;
+    }
+
+    /**
+     * Gets the size in bits of the primitive data type.
+     * 
+     * @param type the primitive type
+     * 
+     * @return the size in bits of the primitive data type
+     */
+    public static int getDataTypeSize(int type) {
+        switch (type) {
+
+        case TYPE_BYTE:
+            return 8;
+
+        case TYPE_USHORT:
+        case TYPE_SHORT:
+            return 16;
+
+        case TYPE_INT:
+        case TYPE_FLOAT:
+            return 32;
+
+        case TYPE_DOUBLE:
+            return 64;
+
+        default:
+            // awt.22C=Unknown data type {0}
+            throw new IllegalArgumentException(Messages.getString("awt.22C", type)); //$NON-NLS-1$
+        }
+    }
+    
+    /**
+     * Notifies the listener that the data has changed.
+     */
+    void notifyChanged(){
+        if(listener != null && !dataChanged){
+            dataChanged = true;
+            listener.dataChanged();
+        }
+    }
+    
+    /**
+     * Notifies the listener that the data has been released.
+     */
+    void notifyTaken(){
+        if(listener != null && !dataTaken){
+            dataTaken = true;
+            listener.dataTaken();
+        }
+    }
+    
+    /**
+     * Release the data.
+     */
+    void releaseData(){
+        if(listener != null && dataTaken){
+            dataTaken = false;
+            listener.dataReleased();
+        }
+    }
+    
+    /**
+     * Adds the data buffer listener.
+     * 
+     * @param listener the listener
+     */
+    void addDataBufferListener(DataBufferListener listener){
+        this.listener = listener;
+    }
+    
+    /**
+     * Removes the data buffer listener.
+     */
+    void removeDataBufferListener(){
+        listener = null;
+    }
+    
+    /**
+     * Validate.
+     */
+    void validate(){
+        dataChanged = false;
+    }
+    
+}
+
diff --git a/awt/java/awt/image/DataBufferByte.java b/awt/java/awt/image/DataBufferByte.java
new file mode 100644
index 0000000..4d29c9c
--- /dev/null
+++ b/awt/java/awt/image/DataBufferByte.java
@@ -0,0 +1,171 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+/**
+ * The Class DataBufferByte is the subclass of DataBuffer
+ * for the case where the underlying data is of type byte.
+ */
+public final class DataBufferByte extends DataBuffer {
+
+    /** The data. */
+    byte data[][];
+
+    /**
+     * Instantiates a new data buffer of type unsigned short.
+     * 
+     * @param dataArrays the data arrays to copy the data from
+     * @param size the length (number of elements) to use 
+     * from the data arrays
+     * @param offsets the starting indices for reading the 
+     * data from the internal data arrays
+     */
+    public DataBufferByte(byte dataArrays[][], int size, int offsets[]) {
+        super(TYPE_BYTE, size, dataArrays.length, offsets);
+        data = dataArrays.clone();
+    }
+
+    /**
+     * Instantiates a new data buffer of type unsigned short.
+     * 
+     * @param dataArrays the data arrays to copy the data from
+     * @param size the length (number of elements) to use 
+     * from the data arrays
+     */
+    public DataBufferByte(byte dataArrays[][], int size) {
+        super(TYPE_BYTE, size, dataArrays.length);
+        data = dataArrays.clone();
+    }
+
+    /**
+     * Instantiates a new data buffer of type unsigned short
+     * with a single underlying array of data.
+     * 
+     * @param dataArray the data array to copy the data from
+     * @param size the length (number of elements) to use 
+     * @param offset the starting index to use when reading the data
+     */
+    public DataBufferByte(byte dataArray[], int size, int offset) {
+        super(TYPE_BYTE, size, 1, offset);
+        data = new byte[1][];
+        data[0] = dataArray;
+    }
+
+    /**
+     * Instantiates a new data buffer of type unsigned short
+     * with a single underlying array of data starting at
+     * index 0.
+     * 
+     * @param dataArray the data array to copy the data from
+     * @param size the length (number of elements) to use 
+     */
+    public DataBufferByte(byte dataArray[], int size) {
+        super(TYPE_BYTE, size);
+        data = new byte[1][];
+        data[0] = dataArray;
+    }
+
+    /**
+     * Instantiates a new empty data buffer of type unsigned short
+     * with offsets equal to zero.
+     * 
+     * @param size the length (number of elements) to use 
+     * from the data arrays
+     * @param numBanks the number of data arrays to create
+     */
+    public DataBufferByte(int size, int numBanks) {
+        super(TYPE_BYTE, size, numBanks);
+        data = new byte[numBanks][];
+        int i = 0;
+        while (i < numBanks) {
+            data[i++] = new byte[size];
+        }
+    }
+
+    /**
+     * Instantiates a new empty data buffer of type unsigned short
+     * with a single underlying array of data starting at
+     * index 0.
+     * 
+     * @param size the length (number of elements) to use 
+     */
+    public DataBufferByte(int size) {
+        super(TYPE_BYTE, size);
+        data = new byte[1][];
+        data[0] = new byte[size];
+    }
+
+    @Override
+    public void setElem(int bank, int i, int val) {
+        data[bank][offsets[bank] + i] = (byte) val;
+        notifyChanged();
+    }
+
+    @Override
+    public void setElem(int i, int val) {
+        data[0][offset + i] = (byte) val;
+        notifyChanged();
+    }
+
+    @Override
+    public int getElem(int bank, int i) {
+        return (data[bank][offsets[bank] + i]) & 0xff;
+    }
+
+    /**
+     * Gets the data of the specified internal data array.
+     * 
+     * @param bank the index of the desired data array
+     * 
+     * @return the data
+     */
+    public byte[] getData(int bank) {
+        notifyTaken();
+        return data[bank];
+    }
+
+    @Override
+    public int getElem(int i) {
+        return (data[0][offset + i]) & 0xff;
+    }
+
+    /**
+     * Gets the bank data.
+     * 
+     * @return the bank data
+     */
+    public byte[][] getBankData() {
+        notifyTaken();
+        return data.clone();
+    }
+
+    /**
+     * Gets the data of the first data array.
+     * 
+     * @return the data
+     */
+    public byte[] getData() {
+        notifyTaken();
+        return data[0];
+    }
+
+}
+
diff --git a/awt/java/awt/image/DataBufferDouble.java b/awt/java/awt/image/DataBufferDouble.java
new file mode 100644
index 0000000..fa3d324
--- /dev/null
+++ b/awt/java/awt/image/DataBufferDouble.java
@@ -0,0 +1,214 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+/**
+ * The Class DataBufferDouble is the subclass of DataBuffer
+ * for the case where the underlying data is of type double.
+ */
+public final class DataBufferDouble extends DataBuffer {
+
+    /** The data. */
+    double data[][];
+
+    /**
+     * Instantiates a new data buffer of type double.
+     * 
+     * @param dataArrays the data arrays to copy the data from
+     * @param size the length (number of elements) to use 
+     * from the data arrays
+     * @param offsets the starting indices for reading the 
+     * data from the internal data arrays
+    */
+    public DataBufferDouble(double dataArrays[][], int size, int offsets[]) {
+        super(TYPE_DOUBLE, size, dataArrays.length, offsets);
+        data = dataArrays.clone();
+    }
+
+    /**
+     * Instantiates a new data buffer of type double.
+     * 
+     * @param dataArrays the data arrays to copy the data from
+     * @param size the length (number of elements) to use 
+     * from the data arrays
+     */
+    public DataBufferDouble(double dataArrays[][], int size) {
+        super(TYPE_DOUBLE, size, dataArrays.length);
+        data = dataArrays.clone();
+    }
+
+    /**
+     * Instantiates a new data buffer of type double
+     * with a single underlying array of data.
+     * 
+     * @param dataArray the data array to copy the data from
+     * @param size the length (number of elements) to use 
+     * @param offset the starting index to use when reading the data
+     */
+    public DataBufferDouble(double dataArray[], int size, int offset) {
+        super(TYPE_DOUBLE, size, 1, offset);
+        data = new double[1][];
+        data[0] = dataArray;
+    }
+
+    /**
+     * Instantiates a new data buffer of type double
+     * with a single underlying array of data starting at
+     * index 0.
+     * 
+     * @param dataArray the data array to copy the data from
+     * @param size the length (number of elements) to use 
+     */
+    public DataBufferDouble(double dataArray[], int size) {
+        super(TYPE_DOUBLE, size);
+        data = new double[1][];
+        data[0] = dataArray;
+    }
+
+    /**
+     * Instantiates a new empty data buffer of type double
+     * with offsets equal to zero.
+     * 
+     * @param size the length (number of elements) to use 
+     * from the data arrays
+     * @param numBanks the number of data arrays to create
+     */
+    public DataBufferDouble(int size, int numBanks) {
+        super(TYPE_DOUBLE, size, numBanks);
+        data = new double[numBanks][];
+        int i = 0;
+        while (i < numBanks) {
+            data[i++] = new double[size];
+        }
+    }
+
+    /**
+     * Instantiates a new empty data buffer of type double
+     * with a single underlying array of data starting at
+     * index 0.
+     * 
+     * @param size the length (number of elements) to use 
+     */
+    public DataBufferDouble(int size) {
+        super(TYPE_DOUBLE, size);
+        data = new double[1][];
+        data[0] = new double[size];
+    }
+
+    @Override
+    public void setElem(int bank, int i, int val) {
+        data[bank][offsets[bank] + i] = val;
+        notifyChanged();
+    }
+
+    @Override
+    public void setElemFloat(int bank, int i, float val) {
+        data[bank][offsets[bank] + i] = val;
+        notifyChanged();
+    }
+
+    @Override
+    public void setElemDouble(int bank, int i, double val) {
+        data[bank][offsets[bank] + i] = val;
+        notifyChanged();
+    }
+
+    @Override
+    public void setElem(int i, int val) {
+        data[0][offset + i] = val;
+        notifyChanged();
+    }
+
+    @Override
+    public int getElem(int bank, int i) {
+        return (int) (data[bank][offsets[bank] + i]);
+    }
+
+    @Override
+    public float getElemFloat(int bank, int i) {
+        return (float) (data[bank][offsets[bank] + i]);
+    }
+
+    @Override
+    public double getElemDouble(int bank, int i) {
+        return data[bank][offsets[bank] + i];
+    }
+
+    @Override
+    public void setElemFloat(int i, float val) {
+        data[0][offset + i] = val;
+        notifyChanged();
+    }
+
+    @Override
+    public void setElemDouble(int i, double val) {
+        data[0][offset + i] = val;
+        notifyChanged();
+    }
+
+    /**
+     * Gets the data of the specified internal data array.
+     * 
+     * @param bank the index of the desired data array
+     * 
+     * @return the data
+     */
+    public double[] getData(int bank) {
+        notifyTaken();
+        return data[bank];
+    }
+
+    @Override
+    public int getElem(int i) {
+        return (int) (data[0][offset + i]);
+    }
+
+    @Override
+    public float getElemFloat(int i) {
+        return (float) (data[0][offset + i]);
+    }
+
+    @Override
+    public double getElemDouble(int i) {
+        return data[0][offset + i];
+    }
+
+    /**
+     * Gets the bank data.
+     * 
+     * @return the bank data
+     */
+    public double[][] getBankData() {
+        notifyTaken();
+        return data.clone();
+    }
+
+    /**
+     * Gets the data of the first data array.
+     * 
+     * @return the data
+     */
+    public double[] getData() {
+        notifyTaken();
+        return data[0];
+    }
+}
+
diff --git a/awt/java/awt/image/DataBufferFloat.java b/awt/java/awt/image/DataBufferFloat.java
new file mode 100644
index 0000000..e34245c
--- /dev/null
+++ b/awt/java/awt/image/DataBufferFloat.java
@@ -0,0 +1,214 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+/**
+ * The Class DataBufferFloat is the subclass of DataBuffer
+ * for the case where the underlying data is float.
+ */
+public final class DataBufferFloat extends DataBuffer {
+
+    /** The data. */
+    float data[][];
+
+    /**
+     * Instantiates a new data buffer of type float.
+     * 
+     * @param dataArrays the data arrays to copy the data from
+     * @param size the length (number of elements) to use 
+     * from the data arrays
+     * @param offsets the starting indices for reading the 
+     * data from the internal data arrays
+     */
+    public DataBufferFloat(float dataArrays[][], int size, int offsets[]) {
+        super(TYPE_FLOAT, size, dataArrays.length, offsets);
+        data = dataArrays.clone();
+    }
+
+    /**
+     * Instantiates a new data buffer of type float.
+     * 
+     * @param dataArrays the data arrays to copy the data from
+     * @param size the length (number of elements) to use 
+     * from the data arrays
+     */
+    public DataBufferFloat(float dataArrays[][], int size) {
+        super(TYPE_FLOAT, size, dataArrays.length);
+        data = dataArrays.clone();
+    }
+
+    /**
+     * Instantiates a new data buffer of type float
+     * with a single underlying array of data.
+     * 
+     * @param dataArray the data array to copy the data from
+     * @param size the length (number of elements) to use 
+     * @param offset the starting index to use when reading the data
+     */
+    public DataBufferFloat(float dataArray[], int size, int offset) {
+        super(TYPE_FLOAT, size, 1, offset);
+        data = new float[1][];
+        data[0] = dataArray;
+    }
+
+    /**
+     * Instantiates a new data buffer of type float
+     * with a single underlying array of data starting at
+     * index 0.
+     * 
+     * @param dataArray the data array to copy the data from
+     * @param size the length (number of elements) to use 
+     */
+    public DataBufferFloat(float dataArray[], int size) {
+        super(TYPE_FLOAT, size);
+        data = new float[1][];
+        data[0] = dataArray;
+    }
+
+    /**
+     * Instantiates a new empty data buffer of type float
+     * with offsets equal to zero.
+     * 
+     * @param size the length (number of elements) to use 
+     * from the data arrays
+     * @param numBanks the number of data arrays to create
+     */
+    public DataBufferFloat(int size, int numBanks) {
+        super(TYPE_FLOAT, size, numBanks);
+        data = new float[numBanks][];
+        int i = 0;
+        while (i < numBanks) {
+            data[i++] = new float[size];
+        }
+    }
+
+    /**
+     * Instantiates a new empty data buffer of type float
+     * with a single underlying array of data starting at
+     * index 0.
+     * 
+     * @param size the length (number of elements) to use 
+     */
+    public DataBufferFloat(int size) {
+        super(TYPE_FLOAT, size);
+        data = new float[1][];
+        data[0] = new float[size];
+    }
+
+    @Override
+    public void setElem(int bank, int i, int val) {
+        data[bank][offsets[bank] + i] = val;
+        notifyChanged();
+    }
+
+    @Override
+    public void setElemFloat(int bank, int i, float val) {
+        data[bank][offsets[bank] + i] = val;
+        notifyChanged();
+    }
+
+    @Override
+    public void setElemDouble(int bank, int i, double val) {
+        data[bank][offsets[bank] + i] = (float) val;
+        notifyChanged();
+    }
+
+    @Override
+    public void setElem(int i, int val) {
+        data[0][offset + i] = val;
+        notifyChanged();
+    }
+
+    @Override
+    public int getElem(int bank, int i) {
+        return (int) (data[bank][offsets[bank] + i]);
+    }
+
+    @Override
+    public float getElemFloat(int bank, int i) {
+        return data[bank][offsets[bank] + i];
+    }
+
+    @Override
+    public double getElemDouble(int bank, int i) {
+        return data[bank][offsets[bank] + i];
+    }
+
+    @Override
+    public void setElemFloat(int i, float val) {
+        data[0][offset + i] = val;
+        notifyChanged();
+    }
+
+    @Override
+    public void setElemDouble(int i, double val) {
+        data[0][offset + i] = (float) val;
+        notifyChanged();
+    }
+
+    /**
+     * Gets the data of the specified internal data array.
+     * 
+     * @param bank the index of the desired array
+     * 
+     * @return the data
+     */
+    public float[] getData(int bank) {
+        notifyTaken();
+        return data[bank];
+    }
+
+    @Override
+    public int getElem(int i) {
+        return (int) (data[0][offset + i]);
+    }
+
+    @Override
+    public float getElemFloat(int i) {
+        return data[0][offset + i];
+    }
+
+    @Override
+    public double getElemDouble(int i) {
+        return data[0][offset + i];
+    }
+
+    /**
+     * Gets the bank data.
+     * 
+     * @return the bank data
+     */
+    public float[][] getBankData() {
+        notifyTaken();
+        return data.clone();
+    }
+
+    /**
+     * Gets the data of the first data array.
+     * 
+     * @return the data
+     */
+    public float[] getData() {
+        notifyTaken();
+        return data[0];
+    }
+}
+
diff --git a/awt/java/awt/image/DataBufferInt.java b/awt/java/awt/image/DataBufferInt.java
new file mode 100644
index 0000000..43dc188
--- /dev/null
+++ b/awt/java/awt/image/DataBufferInt.java
@@ -0,0 +1,170 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+/**
+ * The Class DataBufferInt is the subclass of DataBuffer
+ * for the case where the underlying data is of type int.
+ */
+public final class DataBufferInt extends DataBuffer {
+
+    /** The data. */
+    int data[][];
+
+    /**
+     * Instantiates a new data buffer of type int.
+     * 
+     * @param dataArrays the data arrays to copy the data from
+     * @param size the length (number of elements) to use 
+     * from the data arrays
+     * @param offsets the starting indices for reading the 
+     * data from the internal data arrays
+     */
+    public DataBufferInt(int dataArrays[][], int size, int offsets[]) {
+        super(TYPE_INT, size, dataArrays.length, offsets);
+        data = dataArrays.clone();
+    }
+
+    /**
+     * Instantiates a new data buffer of type int.
+     * 
+     * @param dataArrays the data arrays to copy the data from
+     * @param size the length (number of elements) to use 
+     * from the data arrays
+     */
+    public DataBufferInt(int dataArrays[][], int size) {
+        super(TYPE_INT, size, dataArrays.length);
+        data = dataArrays.clone();
+    }
+
+    /**
+     * Instantiates a new data buffer of type int
+     * with a single underlying array of data.
+     * 
+     * @param dataArray the data array to copy the data from
+     * @param size the length (number of elements) to use 
+     * @param offset the starting index to use when reading the data
+     */
+    public DataBufferInt(int dataArray[], int size, int offset) {
+        super(TYPE_INT, size, 1, offset);
+        data = new int[1][];
+        data[0] = dataArray;
+    }
+
+    /**
+     * Instantiates a new data buffer of type int
+     * with a single underlying array of data starting at
+     * index 0.
+     * 
+     * @param dataArray the data array to copy the data from
+     * @param size the length (number of elements) to use 
+     */
+    public DataBufferInt(int dataArray[], int size) {
+        super(TYPE_INT, size);
+        data = new int[1][];
+        data[0] = dataArray;
+    }
+
+    /**
+     * Instantiates a new empty data buffer of type int
+     * with offsets equal to zero.
+     * 
+     * @param size the length (number of elements) to use 
+     * from the data arrays
+     * @param numBanks the number of data arrays to create
+     */
+    public DataBufferInt(int size, int numBanks) {
+        super(TYPE_INT, size, numBanks);
+        data = new int[numBanks][];
+        int i = 0;
+        while (i < numBanks) {
+            data[i++] = new int[size];
+        }
+    }
+
+    /**
+     * Instantiates a new empty data buffer of type int
+     * with a single underlying array of data starting at
+     * index 0.
+     * 
+     * @param size the length (number of elements) to use 
+     */
+    public DataBufferInt(int size) {
+        super(TYPE_INT, size);
+        data = new int[1][];
+        data[0] = new int[size];
+    }
+
+    @Override
+    public void setElem(int bank, int i, int val) {
+        data[bank][offsets[bank] + i] = val;
+        notifyChanged();
+    }
+
+    @Override
+    public void setElem(int i, int val) {
+        data[0][offset + i] = val;
+        notifyChanged();
+    }
+
+    @Override
+    public int getElem(int bank, int i) {
+        return data[bank][offsets[bank] + i];
+    }
+
+    /**
+     * Gets the data of the specified internal data array.
+     * 
+     * @param bank the index of the desired data array
+     * 
+     * @return the data
+     */
+    public int[] getData(int bank) {
+        notifyTaken();
+        return data[bank];
+    }
+
+    @Override
+    public int getElem(int i) {
+        return data[0][offset + i];
+    }
+
+    /**
+     * Gets the bank data.
+     * 
+     * @return the bank data
+     */
+    public int[][] getBankData() {
+        notifyTaken();
+        return data.clone();
+    }
+
+    /**
+     * Gets the data of the first data array.
+     * 
+     * @return the data
+     */
+    public int[] getData() {
+        notifyTaken();
+        return data[0];
+    }
+}
+
diff --git a/awt/java/awt/image/DataBufferShort.java b/awt/java/awt/image/DataBufferShort.java
new file mode 100644
index 0000000..819ba4a
--- /dev/null
+++ b/awt/java/awt/image/DataBufferShort.java
@@ -0,0 +1,172 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+/**
+ * The Class DataBufferShort is the subclass of DataBuffer
+ * for the case where the underlying data is short.
+ */
+public final class DataBufferShort extends DataBuffer {
+
+    /** The data. */
+    short data[][];
+
+    /**
+     * Instantiates a new data buffer of type short.
+     * 
+     * @param dataArrays the data arrays to copy the data from
+     * @param size the length (number of elements) to use 
+     * from the data arrays
+     * @param offsets the starting indices for reading the 
+     * data from the internal data arrays
+     */
+    public DataBufferShort(short dataArrays[][], int size, int offsets[]) {
+        super(TYPE_SHORT, size, dataArrays.length, offsets);
+        data = dataArrays.clone();
+    }
+
+    /**
+     * Instantiates a new data buffer of type short.
+     * 
+     * @param dataArrays the data arrays to copy the data from
+     * @param size the length (number of elements) to use 
+     * from the data arrays
+     */
+    public DataBufferShort(short dataArrays[][], int size) {
+        super(TYPE_SHORT, size, dataArrays.length);
+        data = dataArrays.clone();
+    }
+
+    /**
+     * Instantiates a new data buffer of type short
+     * with a single underlying array of data.
+     * 
+     * @param dataArray the data array to copy the data from
+     * @param size the length (number of elements) to use 
+     * @param offset the starting index to use when reading the data
+
+     */
+    public DataBufferShort(short dataArray[], int size, int offset) {
+        super(TYPE_SHORT, size, 1, offset);
+        data = new short[1][];
+        data[0] = dataArray;
+    }
+
+    /**
+     * Instantiates a new data buffer of type short
+     * with a single underlying array of data starting at
+     * index 0.
+     * 
+     * @param dataArray the data array to copy the data from
+     * @param size the length (number of elements) to use 
+
+     */
+    public DataBufferShort(short dataArray[], int size) {
+        super(TYPE_SHORT, size);
+        data = new short[1][];
+        data[0] = dataArray;
+    }
+
+    /**
+     * Instantiates a new data buffer of type short
+     * with offsets equal to zero.
+     * 
+     * @param size the length (number of elements) to use 
+     * from the data arrays
+     * @param numBanks the number of data arrays to create
+     */
+    public DataBufferShort(int size, int numBanks) {
+        super(TYPE_SHORT, size, numBanks);
+        data = new short[numBanks][];
+        int i = 0;
+        while (i < numBanks) {
+            data[i++] = new short[size];
+        }
+    }
+
+    /**
+     * Instantiates a new empty data buffer of type short
+     * with a single underlying array of data starting at
+     * index 0.
+     * 
+     * @param size the length (number of elements) to use 
+     */
+    public DataBufferShort(int size) {
+        super(TYPE_SHORT, size);
+        data = new short[1][];
+        data[0] = new short[size];
+    }
+
+    @Override
+    public void setElem(int bank, int i, int val) {
+        data[bank][offsets[bank] + i] = (short) val;
+        notifyChanged();
+    }
+
+    @Override
+    public void setElem(int i, int val) {
+        data[0][offset + i] = (short) val;
+        notifyChanged();
+    }
+
+    @Override
+    public int getElem(int bank, int i) {
+        return (data[bank][offsets[bank] + i]);
+    }
+
+    /**
+     * Gets the data of the specified internal data array.
+     * 
+     * @param bank the index of the desired data array
+     * 
+     * @return the data
+     */
+    public short[] getData(int bank) {
+        notifyTaken();
+        return data[bank];
+    }
+
+    @Override
+    public int getElem(int i) {
+        return (data[0][offset + i]);
+    }
+
+    /**
+     * Gets the bank data.
+     * 
+     * @return the bank data
+     */
+    public short[][] getBankData() {
+        notifyTaken();
+        return data.clone();
+    }
+
+    /**
+     * Gets the data of the first data array.
+     * 
+     * @return the data
+     */
+    public short[] getData() {
+        notifyTaken();
+        return data[0];
+    }
+}
+
diff --git a/awt/java/awt/image/DataBufferUShort.java b/awt/java/awt/image/DataBufferUShort.java
new file mode 100644
index 0000000..7982678
--- /dev/null
+++ b/awt/java/awt/image/DataBufferUShort.java
@@ -0,0 +1,182 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Class DataBufferUShort is the subclass of DataBuffer
+ * for the case where the underlying data is unsigned short.
+ */
+public final class DataBufferUShort extends DataBuffer {
+
+    /** The data. */
+    short data[][];
+
+    /**
+     * Instantiates a new data buffer of type unsigned short.
+     * 
+     * @param dataArrays the data arrays to copy the data from
+     * @param size the length (number of elements) to use 
+     * from the data arrays
+     * @param offsets the starting indices for reading the 
+     * data from the internal data arrays
+     */
+    public DataBufferUShort(short dataArrays[][], int size, int offsets[]) {
+        super(TYPE_USHORT, size, dataArrays.length, offsets);
+        for(int i = 0; i < dataArrays.length; i++){
+            if(dataArrays[i].length < offsets[i] + size){
+                // awt.28d=Length of dataArray[{0}] is less than size + offset[{1}]
+                throw new IllegalArgumentException(Messages.getString("awt.28D", i, i));  //$NON-NLS-1$
+            }
+        }
+        data = dataArrays.clone();
+    }
+
+    /**
+     * Instantiates a new data buffer of type unsigned short.
+     * 
+     * @param dataArrays the data arrays to copy the data from
+     * @param size the length (number of elements) to use 
+     * from the data arrays
+     */
+    public DataBufferUShort(short dataArrays[][], int size) {
+        super(TYPE_USHORT, size, dataArrays.length);
+        data = dataArrays.clone();
+    }
+
+    /**
+     * Instantiates a new data buffer of type unsigned short
+     * with a single underlying array of data.
+     * 
+     * @param dataArray the data array to copy the data from
+     * @param size the length (number of elements) to use 
+     * @param offset the starting index to use when reading the data
+     */
+    public DataBufferUShort(short dataArray[], int size, int offset) {
+        super(TYPE_USHORT, size, 1, offset);
+        if(dataArray.length < size + offset){
+            // awt.28E=Length of dataArray is less than size + offset
+            throw new IllegalArgumentException(Messages.getString("awt.28E")); //$NON-NLS-1$
+        }
+        data = new short[1][];
+        data[0] = dataArray;
+    }
+
+    /**
+     * Instantiates a new data buffer of type unsigned short
+     * with a single underlying array of data starting at
+     * index 0.
+     * 
+     * @param dataArray the data array to copy the data from
+     * @param size the length (number of elements) to use 
+     */
+    public DataBufferUShort(short dataArray[], int size) {
+        super(TYPE_USHORT, size);
+        data = new short[1][];
+        data[0] = dataArray;
+    }
+
+    /**
+     * Instantiates a new empty data buffer of type unsigned short
+     * with offsets equal to zero.
+     * 
+     * @param size the length (number of elements) to use 
+     * from the data arrays
+     * @param numBanks the number of data arrays to create
+     */
+    public DataBufferUShort(int size, int numBanks) {
+        super(TYPE_USHORT, size, numBanks);
+        data = new short[numBanks][];
+        int i= 0;
+        while( i < numBanks) {
+            data[i++] = new short[size];
+        }
+    }
+
+    /**
+     * Instantiates a new empty data buffer of type unsigned short
+     * with a single underlying array of data starting at
+     * index 0.
+     * 
+     * @param size the length (number of elements) to use 
+     */
+    public DataBufferUShort(int size) {
+        super(TYPE_USHORT, size);
+        data = new short[1][];
+        data[0] = new short[size];
+    }
+
+    @Override
+    public void setElem(int bank, int i, int val) {
+        data[bank][offsets[bank] + i] = (short)val;
+        notifyChanged();
+    }
+
+    @Override
+    public void setElem(int i, int val) {
+        data[0][offset + i] = (short)val;
+        notifyChanged();
+    }
+
+    @Override
+    public int getElem(int bank, int i) {
+        return (data[bank][offsets[bank] + i]) & 0xffff;
+    }
+
+    /**
+     * Gets the data of the specified internal data array.
+     * 
+     * @param bank the index of the desired data array
+     * 
+     * @return the data
+     */
+    public short[] getData(int bank) {
+        notifyTaken();
+        return data[bank];
+    }
+
+    @Override
+    public int getElem(int i) {
+        return (data[0][offset + i]) & 0xffff;
+    }
+
+    /**
+     * Gets the bank data.
+     * 
+     * @return the bank data
+     */
+    public short[][] getBankData() {
+        notifyTaken();
+        return data.clone();
+    }
+
+    /**
+     * Gets the data of the first data array.
+     * 
+     * @return the data
+     */
+    public short[] getData() {
+        notifyTaken();
+        return data[0];
+    }
+}
+
diff --git a/awt/java/awt/image/DirectColorModel.java b/awt/java/awt/image/DirectColorModel.java
new file mode 100644
index 0000000..7a287c0
--- /dev/null
+++ b/awt/java/awt/image/DirectColorModel.java
@@ -0,0 +1,862 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import java.awt.color.ColorSpace;
+import java.awt.Transparency;
+import java.util.Arrays;
+
+import org.apache.harmony.awt.gl.color.LUTColorConverter;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Class DirectColorModel represents a standard (packed) RGB
+ * color model with additional support for converting between sRGB
+ * color space and 8 or 16 bit linear RGB color space using lookup tables.
+ */
+public class DirectColorModel extends PackedColorModel {
+
+    /** The from_ linea r_ rg b_ lut. */
+    private byte from_LINEAR_RGB_LUT[]; // Lookup table for conversion from
+                                        // Linear RGB Color Space into sRGB
+
+    /** The to_ linea r_8 rg b_ lut. */
+    private byte to_LINEAR_8RGB_LUT[];  // Lookup table for conversion from
+                                        // sRGB Color Space into Linear RGB 
+                                        // 8 bit
+
+    /** The to_ linea r_16 rg b_ lut. */
+    private short to_LINEAR_16RGB_LUT[];  // Lookup table for conversion from
+                                          // sRGB Color Space into Linear RGB 
+                                          // 16 bit 
+
+    /** The alpha lut. */
+    private byte alphaLUT[];            // Lookup table for scale alpha value  
+
+    /** The color lu ts. */
+    private byte colorLUTs[][];         // Lookup tables for scale color values 
+
+    /** The is_s rgb. */
+    private boolean is_sRGB;            // ColorModel has sRGB ColorSpace
+
+    /** The is_ linea r_ rgb. */
+    private boolean is_LINEAR_RGB;      // Color Model has Linear RGB Color 
+                                        // Space
+
+    /** The LINEA r_ rg b_ length. */
+    private int LINEAR_RGB_Length;      // Linear RGB bit length
+
+    /** The factor. */
+    private float fFactor;              // Scale factor
+
+    /**
+     * Instantiates a new direct color model.
+     * 
+     * @param space the color space
+     * @param bits the array of component masks
+     * @param rmask the bitmask corresponding to the red band
+     * @param gmask the bitmask corresponding to the green band
+     * @param bmask the bitmask corresponding to the blue band
+     * @param amask the bitmask corresponding to the alpha band
+     * @param isAlphaPremultiplied whether the alpha is premultiplied in this color model
+     * @param transferType the transfer type (primitive java type 
+     * to use for the components)
+     * 
+     * @throws IllegalArgumentException if the number of bits in the combined 
+     * bitmasks for the color bands is less than one or greater than 32
+     */
+    public DirectColorModel(ColorSpace space, int bits, int rmask, int gmask,
+            int bmask, int amask, boolean isAlphaPremultiplied,
+            int transferType) {
+
+        super(space, bits, rmask, gmask, bmask, amask, isAlphaPremultiplied,
+                (amask == 0 ? Transparency.OPAQUE : Transparency.TRANSLUCENT),
+                transferType);
+
+        initLUTs();
+    }
+
+    /**
+     * Instantiates a new direct color model, determining the transfer 
+     * type from the bits array, the transparency from the alpha mask, 
+     * and the default color space {@link ColorSpace#CS_sRGB}.
+     * 
+     * @param bits the array of component masks
+     * @param rmask the bitmask corresponding to the red band
+     * @param gmask the bitmask corresponding to the green band
+     * @param bmask the bitmask corresponding to the blue band
+     * @param amask the bitmask corresponding to the alpha band
+     */
+    public DirectColorModel(int bits, int rmask, int gmask, int bmask,
+            int amask) {
+
+        super(ColorSpace.getInstance(ColorSpace.CS_sRGB), bits, rmask, gmask,
+                bmask, amask, false,
+                (amask == 0 ? Transparency.OPAQUE : Transparency.TRANSLUCENT),
+                ColorModel.getTransferType(bits));
+
+        initLUTs();
+    }
+
+    /**
+     * Instantiates a new direct color model with no alpha channel, 
+     * determining the transfer type from the bits array, 
+     * the default color space {@link ColorSpace#CS_sRGB}, 
+     * and with the transparency set to {@link Transparency#OPAQUE}.
+     * 
+     * @param bits the array of component masks
+     * @param rmask the bitmask corresponding to the red band
+     * @param gmask the bitmask corresponding to the green band
+     * @param bmask the bitmask corresponding to the blue band
+     */
+    public DirectColorModel(int bits, int rmask, int gmask, int bmask) {
+        this(bits, rmask, gmask, bmask, 0);
+    }
+
+    @Override
+    public Object getDataElements(int components[], int offset, Object obj) {
+        int pixel = 0;
+        for (int i = 0; i < numComponents; i++) {
+            pixel |= (components[offset + i] << offsets[i]) & componentMasks[i];
+        }
+
+        switch (transferType) {
+        case DataBuffer.TYPE_BYTE:
+            byte ba[];
+            if (obj == null) {
+                ba = new byte[1];
+            } else {
+                ba = (byte[]) obj;
+            }
+            ba[0] = (byte) pixel;
+            obj = ba;
+            break;
+
+        case DataBuffer.TYPE_USHORT:
+            short sa[];
+            if (obj == null) {
+                sa = new short[1];
+            } else {
+                sa = (short[]) obj;
+            }
+            sa[0] = (short) pixel;
+            obj = sa;
+            break;
+
+        case DataBuffer.TYPE_INT:
+            int ia[];
+            if (obj == null) {
+                ia = new int[1];
+            } else {
+                ia = (int[]) obj;
+            }
+            ia[0] = pixel;
+            obj = ia;
+            break;
+
+        default:
+            // awt.214=This Color Model doesn't support this transferType
+            throw new UnsupportedOperationException(Messages.getString("awt.214")); //$NON-NLS-1$
+        }
+
+        return obj;
+    }
+
+    @Override
+    public Object getDataElements(int rgb, Object pixel) {
+        if (equals(ColorModel.getRGBdefault())) {
+            int ia[];
+            if (pixel == null) {
+                ia = new int[1];
+            } else {
+                ia = (int[]) pixel;
+            }
+            ia[0] = rgb;
+            return ia;
+        }
+
+        int alpha = (rgb >> 24) & 0xff;
+        int red = (rgb >> 16) & 0xff;
+        int green = (rgb >> 8) & 0xff;
+        int blue = rgb & 0xff;
+
+        float comp[] = new float[numColorComponents];
+        float normComp[] = null;
+
+        if (is_sRGB || is_LINEAR_RGB) {
+            if (is_LINEAR_RGB) {
+                if (LINEAR_RGB_Length == 8) {
+                    red = to_LINEAR_8RGB_LUT[red] & 0xff;
+                    green = to_LINEAR_8RGB_LUT[green] & 0xff;
+                    blue = to_LINEAR_8RGB_LUT[blue] & 0xff;
+                } else {
+                    red = to_LINEAR_16RGB_LUT[red] & 0xffff;
+                    green = to_LINEAR_16RGB_LUT[green] & 0xffff;
+                    blue = to_LINEAR_16RGB_LUT[blue] & 0xffff;
+                }
+            }
+            comp[0] = red / fFactor;
+            comp[1] = green / fFactor;
+            comp[2] = blue / fFactor;
+            if (!hasAlpha) {
+                normComp = comp;
+            } else {
+                float normAlpha = alpha / 255.0f;
+                normComp = new float[numComponents];
+                for (int i = 0; i < numColorComponents; i++) {
+                    normComp[i] = comp[i];
+                }
+                normComp[numColorComponents] = normAlpha;
+            }
+        } else {
+            comp[0] = red / fFactor;
+            comp[1] = green / fFactor;
+            comp[2] = blue / fFactor;
+            float rgbComp[] = cs.fromRGB(comp);
+            if (!hasAlpha) {
+                normComp = rgbComp;
+            } else {
+                float normAlpha = alpha / 255.0f;
+                normComp = new float[numComponents];
+                for (int i = 0; i < numColorComponents; i++) {
+                    normComp[i] = rgbComp[i];
+                }
+                normComp[numColorComponents] = normAlpha;
+            }
+        }
+
+        int pxl = 0;
+        if (hasAlpha) {
+            float normAlpha = normComp[numColorComponents];
+            alpha = (int) (normAlpha * maxValues[numColorComponents] + 0.5f);
+            if (isAlphaPremultiplied) {
+                red = (int) (normComp[0] * normAlpha * maxValues[0] + 0.5f);
+                green = (int) (normComp[1] * normAlpha * maxValues[1] + 0.5f);
+                blue = (int) (normComp[2] * normAlpha * maxValues[2] + 0.5f);
+            } else {
+                red = (int) (normComp[0] * maxValues[0] + 0.5f);
+                green = (int) (normComp[1] * maxValues[1] + 0.5f);
+                blue = (int) (normComp[2] * maxValues[2] + 0.5f);
+            }
+            pxl = (alpha << offsets[3]) & componentMasks[3];
+        } else {
+            red = (int) (normComp[0] * maxValues[0] + 0.5f);
+            green = (int) (normComp[1] * maxValues[1] + 0.5f);
+            blue = (int) (normComp[2] * maxValues[2] + 0.5f);
+        }
+
+        pxl |= ((red << offsets[0]) & componentMasks[0]) |
+               ((green << offsets[1]) & componentMasks[1]) |
+               ((blue << offsets[2]) & componentMasks[2]);
+
+        switch (transferType) {
+        case DataBuffer.TYPE_BYTE:
+            byte ba[];
+            if (pixel == null) {
+                ba = new byte[1];
+            } else {
+                ba = (byte[]) pixel;
+            }
+            ba[0] = (byte) pxl;
+            return ba;
+
+        case DataBuffer.TYPE_USHORT:
+            short sa[];
+            if (pixel == null) {
+                sa = new short[1];
+            } else {
+                sa = (short[]) pixel;
+            }
+            sa[0] = (short) pxl;
+            return sa;
+
+        case DataBuffer.TYPE_INT:
+            int ia[];
+            if (pixel == null) {
+                ia = new int[1];
+            } else {
+                ia = (int[]) pixel;
+            }
+            ia[0] = pxl;
+            return ia;
+
+        default:
+            // awt.214=This Color Model doesn't support this transferType
+            throw new UnsupportedOperationException(Messages.getString("awt.214")); //$NON-NLS-1$
+        }
+    }
+
+    @Override
+    public final ColorModel coerceData(WritableRaster raster,
+            boolean isAlphaPremultiplied) {
+
+        if (!hasAlpha || this.isAlphaPremultiplied == isAlphaPremultiplied) {
+            return this;
+        }
+
+        int minX = raster.getMinX();
+        int minY = raster.getMinY();
+        int w = raster.getWidth();
+        int h = raster.getHeight();
+
+        int components[] = null;
+        int transparentComponents[] = new int[numComponents];
+
+        float alphaFactor = maxValues[numColorComponents];
+
+        if (isAlphaPremultiplied) {
+            switch (transferType) {
+            case DataBuffer.TYPE_BYTE:
+            case DataBuffer.TYPE_USHORT:
+            case DataBuffer.TYPE_INT:
+                for (int i = 0; i < h; i++, minY++) {
+                    for (int j = 0, x = minX; j < w; j++, x++) {
+                        components = raster.getPixel(x, minY, components);
+                        if (components[numColorComponents] == 0) {
+                            raster.setPixel(x, minY, transparentComponents);
+                        } else {
+                            float alpha =
+                                components[numColorComponents] /
+                                    alphaFactor;
+                            for (int n = 0; n < numColorComponents; n++) {
+                                components[n] =
+                                    (int) (alpha * components[n] + 0.5f);
+                            }
+                            raster.setPixel(x, minY, components);
+                        }
+                    }
+
+                }
+                break;
+
+            default:
+                // awt.214=This Color Model doesn't support this transferType
+                throw new UnsupportedOperationException(Messages.getString("awt.214")); //$NON-NLS-1$
+            }
+        } else {
+            switch (transferType) {
+            case DataBuffer.TYPE_BYTE:
+            case DataBuffer.TYPE_USHORT:
+            case DataBuffer.TYPE_INT:
+                for (int i = 0; i < h; i++, minY++) {
+                    for (int j = 0, x = minX; j < w; j++, x++) {
+                        components = raster.getPixel(x, minY, components);
+                        if (components[numColorComponents] != 0) {
+                            float alpha =
+                                alphaFactor / components[numColorComponents];
+                            for (int n = 0; n < numColorComponents; n++) {
+                                components[n] =
+                                    (int) (alpha * components[n] + 0.5f);
+                            }
+                            raster.setPixel(x, minY, components);
+                        }
+                    }
+
+                }
+                break;
+
+            default:
+                // awt.214=This Color Model doesn't support this transferType
+                throw new UnsupportedOperationException(Messages.getString("awt.214")); //$NON-NLS-1$
+            }
+
+        }
+
+        return new DirectColorModel(cs, pixel_bits, componentMasks[0],
+                componentMasks[1], componentMasks[2], componentMasks[3],
+                isAlphaPremultiplied, transferType);
+    }
+
+    @Override
+    public String toString() {
+        // The output format based on 1.5 release behaviour. 
+        // It could be reveled such way:
+        // BufferedImage bi = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
+        // ColorModel cm = bi.getColorModel();
+        // System.out.println(cm.toString());
+        String str = "DirectColorModel:" + " rmask = " + //$NON-NLS-1$ //$NON-NLS-2$
+               Integer.toHexString(componentMasks[0]) + " gmask = " + //$NON-NLS-1$
+               Integer.toHexString(componentMasks[1]) + " bmask = " + //$NON-NLS-1$
+               Integer.toHexString(componentMasks[2]) + " amask = " + //$NON-NLS-1$
+               (!hasAlpha ? "0" : Integer.toHexString(componentMasks[3])); //$NON-NLS-1$
+
+        return str;
+    }
+
+    @Override
+    public final int[] getComponents(Object pixel, int components[],
+            int offset) {
+
+        if (components == null) {
+            components = new int[numComponents + offset];
+        }
+
+        int intPixel = 0;
+
+        switch (transferType) {
+        case DataBuffer.TYPE_BYTE:
+            byte ba[] = (byte[]) pixel;
+            intPixel = ba[0] & 0xff;
+            break;
+
+        case DataBuffer.TYPE_USHORT:
+            short sa[] = (short[]) pixel;
+            intPixel = sa[0] & 0xffff;
+            break;
+
+        case DataBuffer.TYPE_INT:
+            int ia[] = (int[]) pixel;
+            intPixel = ia[0];
+            break;
+
+        default:
+            // awt.22D=This transferType ( {0} ) is not supported by this color model
+            throw new UnsupportedOperationException(Messages.getString("awt.22D", //$NON-NLS-1$
+                   transferType));
+        }
+
+        return getComponents(intPixel, components, offset);
+    }
+
+    @Override
+    public int getRed(Object inData) {
+        int pixel = 0;
+        switch (transferType) {
+        case DataBuffer.TYPE_BYTE:
+            byte ba[] = (byte[]) inData;
+            pixel = ba[0] & 0xff;
+            break;
+
+        case DataBuffer.TYPE_USHORT:
+            short sa[] = (short[]) inData;
+            pixel = sa[0] & 0xffff;
+            break;
+
+        case DataBuffer.TYPE_INT:
+            int ia[] = (int[]) inData;
+            pixel = ia[0];
+            break;
+
+        default:
+            // awt.214=This Color Model doesn't support this transferType
+            throw new UnsupportedOperationException(Messages.getString("awt.214")); //$NON-NLS-1$
+        }
+        return getRed(pixel);
+    }
+
+    @Override
+    public int getRGB(Object inData) {
+        int pixel = 0;
+        switch (transferType) {
+        case DataBuffer.TYPE_BYTE:
+            byte ba[] = (byte[]) inData;
+            pixel = ba[0] & 0xff;
+            break;
+
+        case DataBuffer.TYPE_USHORT:
+            short sa[] = (short[]) inData;
+            pixel = sa[0] & 0xffff;
+            break;
+
+        case DataBuffer.TYPE_INT:
+            int ia[] = (int[]) inData;
+            pixel = ia[0];
+            break;
+
+        default:
+            // awt.214=This Color Model doesn't support this transferType
+            throw new UnsupportedOperationException(Messages.getString("awt.214")); //$NON-NLS-1$
+        }
+        return getRGB(pixel);
+    }
+
+    @Override
+    public int getGreen(Object inData) {
+        int pixel = 0;
+        switch (transferType) {
+        case DataBuffer.TYPE_BYTE:
+            byte ba[] = (byte[]) inData;
+            pixel = ba[0] & 0xff;
+            break;
+
+        case DataBuffer.TYPE_USHORT:
+            short sa[] = (short[]) inData;
+            pixel = sa[0] & 0xffff;
+            break;
+
+        case DataBuffer.TYPE_INT:
+            int ia[] = (int[]) inData;
+            pixel = ia[0];
+            break;
+
+        default:
+            // awt.214=This Color Model doesn't support this transferType
+            throw new UnsupportedOperationException(Messages.getString("awt.214")); //$NON-NLS-1$
+        }
+        return getGreen(pixel);
+    }
+
+    @Override
+    public int getBlue(Object inData) {
+        int pixel = 0;
+        switch (transferType) {
+        case DataBuffer.TYPE_BYTE:
+            byte ba[] = (byte[]) inData;
+            pixel = ba[0] & 0xff;
+            break;
+
+        case DataBuffer.TYPE_USHORT:
+            short sa[] = (short[]) inData;
+            pixel = sa[0] & 0xffff;
+            break;
+
+        case DataBuffer.TYPE_INT:
+            int ia[] = (int[]) inData;
+            pixel = ia[0];
+            break;
+
+        default:
+            // awt.214=This Color Model doesn't support this transferType
+            throw new UnsupportedOperationException(Messages.getString("awt.214")); //$NON-NLS-1$
+        }
+        return getBlue(pixel);
+    }
+
+    @Override
+    public int getAlpha(Object inData) {
+        int pixel = 0;
+        switch (transferType) {
+        case DataBuffer.TYPE_BYTE:
+            byte ba[] = (byte[]) inData;
+            pixel = ba[0] & 0xff;
+            break;
+
+        case DataBuffer.TYPE_USHORT:
+            short sa[] = (short[]) inData;
+            pixel = sa[0] & 0xffff;
+            break;
+
+        case DataBuffer.TYPE_INT:
+            int ia[] = (int[]) inData;
+            pixel = ia[0];
+            break;
+
+        default:
+            // awt.214=This Color Model doesn't support this transferType
+            throw new UnsupportedOperationException(Messages.getString("awt.214")); //$NON-NLS-1$
+        }
+        return getAlpha(pixel);
+    }
+
+    @Override
+    public final WritableRaster createCompatibleWritableRaster(int w, int h) {
+        if (w <= 0 || h <= 0) {
+            // awt.22E=w or h is less than or equal to zero
+            throw new IllegalArgumentException(Messages.getString("awt.22E")); //$NON-NLS-1$
+        }
+
+        int bandMasks[] = componentMasks.clone();
+
+        if (pixel_bits > 16) {
+            return Raster.createPackedRaster(DataBuffer.TYPE_INT, w, h,
+                    bandMasks, null);
+        } else if (pixel_bits > 8) {
+            return Raster.createPackedRaster(DataBuffer.TYPE_USHORT, w, h,
+                    bandMasks, null);
+        } else {
+            return Raster.createPackedRaster(DataBuffer.TYPE_BYTE, w, h,
+                    bandMasks, null);
+        }
+    }
+
+    @Override
+    public boolean isCompatibleRaster(Raster raster) {
+        SampleModel sm = raster.getSampleModel();
+        if (!(sm instanceof SinglePixelPackedSampleModel)) {
+            return false;
+        }
+
+        SinglePixelPackedSampleModel sppsm = (SinglePixelPackedSampleModel) sm;
+
+        if (sppsm.getNumBands() != numComponents) {
+            return false;
+        }
+        if (raster.getTransferType() != transferType) {
+            return false;
+        }
+
+        int maskBands[] = sppsm.getBitMasks();
+        return Arrays.equals(maskBands, componentMasks);
+    }
+
+    @Override
+    public int getDataElement(int components[], int offset) {
+        int pixel = 0;
+        for (int i = 0; i < numComponents; i++) {
+            pixel |= (components[offset + i] << offsets[i]) & componentMasks[i];
+        }
+        return pixel;
+    }
+
+    @Override
+    public final int[] getComponents(int pixel, int components[], int offset) {
+        if (components == null) {
+            components = new int[numComponents + offset];
+        }
+        for (int i = 0; i < numComponents; i++) {
+            components[offset + i] = (pixel & componentMasks[i]) >> offsets[i];
+        }
+        return components;
+    }
+
+    @Override
+    public final int getRed(int pixel) {
+        if (is_sRGB) {
+            return getComponentFrom_sRGB(pixel, 0);
+        }
+        if (is_LINEAR_RGB) {
+            return getComponentFrom_LINEAR_RGB(pixel, 0);
+        }
+        return getComponentFrom_RGB(pixel, 0);
+    }
+
+    @Override
+    public final int getRGB(int pixel) {
+        return (getAlpha(pixel) << 24) | (getRed(pixel) << 16) |
+               (getGreen(pixel) << 8) | getBlue(pixel);
+    }
+
+    @Override
+    public final int getGreen(int pixel) {
+        if (is_sRGB) {
+            return getComponentFrom_sRGB(pixel, 1);
+        }
+        if (is_LINEAR_RGB) {
+            return getComponentFrom_LINEAR_RGB(pixel, 1);
+        }
+        return getComponentFrom_RGB(pixel, 1);
+    }
+
+    @Override
+    public final int getBlue(int pixel) {
+        if (is_sRGB) {
+            return getComponentFrom_sRGB(pixel, 2);
+        }
+        if (is_LINEAR_RGB) {
+            return getComponentFrom_LINEAR_RGB(pixel, 2);
+        }
+        return getComponentFrom_RGB(pixel, 2);
+    }
+
+    @Override
+    public final int getAlpha(int pixel) {
+        if (!hasAlpha) {
+            return 255;
+        }
+        int a = (pixel & componentMasks[3]) >>> offsets[3];
+        if (bits[3] == 8) {
+            return a;
+        }
+        return alphaLUT[a] & 0xff;
+    }
+
+    /**
+     * Gets the red mask.
+     * 
+     * @return the red mask
+     */
+    public final int getRedMask() {
+        return componentMasks[0];
+    }
+
+    /**
+     * Gets the green mask.
+     * 
+     * @return the green mask
+     */
+    public final int getGreenMask() {
+        return componentMasks[1];
+    }
+
+    /**
+     * Gets the blue mask.
+     * 
+     * @return the blue mask
+     */
+    public final int getBlueMask() {
+        return componentMasks[2];
+    }
+
+    /**
+     * Gets the alpha mask.
+     * 
+     * @return the alpha mask
+     */
+    public final int getAlphaMask() {
+        if (hasAlpha) {
+            return componentMasks[3];
+        }
+        return 0;
+    }
+
+    /**
+     * Initialization of Lookup tables.
+     */
+    private void initLUTs() {
+        is_sRGB = cs.isCS_sRGB();
+        is_LINEAR_RGB = (cs == LUTColorConverter.LINEAR_RGB_CS);
+
+        if (is_LINEAR_RGB) {
+            if (maxBitLength > 8) {
+                LINEAR_RGB_Length = 16;
+                from_LINEAR_RGB_LUT =
+                    LUTColorConverter.getFrom16lRGBtosRGB_LUT();
+                to_LINEAR_16RGB_LUT =
+                    LUTColorConverter.getFromsRGBto16lRGB_LUT();
+            } else {
+                LINEAR_RGB_Length = 8;
+                from_LINEAR_RGB_LUT =
+                    LUTColorConverter.getFrom8lRGBtosRGB_LUT();
+                to_LINEAR_8RGB_LUT =
+                    LUTColorConverter.getFromsRGBto8lRGB_LUT();
+            }
+            fFactor = ((1 << LINEAR_RGB_Length) - 1);
+        } else {
+            fFactor = 255.0f;
+        }
+
+        if (hasAlpha && bits[3] != 8) {
+            alphaLUT = new byte[maxValues[3] + 1];
+            for (int i = 0; i <= maxValues[3]; i++) {
+                alphaLUT[i] = (byte) (scales[3] * i + 0.5f);
+            }
+
+        }
+
+        if (!isAlphaPremultiplied) {
+            colorLUTs = new byte[3][];
+
+            if (is_sRGB) {
+                for (int i = 0; i < numColorComponents; i++) {
+                    if (bits[i] != 8) {
+                        for (int j = 0; j < i; j++) {
+                            if (bits[i] == bits[j]) {
+                                colorLUTs[i] = colorLUTs[j];
+                                break;
+                            }
+                        }
+                        colorLUTs[i] = new byte[maxValues[i] + 1];
+                        for (int j = 0; j <= maxValues[i]; j++) {
+                            colorLUTs[i][j] = (byte) (scales[i] * j + 0.5f);
+                        }
+                    }
+                }
+            }
+
+            if (is_LINEAR_RGB) {
+                for (int i = 0; i < numColorComponents; i++) {
+                    if (bits[i] != LINEAR_RGB_Length) {
+                        for (int j = 0; j < i; j++) {
+                            if (bits[i] == bits[j]) {
+                                colorLUTs[i] = colorLUTs[j];
+                                break;
+                            }
+                        }
+                        colorLUTs[i] = new byte[maxValues[i] + 1];
+                        for (int j = 0; j <= maxValues[0]; j++) {
+                            int idx;
+                            if (LINEAR_RGB_Length == 8) {
+                                idx = (int) (scales[i] * j + 0.5f);
+                            } else {
+                                idx = (int) (scales[i] * j * 257.0f + 0.5f);
+                            }
+                            colorLUTs[i][j] = from_LINEAR_RGB_LUT[idx];
+                        }
+                    }
+                }
+            }
+
+        }
+    }
+
+    /**
+     * This method return RGB component value if Color Model has
+     * sRGB ColorSpace.
+     * 
+     * @param pixel - INT representation of pixel
+     * @param idx - index of pixel component
+     * 
+     * @return - value of the pixel component scaled fro 0 to 255
+     */
+    private int getComponentFrom_sRGB(int pixel, int idx) {
+        int comp = (pixel & componentMasks[idx]) >> offsets[idx];
+        if (isAlphaPremultiplied) {
+            int alpha = (pixel & componentMasks[3]) >>> offsets[3];
+            comp = alpha == 0 ? 0 : (int) (scales[idx] * comp * 255.0f /
+                    (scales[3] * alpha) + 0.5f);
+        } else if (bits[idx] != 8) {
+            comp = colorLUTs[idx][comp] & 0xff;
+        }
+        return comp;
+    }
+
+    /**
+     * This method return RGB component value if Color Model has
+     * Linear RGB ColorSpace.
+     * 
+     * @param pixel - INT representation of pixel
+     * @param idx - index of pixel component
+     * 
+     * @return - value of the pixel component scaled fro 0 to 255
+     */
+    private int getComponentFrom_LINEAR_RGB(int pixel, int idx) {
+        int comp = (pixel & componentMasks[idx]) >> offsets[idx];
+        if (isAlphaPremultiplied) {
+            float factor = ((1 << LINEAR_RGB_Length) - 1);
+            int alpha = (pixel & componentMasks[3]) >> offsets[3];
+            comp = alpha == 0 ? 0 : (int) (scales[idx] * comp * factor /
+                    (scales[3] * alpha) + 0.5f);
+        } else if (bits[idx] != LINEAR_RGB_Length) {
+            comp = colorLUTs[idx][comp] & 0xff;
+        } else {
+            comp = from_LINEAR_RGB_LUT[comp] & 0xff;
+        }
+        return comp;
+    }
+
+    /**
+     * This method return RGB component value if Color Model has
+     * arbitrary RGB ColorSapce.
+     * 
+     * @param pixel - INT representation of pixel
+     * @param idx - index of pixel component
+     * 
+     * @return - value of the pixel component scaled fro 0 to 255
+     */
+    private int getComponentFrom_RGB(int pixel, int idx) {
+        int components[] = getComponents(pixel, null, 0);
+        float[] normComponents = getNormalizedComponents(components, 0, null, 0);
+        float[] sRGBcomponents = cs.toRGB(normComponents);
+        return (int) (sRGBcomponents[idx] * 255.0f + 0.5f);
+    }
+
+}
+
diff --git a/awt/java/awt/image/FilteredImageSource.java b/awt/java/awt/image/FilteredImageSource.java
new file mode 100644
index 0000000..6a41fa7
--- /dev/null
+++ b/awt/java/awt/image/FilteredImageSource.java
@@ -0,0 +1,88 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import java.util.Hashtable;
+
+
+/**
+ * The FilteredImageSource class is used for producing image data for a new 
+ * filtered version of the original image using the specified filter object. 
+ */
+public class FilteredImageSource implements ImageProducer {
+
+    /** The source. */
+    private final ImageProducer source;
+    
+    /** The filter. */
+    private final ImageFilter filter;
+
+    /** The cons table. */
+    private final Hashtable<ImageConsumer, ImageConsumer> consTable = new Hashtable<ImageConsumer, ImageConsumer>();
+
+    /**
+     * Instantiates a new FilteredImageSource object with 
+     * the specified ImageProducer and the ImageFilter objects.
+     * 
+     * @param orig the specified ImageProducer.
+     * @param imgf the specified ImageFilter.
+     */
+    public FilteredImageSource(ImageProducer orig, ImageFilter imgf) {
+        source = orig;
+        filter = imgf;
+    }
+
+    public synchronized boolean isConsumer(ImageConsumer ic) {
+        if(ic != null) {
+            return consTable.containsKey(ic);
+        }
+        return false;
+    }
+
+    public void startProduction(ImageConsumer ic) {
+        addConsumer(ic);
+        ImageConsumer fic = consTable.get(ic);
+        source.startProduction(fic);
+    }
+
+    public void requestTopDownLeftRightResend(ImageConsumer ic) {
+        if(ic != null && isConsumer(ic)){
+            ImageFilter fic = (ImageFilter) consTable.get(ic);
+            fic.resendTopDownLeftRight(source);
+        }
+    }
+
+    public synchronized void removeConsumer(ImageConsumer ic) {
+        if(ic != null && isConsumer(ic)){
+            ImageConsumer fic = consTable.get(ic);
+            source.removeConsumer(fic);
+            consTable.remove(ic);
+        }
+    }
+
+    public synchronized void addConsumer(ImageConsumer ic) {
+        if(ic != null && !isConsumer(ic)){
+            ImageConsumer fic = filter.getFilterInstance(ic);
+            source.addConsumer(fic);
+            consTable.put(ic, fic);
+        }
+    }
+}
diff --git a/awt/java/awt/image/ImageConsumer.java b/awt/java/awt/image/ImageConsumer.java
new file mode 100644
index 0000000..2eba290
--- /dev/null
+++ b/awt/java/awt/image/ImageConsumer.java
@@ -0,0 +1,165 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import java.util.Hashtable;
+
+/**
+ * The ImageConsumer interface provides the data about the image
+ * and about how its data is delivered.  A ImageProducer provides 
+ * all of the information about the image using 
+ * the methods defined in this interface.
+ */
+public interface ImageConsumer {
+
+    /** 
+     * The Constant RANDOMPIXELORDER indicates that the pixels are 
+     * delivered in a random order.
+     */
+    public static final int RANDOMPIXELORDER = 1;
+
+    /** 
+     * The Constant TOPDOWNLEFTRIGHT indicates that the pixels are 
+     * delivered in top-down, left-to-right order. 
+     */
+    public static final int TOPDOWNLEFTRIGHT = 2;
+
+    /** 
+     * The Constant COMPLETESCANLINES indicates that the pixels are
+     * delivered in complete scanline. 
+     */
+    public static final int COMPLETESCANLINES = 4;
+
+    /** 
+     * The Constant SINGLEPASS indicates that pixels are delivered 
+     * in a single pass. 
+     */
+    public static final int SINGLEPASS = 8;
+
+    /** 
+     * The Constant SINGLEFRAME indicates that image consists of
+     * single frame.
+     */
+    public static final int SINGLEFRAME = 16;
+
+    /** 
+     * The Constant IMAGEERROR indicates an image error during image producing.
+     */
+    public static final int IMAGEERROR = 1;
+
+    /** 
+     * The Constant SINGLEFRAMEDONE indicates that only one of the 
+     * image's frames is completed. 
+     */
+    public static final int SINGLEFRAMEDONE = 2;
+
+    /** 
+     * The Constant STATICIMAGEDONE indicates that the image is completed. 
+     */
+    public static final int STATICIMAGEDONE = 3;
+
+    /** 
+     * The Constant IMAGEABORTED indicates that the image producing 
+     * process is aborted. 
+     */
+    public static final int IMAGEABORTED = 4;
+
+    /**
+     * Sets the properties for the image associated with this ImageConsumer.
+     * 
+     * @param props the properties for the image associated with 
+     * this ImageConsumer.
+     */
+    public void setProperties(Hashtable<?, ?> props);
+
+    /**
+     * Sets the ColorModel object.
+     * 
+     * @param model the new ColorModel.
+     */
+    public void setColorModel(ColorModel model);
+
+    /**
+     * Sets the pixels for the specified rectangular area of the image.
+     * 
+     * @param x the X coordinate of rectangular area.
+     * @param y the Y coordinate of rectangular area.
+     * @param w the width of rectangular area.
+     * @param h the height of rectangular area.
+     * @param model the specified ColorModel to be used for pixels
+     * converting.  
+     * @param pixels the array of pixels.
+     * @param off the offset of pixels array.
+     * @param scansize the distance from the one row of pixels
+     * to the next row in the specified array.
+     */
+    public void setPixels(int x, int y, int w, int h, ColorModel model,
+            int[] pixels, int off, int scansize);
+
+    /**
+     * Sets the pixels for the specified rectangular area of the image.
+     * 
+     * @param x the X coordinate of rectangular area.
+     * @param y the Y coordinate of rectangular area.
+     * @param w the width of rectangular area.
+     * @param h the height of rectangular area.
+     * @param model the specified ColorModel to be used for pixels
+     * converting.  
+     * @param pixels the array of pixels.
+     * @param off the offset of pixels array.
+     * @param scansize the distance from the one row of pixels
+     * to the next row in the specified array.
+     */
+    public void setPixels(int x, int y, int w, int h, ColorModel model,
+            byte[] pixels, int off, int scansize);
+
+    /**
+     * Sets the dimensions of a source image.
+     * 
+     * @param width the width of the image.
+     * @param height the height of the image.
+     */
+    public void setDimensions(int width, int height);
+
+    /**
+     * Sets the hint flags of pixels order, which is used by 
+     * the ImageConsumer for obtaining pixels from the ImageProducer
+     * for which this ImageConsumer is added.
+     * 
+     * @param hintflags the mask of hint flags. 
+     */
+    public void setHints(int hintflags);
+
+    /**
+     * THis method is called in the one of the following cases:
+     * <ul>
+     * <li>The ImageProducer (for which this ImageConsumer is added) 
+     * has been delivered all pixels of the source image. </li>
+     * <li>A one frame of an animation has been completed. </li> 
+     * <li> An error while loading or producing of the image has occured.
+     * </ul> 
+     * 
+     * @param status the status of image producing.
+     */
+    public void imageComplete(int status);
+
+}
+
diff --git a/awt/java/awt/image/ImageFilter.java b/awt/java/awt/image/ImageFilter.java
new file mode 100644
index 0000000..e386d65
--- /dev/null
+++ b/awt/java/awt/image/ImageFilter.java
@@ -0,0 +1,129 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import java.util.Hashtable;
+
+/**
+ * The ImageFilter class provides a filter for delivering image data 
+ * from an ImageProducer to an ImageConsumer.
+ */
+public class ImageFilter implements ImageConsumer, Cloneable {
+
+    /** The consumer. */
+    protected ImageConsumer consumer;
+
+    /**
+     * Instantiates a new ImageFilter.
+     */
+    public ImageFilter() {
+        super();
+    }
+
+    /**
+     * Gets an instance of an ImageFilter object which performs
+     * the filtering for the specified ImageConsumer.
+     *  
+     * @param ic the specified ImageConsumer.
+     * 
+     * @return an ImageFilter used to perform the filtering for 
+     * the specified ImageConsumer.
+     */
+    public ImageFilter getFilterInstance(ImageConsumer ic) {
+        ImageFilter filter = (ImageFilter) clone();
+        filter.consumer = ic;
+        return filter;
+    }
+
+    @SuppressWarnings("unchecked")
+    public void setProperties(Hashtable<?, ?> props) {
+        Hashtable<Object, Object> fprops;
+        if (props == null) {
+            fprops = new Hashtable<Object, Object>();
+        } else {
+            fprops = (Hashtable<Object, Object>) props.clone();
+        }
+        String propName = "Filters"; //$NON-NLS-1$
+        String prop = "Null filter"; //$NON-NLS-1$
+        Object o = fprops.get(propName);
+        if (o != null) {
+            if (o instanceof String) {
+                prop = (String) o + "; " + prop; //$NON-NLS-1$
+            } else {
+                prop = o.toString() + "; " + prop; //$NON-NLS-1$
+            }
+        }
+        fprops.put(propName, prop);
+        consumer.setProperties(fprops);
+    }
+
+    /**
+     * Returns a copy of this ImageFilter.
+     * 
+     * @return a copy of this ImageFilter.
+     */
+    @Override
+    public Object clone() {
+        try {
+            return super.clone();
+        } catch (CloneNotSupportedException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Responds to a request for a Top-Down-Left-Right ordered 
+     * resend of the pixel data from an ImageConsumer. 
+     * 
+     * @param ip the ImageProducer that provides this instance of 
+     * the filter.
+     */
+    public void resendTopDownLeftRight(ImageProducer ip) {
+        ip.requestTopDownLeftRightResend(this);
+    }
+
+    public void setColorModel(ColorModel model) {
+        consumer.setColorModel(model);
+    }
+
+    public void setPixels(int x, int y, int w, int h, ColorModel model, int[] pixels, int off,
+            int scansize) {
+        consumer.setPixels(x, y, w, h, model, pixels, off, scansize);
+    }
+
+    public void setPixels(int x, int y, int w, int h, ColorModel model, byte[] pixels, int off,
+            int scansize) {
+        consumer.setPixels(x, y, w, h, model, pixels, off, scansize);
+    }
+
+    public void setDimensions(int width, int height) {
+        consumer.setDimensions(width, height);
+    }
+
+    public void setHints(int hints) {
+        consumer.setHints(hints);
+    }
+
+    public void imageComplete(int status) {
+        consumer.imageComplete(status);
+    }
+
+}
diff --git a/awt/java/awt/image/ImageObserver.java b/awt/java/awt/image/ImageObserver.java
new file mode 100644
index 0000000..418bd07
--- /dev/null
+++ b/awt/java/awt/image/ImageObserver.java
@@ -0,0 +1,99 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import java.awt.Image;
+
+/**
+ * the ImageObserver interface is an asynchronous update interface 
+ * for receiving notifications about Image construction status.
+ */
+public interface ImageObserver {
+
+    /** 
+     * The Constant WIDTH indicates that the width of the image is 
+     * available. 
+     */
+    public static final int WIDTH = 1;
+
+    /** 
+     * The Constant HEIGHT indicates that the width of the image is 
+     * available.
+     */
+    public static final int HEIGHT = 2;
+
+    /** 
+     * The Constant PROPERTIES indicates that the properties of the image
+     * are available. 
+     */
+    public static final int PROPERTIES = 4;
+
+    /**
+     *  The Constant SOMEBITS indicates that more bits needed for 
+     *  drawing a scaled variation of the image pixels are available.
+     */
+    public static final int SOMEBITS = 8;
+
+    /** 
+     * The Constant FRAMEBITS indicates that complete frame of 
+     * a image which was previously drawn is now available
+     * for drawing again. 
+     */
+    public static final int FRAMEBITS = 16;
+
+    /** 
+     * The Constant ALLBITS indicates that an image which 
+     * was previously drawn is now complete and can be drawn again. 
+     */
+    public static final int ALLBITS = 32;
+
+    /** 
+     * The Constant ERROR indicates that error occured. 
+     */
+    public static final int ERROR = 64;
+
+    /** 
+     * The Constant ABORT indicates that the image producing is 
+     * aborted.
+     */
+    public static final int ABORT = 128;
+
+    /**
+     * This method is called when information about an Image
+     * interface becomes available. This method returns true 
+     * if further updates are needed, false if not.
+     * 
+     * @param img the image to be observed.
+     * @param infoflags the bitwise OR combination of information flags:
+     * ABORT, ALLBITS, ERROR, FRAMEBITS, HEIGHT, PROPERTIES, SOMEBITS, 
+     * WIDTH.
+     * @param x the X coordinate.
+     * @param y the Y coordinate.
+     * @param width the width.
+     * @param height the height.
+     * 
+     * @return true if further updates are needed, false if not.
+     */
+    public boolean imageUpdate(Image img, int infoflags, int x, int y,
+            int width, int height);
+
+}
+
diff --git a/awt/java/awt/image/ImageProducer.java b/awt/java/awt/image/ImageProducer.java
new file mode 100644
index 0000000..557ae08
--- /dev/null
+++ b/awt/java/awt/image/ImageProducer.java
@@ -0,0 +1,74 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+
+/**
+ * The ImageProducer provides an interface for objects which produce
+ * the image data. ImageProducer is used for reconstructing the 
+ * image. Each image contains an ImageProducer. 
+ */
+public interface ImageProducer {
+
+    /**
+     * Checks if the specified ImageConsumer is registered with this 
+     * ImageProvider or not.
+     * 
+     * @param ic the ImageConsumer to be checked.
+     * 
+     * @return true, if the specified ImageConsumer is registered with this 
+     * ImageProvider, false otherwise.
+     */
+    public boolean isConsumer(ImageConsumer ic);
+
+    /**
+     * Starts a reconstruction of the image data which will 
+     * be delivered to this consumer. This method addes the
+     * specified ImageConsumer before reconstructing the image.  
+     * 
+     * @param ic the specified ImageConsumer.
+     */
+    public void startProduction(ImageConsumer ic);
+
+    /**
+     * Requests the ImageProducer to resend the image data 
+     * in ImageConsumer.TOPDOWNLEFTRIGHT order.
+     * 
+     * @param ic the specified ImageConsumer.
+     */
+    public void requestTopDownLeftRightResend(ImageConsumer ic);
+
+    /**
+     * Deregisters the specified ImageConsumer.
+     * 
+     * @param ic the specified ImageConsumer.
+     */
+    public void removeConsumer(ImageConsumer ic);
+
+    /**
+     * Adds the specified ImageConsumer object to this ImageProducer.
+     * 
+     * @param ic the specified ImageConsumer.
+     */
+    public void addConsumer(ImageConsumer ic);
+
+}
+
diff --git a/awt/java/awt/image/ImagingOpException.java b/awt/java/awt/image/ImagingOpException.java
new file mode 100644
index 0000000..ebcaba4
--- /dev/null
+++ b/awt/java/awt/image/ImagingOpException.java
@@ -0,0 +1,44 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ *
+ * @date: Oct 5, 2005
+ */
+
+package java.awt.image;
+
+/**
+ * The ImagingOpException class provides error notification when 
+ * the BufferedImageOp or RasterOp filter methods can not perform
+ * the desired filter operation.
+ */
+public class ImagingOpException extends RuntimeException {
+    
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = 8026288481846276658L;
+
+    /**
+     * Instantiates a new ImagingOpException with a detail message.
+     * 
+     * @param s the detail message.
+     */
+    public ImagingOpException(String s) {
+        super(s);
+    }
+}
diff --git a/awt/java/awt/image/IndexColorModel.java b/awt/java/awt/image/IndexColorModel.java
new file mode 100644
index 0000000..a7043f4
--- /dev/null
+++ b/awt/java/awt/image/IndexColorModel.java
@@ -0,0 +1,1020 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import java.awt.Transparency;
+import java.awt.color.ColorSpace;
+import java.math.BigInteger;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Class IndexColorModel represents a color model in which the 
+ * color values of the pixels are read from a palette.
+ */
+public class IndexColorModel extends ColorModel {
+
+    /** The color map. */
+    private int colorMap[];        // Color Map  
+
+    /** The map size. */
+    private int mapSize;           // Color Map size
+
+    /** The transparent index. */
+    private int transparentIndex;  // Index of fully transparent pixel
+
+    /** The gray palette. */
+    private boolean grayPalette;   // Color Model has Color Map with Gray Pallete
+
+    /** The valid bits. */
+    private BigInteger validBits;  // Specify valid Color Map values
+
+    /** The Constant CACHESIZE. */
+    private static final int CACHESIZE = 20; // Cache size. Cache used for 
+                                             // improving performace of selection
+                                             // nearest color in Color Map
+
+    /** The cachetable. */
+    private final int cachetable[] = new int[CACHESIZE * 2]; // Cache table - used for 
+                               // storing RGB values and that appropriate indices 
+                               // in the Color Map 
+                    
+
+    /** The next insert idx. */
+    private int nextInsertIdx = 0;  // Next index for insertion into Cache table
+
+    /** The total inserted. */
+    private int totalInserted = 0;  // Number of inserted values into Cache table
+
+    /**
+     * Instantiates a new index color model.
+     * 
+     * @param bits the array of component masks
+     * @param size the size of the color map
+     * @param cmap the array that gives the color mapping
+     * @param start the start index of the color mapping data within the cmap array
+     * @param transferType the transfer type (primitive java type 
+     * to use for the components)
+     * @param validBits a list of which bits represent valid colormap 
+     * values, or null if all are valid
+     * 
+     * @throws IllegalArgumentException if the size of the color map is
+     * less than one
+     */
+    public IndexColorModel(int bits, int size, int cmap[], int start,
+            int transferType, BigInteger validBits) {
+
+        super(bits, IndexColorModel.createBits(true),
+                ColorSpace.getInstance(ColorSpace.CS_sRGB), true, false,
+                Transparency.OPAQUE, validateTransferType(transferType));
+
+        if (size < 1) {
+            // awt.264=Size of the color map is less than 1
+            throw new IllegalArgumentException(Messages.getString("awt.264")); //$NON-NLS-1$
+        }
+
+        mapSize = size;
+        colorMap = new int[mapSize];
+        transparentIndex = -1;
+
+        if (validBits != null) {
+            for (int i = 0; i < mapSize; i++) {
+                if (!validBits.testBit(i)) {
+                    this.validBits = validBits;
+                }
+                break;
+            }
+        }
+
+        transparency = Transparency.OPAQUE;
+        int alphaMask = 0xff000000;
+        int alpha = 0;
+
+        for (int i = 0; i < mapSize; i++, start++) {
+            colorMap[i] = cmap[start];
+            alpha = cmap[start] & alphaMask;
+
+            if (alpha == alphaMask) {
+                continue;
+            }
+            if (alpha == 0) {
+                if (transparentIndex < 0) {
+                    transparentIndex = i;
+                }
+                if (transparency == Transparency.OPAQUE) {
+                    transparency = Transparency.BITMASK;
+                }
+            } else if (alpha != alphaMask &&
+                    transparency != Transparency.TRANSLUCENT) {
+                transparency = Transparency.TRANSLUCENT;
+            }
+
+        }
+        checkPalette();
+
+    }
+
+    /**
+     * Instantiates a new index color model.
+     * 
+     * @param bits the array of component masks
+     * @param size the size of the color map
+     * @param cmap the array that gives the color mapping
+     * @param start the start index of the color mapping data within the cmap array
+     * @param hasalpha whether this color model uses alpha
+     * @param trans the transparency supported, @see java.awt.Transparency
+     * @param transferType the transfer type (primitive java type 
+     * to use for the components)
+     * 
+     * @throws IllegalArgumentException if the size of the color map is
+     * less than one
+     */
+    public IndexColorModel(int bits, int size, int cmap[], int start,
+            boolean hasalpha, int trans, int transferType) {
+
+        super(bits, IndexColorModel.createBits(hasalpha || (trans >= 0)),
+                ColorSpace.getInstance(ColorSpace.CS_sRGB),
+                (hasalpha || (trans >= 0)), false, Transparency.OPAQUE,
+                validateTransferType(transferType));
+
+        if (size < 1) {
+            // awt.264=Size of the color map is less than 1
+            throw new IllegalArgumentException(Messages.getString("awt.264")); //$NON-NLS-1$
+        }
+
+        mapSize = size;
+        colorMap = new int[mapSize];
+        if (trans >= 0 && trans < mapSize) {
+            transparentIndex = trans;
+            transparency = Transparency.BITMASK;
+        } else {
+            transparentIndex = -1;
+            transparency = Transparency.OPAQUE;
+        }
+
+        int alphaMask = 0xff000000;
+        int alpha = 0;
+
+        for (int i = 0; i < mapSize; i++, start++) {
+            if (transparentIndex == i) {
+                colorMap[i] = cmap[start] & 0x00ffffff;
+                continue;
+            }
+            if (hasalpha) {
+                alpha = cmap[start] & alphaMask;
+                colorMap[i] = cmap[start];
+
+                if (alpha == alphaMask) {
+                    continue;
+                }
+                if (alpha == 0) {
+                    if (trans < 0) {
+                        trans = i;
+                    }
+                    if (transparency == Transparency.OPAQUE) {
+                        transparency = Transparency.BITMASK;
+                    }
+                } else if (alpha != 0
+                        && transparency != Transparency.TRANSLUCENT) {
+                    transparency = Transparency.TRANSLUCENT;
+                }
+            } else {
+                colorMap[i] = alphaMask | cmap[start];
+            }
+        }
+        checkPalette();
+
+    }
+
+    /**
+     * Instantiates a new index color model by building the color map 
+     * from arrays of red, green, blue, and alpha values.
+     * 
+     * @param bits the array of component masks
+     * @param size the size of the color map
+     * @param r the array giving the red components of the entries in the color map
+     * @param g the array giving the green components of the entries in the color map
+     * @param b the array giving the blue components of the entries in the color map
+     * @param a the array giving the alpha components of the entries in the color map
+     * 
+     * @throws IllegalArgumentException if the size of the color map is
+     * less than one
+     * @throws ArrayIndexOutOfBoundsException if the size of one of the 
+     * component arrays is less than the size of the color map
+     */
+    public IndexColorModel(int bits, int size, byte r[], byte g[], byte b[],
+            byte a[]) {
+
+        super(bits, IndexColorModel.createBits(true),
+                ColorSpace.getInstance(ColorSpace.CS_sRGB), true, false,
+                Transparency.OPAQUE,
+                validateTransferType(ColorModel.getTransferType(bits)));
+
+        createColorMap(size, r, g, b, a, -1);
+        checkPalette();
+    }
+
+    /**
+     * Instantiates a new index color model by building the color map 
+     * from arrays of red, green, and blue values.
+     * 
+     * @param bits the array of component masks
+     * @param size the size of the color map
+     * @param r the array giving the red components of the entries in the color map
+     * @param g the array giving the green components of the entries in the color map
+     * @param b the array giving the blue components of the entries in the color map
+     * @param trans the transparency supported, @see java.awt.Transparency
+     * 
+     * @throws IllegalArgumentException if the size of the color map is
+     * less than one
+     * @throws ArrayIndexOutOfBoundsException if the size of one of the 
+     * component arrays is less than the size of the color map
+     */
+    public IndexColorModel(int bits, int size, byte r[], byte g[], byte b[],
+            int trans) {
+
+        super(bits, IndexColorModel.createBits((trans >= 0)),
+                ColorSpace.getInstance(ColorSpace.CS_sRGB), (trans >= 0), false,
+                Transparency.OPAQUE,
+                validateTransferType(ColorModel.getTransferType(bits)));
+
+        createColorMap(size, r, g, b, null, trans);
+        checkPalette();
+    }
+
+    /**
+     * Instantiates a new index color model by building the color map 
+     * from arrays of red, green, and blue values.
+     * 
+     * @param bits the array of component masks
+     * @param size the size of the color map
+     * @param r the array giving the red components of the entries in the color map
+     * @param g the array giving the green components of the entries in the color map
+     * @param b the array giving the blue components of the entries in the color map
+     * 
+     * @throws IllegalArgumentException if the size of the color map is
+     * less than one
+     * @throws ArrayIndexOutOfBoundsException if the size of one of the 
+     * component arrays is less than the size of the color map
+     */
+    public IndexColorModel(int bits, int size, byte r[], byte g[], byte b[]) {
+        super(bits, IndexColorModel.createBits(false),
+                ColorSpace.getInstance(ColorSpace.CS_sRGB), false, false,
+                Transparency.OPAQUE,
+                validateTransferType(ColorModel.getTransferType(bits)));
+
+        createColorMap(size, r, g, b, null, -1);
+        checkPalette();
+    }
+
+    /**
+     * Instantiates a new index color model.
+     * 
+     * @param bits the array of component masks
+     * @param size the size of the color map
+     * @param cmap the array that gives the color mapping
+     * @param start the start index of the color mapping data within the cmap array
+     * @param hasalpha whether this color model uses alpha
+     * @param trans the transparency supported, @see java.awt.Transparency
+     * 
+     * @throws IllegalArgumentException if the size of the color map is
+     * less than one
+     */
+    public IndexColorModel(int bits, int size, byte cmap[], int start,
+            boolean hasalpha, int trans) {
+
+        super(bits, IndexColorModel.createBits(hasalpha || (trans >= 0)),
+                ColorSpace.getInstance(ColorSpace.CS_sRGB),
+                (hasalpha || (trans >= 0)), false, Transparency.OPAQUE,
+                validateTransferType(ColorModel.getTransferType(bits)));
+
+        if (size < 1) {
+            // awt.264=Size of the color map is less than 1
+            throw new IllegalArgumentException(Messages.getString("awt.264")); //$NON-NLS-1$
+        }
+
+        mapSize = size;
+        colorMap = new int[mapSize];
+        transparentIndex = -1;
+
+        transparency = Transparency.OPAQUE;
+        int alpha = 0xff000000;
+
+        for (int i = 0; i < mapSize; i++) {
+            colorMap[i] = (cmap[start++] & 0xff) << 16 |
+                   (cmap[start++] & 0xff) << 8 | (cmap[start++] & 0xff);
+            if (trans == i) {
+                if (transparency == Transparency.OPAQUE) {
+                    transparency = Transparency.BITMASK;
+                }
+                if(hasalpha) {
+                    start++;
+                }
+                continue;
+            }
+            if (hasalpha) {
+                alpha = cmap[start++] & 0xff;
+                if (alpha == 0) {
+                    if (transparency == Transparency.OPAQUE) {
+                        transparency = Transparency.BITMASK;
+                        if (trans < 0) {
+                            trans = i;
+                        }
+                    }
+                } else {
+                    if (alpha != 0xff &&
+                           transparency != Transparency.TRANSLUCENT) {
+                        transparency = Transparency.TRANSLUCENT;
+                    }
+                }
+                alpha <<= 24;
+            }
+            colorMap[i] |= alpha;
+        }
+
+        if (trans >= 0 && trans < mapSize) {
+            transparentIndex = trans;
+        }
+        checkPalette();
+
+    }
+
+    /**
+     * Instantiates a new index color model.
+     * 
+     * @param bits the array of component masks
+     * @param size the size of the color map
+     * @param cmap the array that gives the color mapping
+     * @param start the start index of the color mapping data within the cmap array
+     * @param hasalpha whether this color model uses alpha
+     * 
+     * @throws IllegalArgumentException if the size of the color map is
+     * less than one
+     */
+    public IndexColorModel(int bits, int size, byte cmap[], int start,
+            boolean hasalpha) {
+
+        this(bits, size, cmap, start, hasalpha, -1);
+    }
+
+    @Override
+    public Object getDataElements(int[] components, int offset, Object pixel) {
+        int rgb = (components[offset] << 16) | (components[offset + 1]) << 8 |
+               components[offset + 2];
+        if (hasAlpha) {
+            rgb |= components[offset + 3] << 24;
+        } else {
+            rgb |= 0xff000000;
+        }
+        return getDataElements(rgb, pixel);
+    }
+
+    @Override
+    public synchronized Object getDataElements(int rgb, Object pixel) {
+        int red = (rgb >> 16) & 0xff;
+        int green = (rgb >> 8) & 0xff;
+        int blue = rgb & 0xff;
+        int alpha = rgb >>> 24;
+        int pixIdx = 0;
+
+        for (int i = 0; i < totalInserted; i++) {
+            int idx = i * 2;
+            if (rgb == cachetable[idx]) {
+                return createDataObject(cachetable[idx + 1], pixel);
+            }
+        }
+
+        if (!hasAlpha && grayPalette) {
+            int grey = (red * 77 + green * 150 + blue * 29 + 128) >>> 8;
+            int minError = 255;
+            int error = 0;
+
+            for (int i = 0; i < mapSize; i++) {
+                error = Math.abs((colorMap[i] & 0xff) - grey);
+                if (error < minError) {
+                    pixIdx = i;
+                    if (error == 0) {
+                        break;
+                    }
+                    minError = error;
+                }
+            }
+        } else if (alpha == 0 && transparentIndex > -1) {
+            pixIdx = transparentIndex;
+        } else  {
+            int minAlphaError = 255;
+            int minError = 195075; // 255^2 + 255^2 + 255^2
+            int alphaError;
+            int error = 0;
+
+            for (int i = 0; i < mapSize; i++) {
+                int pix = colorMap[i];
+                if (rgb == pix) {
+                    pixIdx = i;
+                    break;
+                }
+                alphaError = Math.abs(alpha - (pix >>> 24));
+                if (alphaError <= minAlphaError) {
+                    minAlphaError = alphaError;
+
+                    int buf = ((pix >> 16) & 0xff) - red;
+                    error = buf * buf;
+
+                    if (error < minError) {
+                        buf = ((pix >> 8) & 0xff) - green;
+                        error += buf * buf;
+
+                        if (error < minError) {
+                            buf = (pix & 0xff) - blue;
+                            error += buf * buf;
+
+                            if (error < minError) {
+                                pixIdx = i;
+                                minError = error;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        cachetable[nextInsertIdx] = rgb;
+        cachetable[nextInsertIdx + 1] = pixIdx;
+
+        nextInsertIdx = (nextInsertIdx + 2) % (CACHESIZE * 2);
+        if (totalInserted < CACHESIZE) {
+            totalInserted++;
+        }
+
+        return createDataObject(pixIdx, pixel);
+    }
+
+    /**
+     * Converts an image from indexed to RGB format.
+     * 
+     * @param raster the raster containing the source image
+     * @param forceARGB whether to use the default RGB color model
+     * 
+     * @return the buffered image
+     * 
+     * @throws IllegalArgumentException if the raster is not compatible with 
+     * this color model
+     */
+    public BufferedImage convertToIntDiscrete(Raster raster,
+            boolean forceARGB) {
+
+        if (!isCompatibleRaster(raster)) {
+            // awt.265=The raster argument is not compatible with this IndexColorModel
+            throw new IllegalArgumentException(Messages.getString("awt.265")); //$NON-NLS-1$
+        }
+
+        ColorModel model;
+        if (forceARGB || transparency == Transparency.TRANSLUCENT) {
+            model = ColorModel.getRGBdefault();
+        } else if (transparency == Transparency.BITMASK) {
+            model = new DirectColorModel(25, 0x00ff0000, 0x0000ff00,
+                    0x000000ff, 0x01000000);
+        } else {
+            model = new DirectColorModel(24, 0x00ff0000, 0x0000ff00, 0x000000ff);
+        }
+
+        int w = raster.getWidth();
+        int h = raster.getHeight();
+
+        WritableRaster distRaster = model.createCompatibleWritableRaster(w, h);
+
+        int minX = raster.getMinX();
+        int minY = raster.getMinY();
+
+        Object obj = null;
+        int pixels[] = null;
+
+        for (int i = 0; i < h; i++, minY++) {
+            obj = raster.getDataElements(minX, minY, w, 1, obj);
+            if (obj instanceof byte[]) {
+                byte ba[] = (byte[]) obj;
+                if (pixels == null) {
+                    pixels = new int[ba.length];
+                }
+                for (int j = 0; j < ba.length; j++) {
+                    pixels[j] = colorMap[ba[j] & 0xff];
+                }
+            } else if (obj instanceof short[]) {
+                short sa[] = (short[]) obj;
+                if (pixels == null) {
+                    pixels = new int[sa.length];
+                }
+                for (int j = 0; j < sa.length; j++) {
+                    pixels[j] = colorMap[sa[j] & 0xffff];
+                }
+            }
+            if (obj instanceof int[]) {
+                int ia[] = (int[]) obj;
+                if (pixels == null) {
+                    pixels = new int[ia.length];
+                }
+                for (int j = 0; j < ia.length; j++) {
+                    pixels[j] = colorMap[ia[j]];
+                }
+            }
+
+            distRaster.setDataElements(0, i, w, 1, pixels);
+        }
+
+        return new BufferedImage(model, distRaster, false, null);
+    }
+
+    /**
+     * Gets the valid pixels.
+     * 
+     * @return the valid pixels
+     */
+    public BigInteger getValidPixels() {
+        return validBits;
+    }
+
+    @Override
+    public String toString() {
+        // The output format based on 1.5 release behaviour. 
+        // It could be reveled such way:
+        // BufferedImage bi = new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_INDEXED);
+        // ColorModel cm = bi.getColorModel();
+        // System.out.println(cm.toString());
+        String str = "IndexColorModel: #pixel_bits = " + pixel_bits + //$NON-NLS-1$
+               " numComponents = " + numComponents + " color space = " + cs + //$NON-NLS-1$ //$NON-NLS-2$
+               " transparency = "; //$NON-NLS-1$
+
+        if (transparency == Transparency.OPAQUE) {
+            str = str + "Transparency.OPAQUE"; //$NON-NLS-1$
+        } else if (transparency == Transparency.BITMASK) {
+            str = str + "Transparency.BITMASK"; //$NON-NLS-1$
+        } else {
+            str = str + "Transparency.TRANSLUCENT"; //$NON-NLS-1$
+        }
+
+        str = str + " transIndex = " + transparentIndex + " has alpha = " + //$NON-NLS-1$ //$NON-NLS-2$
+               hasAlpha + " isAlphaPre = " + isAlphaPremultiplied; //$NON-NLS-1$
+
+        return str;
+    }
+
+    @Override
+    public int[] getComponents(Object pixel, int components[], int offset) {
+        int pixIdx = -1;
+        if (pixel instanceof byte[]) {
+            byte ba[] = (byte[]) pixel;
+            pixIdx = ba[0] & 0xff;
+        } else if (pixel instanceof short[]) {
+            short sa[] = (short[]) pixel;
+            pixIdx = sa[0] & 0xffff;
+        } else if (pixel instanceof int[]) {
+            int ia[] = (int[]) pixel;
+            pixIdx = ia[0];
+        } else {
+            // awt.219=This transferType is not supported by this color model
+            throw new UnsupportedOperationException(Messages.getString("awt.219")); //$NON-NLS-1$
+        }
+
+        return getComponents(pixIdx, components, offset);
+    }
+
+    @Override
+    public WritableRaster createCompatibleWritableRaster(int w, int h) {
+        WritableRaster raster;
+        if (pixel_bits == 1 || pixel_bits == 2 || pixel_bits == 4) {
+            raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE, w, h, 1,
+                    pixel_bits, null);
+        } else if (pixel_bits <= 8) {
+            raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, w, h,
+                    1, null);
+        } else if (pixel_bits <= 16) {
+            raster = Raster.createInterleavedRaster(DataBuffer.TYPE_USHORT, w,
+                    h, 1, null);
+        } else {
+            // awt.266=The number of bits in a pixel is greater than 16
+            throw new UnsupportedOperationException(Messages.getString("awt.266")); //$NON-NLS-1$
+        }
+
+        return raster;
+    }
+
+    @Override
+    public boolean isCompatibleSampleModel(SampleModel sm) {
+        if (sm == null) {
+            return false;
+        }
+
+        if (!(sm instanceof MultiPixelPackedSampleModel)
+                && !(sm instanceof ComponentSampleModel)) {
+            return false;
+        }
+
+        if (sm.getTransferType() != transferType) {
+            return false;
+        }
+        if (sm.getNumBands() != 1) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public SampleModel createCompatibleSampleModel(int w, int h) {
+        if (pixel_bits == 1 || pixel_bits == 2 || pixel_bits == 4) {
+            return new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, w, h,
+                    pixel_bits);
+        }
+        int bandOffsets[] = new int[1];
+        bandOffsets[0] = 0;
+        return new ComponentSampleModel(transferType, w, h, 1, w,
+                bandOffsets);
+
+    }
+
+    @Override
+    public boolean isCompatibleRaster(Raster raster) {
+        int sampleSize = raster.getSampleModel().getSampleSize(0);
+        return (raster.getTransferType() == transferType &&
+               raster.getNumBands() == 1 && (1 << sampleSize) >= mapSize);
+    }
+
+    @Override
+    public int getDataElement(int components[], int offset) {
+        int rgb = (components[offset] << 16) | (components[offset + 1]) << 8
+                | components[offset + 2];
+        
+        if (hasAlpha) {
+            rgb |= components[offset + 3] << 24;
+        } else {
+            rgb |= 0xff000000;
+        }
+ 
+        int pixel;
+
+        switch (transferType) {
+        case DataBuffer.TYPE_BYTE:
+            byte ba[] = (byte[]) getDataElements(rgb, null);
+            pixel = ba[0] & 0xff;
+            break;
+        case DataBuffer.TYPE_USHORT:
+            short sa[] = (short[]) getDataElements(rgb, null);
+            pixel = sa[0] & 0xffff;
+            break;
+        default:
+            // awt.267=The transferType is invalid
+            throw new UnsupportedOperationException(Messages.getString("awt.267")); //$NON-NLS-1$
+        }
+
+        return pixel;
+    }
+
+    /**
+     * Gets the color map.
+     * 
+     * @param rgb the destination array where the color map is written
+     */
+    public final void getRGBs(int rgb[]) {
+        System.arraycopy(colorMap, 0, rgb, 0, mapSize);
+    }
+
+    /**
+     * Gets the red component of the color map.
+     * 
+     * @param r the destination array
+     */
+    public final void getReds(byte r[]) {
+        for (int i = 0; i < mapSize; i++) {
+            r[i] = (byte) (colorMap[i] >> 16);
+        }
+    }
+
+    /**
+     * Gets the green component of the color map.
+     * 
+     * @param g the destination array
+     */
+    public final void getGreens(byte g[]) {
+        for (int i = 0; i < mapSize; i++) {
+            g[i] = (byte) (colorMap[i] >> 8);
+        }
+    }
+
+    /**
+     * Gets the blue component of the color map.
+     * 
+     * @param b the destination array
+     */
+    public final void getBlues(byte b[]) {
+        for (int i = 0; i < mapSize; i++) {
+            b[i] = (byte) colorMap[i];
+        }
+    }
+
+    /**
+     * Gets the alpha component of the color map.
+     * 
+     * @param a the destination array
+     */
+    public final void getAlphas(byte a[]) {
+        for (int i = 0; i < mapSize; i++) {
+            a[i] = (byte) (colorMap[i] >> 24);
+        }
+    }
+
+    @Override
+    public int[] getComponents(int pixel, int components[], int offset) {
+        if (components == null) {
+            components = new int[offset + numComponents];
+        }
+
+        components[offset + 0] = getRed(pixel);
+        components[offset + 1] = getGreen(pixel);
+        components[offset + 2] = getBlue(pixel);
+        if (hasAlpha && (components.length - offset) > 3) {
+            components[offset + 3] = getAlpha(pixel);
+        }
+
+        return components;
+    }
+
+    /**
+     * Checks if the specified pixel is valid for this color model.
+     * 
+     * @param pixel the pixel
+     * 
+     * @return true, if the pixel is valid
+     */
+    public boolean isValid(int pixel) {
+        if (validBits == null) {
+            return (pixel >= 0 && pixel < mapSize);
+        }
+        return (pixel < mapSize && validBits.testBit(pixel));
+    }
+
+    @Override
+    public final int getRed(int pixel) {
+        return (colorMap[pixel] >> 16) & 0xff;
+    }
+
+    @Override
+    public final int getRGB(int pixel) {
+        return colorMap[pixel];
+    }
+
+    @Override
+    public final int getGreen(int pixel) {
+        return (colorMap[pixel] >> 8) & 0xff;
+    }
+
+    @Override
+    public final int getBlue(int pixel) {
+        return colorMap[pixel] & 0xff;
+    }
+
+    @Override
+    public final int getAlpha(int pixel) {
+        return (colorMap[pixel] >> 24) & 0xff;
+    }
+
+    @Override
+    public int[] getComponentSize() {
+        return bits.clone();
+    }
+
+    /**
+     * Checks if this color model validates pixels.
+     * 
+     * @return true, if all pixels are valid, otherwise false
+     */
+    public boolean isValid() {
+        return (validBits == null);
+    }
+
+    @Override
+    public void finalize() {
+        // TODO: implement
+        return;
+    }
+
+    /**
+     * Gets the index that represents the transparent pixel.
+     * 
+     * @return the index that represents the transparent pixel
+     */
+    public final int getTransparentPixel() {
+        return transparentIndex;
+    }
+
+    @Override
+    public int getTransparency() {
+        return transparency;
+    }
+
+    /**
+     * Gets the size of the color map.
+     * 
+     * @return the map size
+     */
+    public final int getMapSize() {
+        return mapSize;
+    }
+
+    /**
+     * Creates the color map.
+     * 
+     * @param size the size
+     * @param r the r
+     * @param g the g
+     * @param b the b
+     * @param a the a
+     * @param trans the trans
+     */
+    private void createColorMap(int size, byte r[], byte g[], byte b[],
+            byte a[], int trans) {
+        if (size < 1) {
+            // awt.264=Size of the color map is less than 1
+            throw new IllegalArgumentException(Messages.getString("awt.264")); //$NON-NLS-1$
+        }
+
+        mapSize = size;
+        colorMap = new int[mapSize];
+        if (trans >= 0 && trans < mapSize) {
+            transparency = Transparency.BITMASK;
+            transparentIndex = trans;
+        } else {
+            transparency = Transparency.OPAQUE;
+            transparentIndex = -1;
+        }
+        int alpha = 0;
+
+        for (int i = 0; i < mapSize; i++) {
+            colorMap[i] = ((r[i] & 0xff) << 16) | ((g[i] & 0xff) << 8) |
+                   (b[i] & 0xff);
+
+            if (trans == i) {
+                continue;
+            }
+
+            if (a == null) {
+                colorMap[i] |= 0xff000000;
+            } else {
+                alpha = a[i] & 0xff;
+                if (alpha == 0xff) {
+                    colorMap[i] |= 0xff000000;
+                } else if (alpha == 0) {
+                    if (transparency == Transparency.OPAQUE) {
+                        transparency = Transparency.BITMASK;
+                    }
+                    if (transparentIndex < 0) {
+                        transparentIndex = i;
+                    }
+                } else {
+                    colorMap[i] |= (a[i] & 0xff) << 24;
+                    if (transparency != Transparency.TRANSLUCENT) {
+                        transparency = Transparency.TRANSLUCENT;
+                    }
+                }
+            }
+
+        }
+
+    }
+
+    /**
+     * This method checking, if Color Map has Gray Palette.
+     */
+    private void checkPalette() {
+        grayPalette = false;
+        if (transparency > Transparency.OPAQUE) {
+            return;
+        }
+        int rgb = 0;
+
+        for (int i = 0; i < mapSize; i++) {
+            rgb = colorMap[i];
+            if (((rgb >> 16) & 0xff) != ((rgb >> 8) & 0xff) ||
+                   ((rgb >> 8) & 0xff) != (rgb & 0xff)) {
+                return;
+            }
+        }
+        grayPalette = true;
+    }
+
+    /**
+     * Construction an array pixel representation.
+     * 
+     * @param colorMapIdx - index into Color Map
+     * @param pixel - pixel
+     * 
+     * @return - an array pixel representation
+     */
+    private Object createDataObject(int colorMapIdx, Object pixel) {
+        if (pixel == null) {
+            switch (transferType) {
+            case DataBuffer.TYPE_BYTE:
+                byte[] ba = new byte[1];
+                ba[0] = (byte) colorMapIdx;
+                pixel = ba;
+                break;
+            case DataBuffer.TYPE_USHORT:
+                short[] sa = new short[1];
+                sa[0] = (short) colorMapIdx;
+                pixel = sa;
+                break;
+            default:
+                // awt.267=The transferType is invalid
+                throw new UnsupportedOperationException(Messages.getString("awt.267")); //$NON-NLS-1$
+            }
+        } else if (pixel instanceof byte[]
+                && transferType == DataBuffer.TYPE_BYTE) {
+            byte ba[] = (byte[]) pixel;
+            ba[0] = (byte) colorMapIdx;
+            pixel = ba;
+        } else if (pixel instanceof short[]&&
+                transferType == DataBuffer.TYPE_USHORT) {
+            short[] sa = (short[]) pixel;
+            sa[0] = (short) colorMapIdx;
+            pixel = sa;
+        } else if (pixel instanceof int[]) {
+            int ia[] = (int[]) pixel;
+            ia[0] = colorMapIdx;
+            pixel = ia;
+        } else {
+            // awt.268=The pixel is not a primitive array of type transferType
+            throw new ClassCastException(Messages.getString("awt.268")); //$NON-NLS-1$
+        }
+        return pixel;
+    }
+
+    /**
+     * Creates the bits.
+     * 
+     * @param hasAlpha the has alpha
+     * 
+     * @return the int[]
+     */
+    private static int[] createBits(boolean hasAlpha) {
+
+        int numChannels;
+        if (hasAlpha) {
+            numChannels = 4;
+        } else {
+            numChannels = 3;
+        }
+
+        int bits[] = new int[numChannels];
+        for (int i = 0; i < numChannels; i++) {
+            bits[i] = 8;
+        }
+
+        return bits;
+
+    }
+
+    /**
+     * Validate transfer type.
+     * 
+     * @param transferType the transfer type
+     * 
+     * @return the int
+     */
+    private static int validateTransferType(int transferType) {
+        if (transferType != DataBuffer.TYPE_BYTE &&
+               transferType != DataBuffer.TYPE_USHORT) {
+            // awt.269=The transferType is not one of DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT
+            throw new IllegalArgumentException(Messages.getString("awt.269")); //$NON-NLS-1$
+        }
+        return transferType;
+    }
+
+    /**
+     * Checks if is gray pallete.
+     * 
+     * @return true, if is gray pallete
+     */
+    boolean isGrayPallete(){
+        return grayPalette;
+    }
+
+}
+
+
diff --git a/awt/java/awt/image/Kernel.java b/awt/java/awt/image/Kernel.java
new file mode 100644
index 0000000..c6f00e2
--- /dev/null
+++ b/awt/java/awt/image/Kernel.java
@@ -0,0 +1,138 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ *
+ * @date: Sep 28, 2005
+ */
+
+package java.awt.image;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Kernel class provides a matrix. This matrix is stored as a float array
+ * which describes how a specified pixel affects the value calculated for 
+ * the pixel's position in the output image of a filtering operation. 
+ * The X, Y origins indicate the kernel matrix element which corresponds to 
+ * the pixel position for which an output value is being calculated.
+ */
+public class Kernel implements Cloneable {
+    
+    /** The x origin. */
+    private final int xOrigin;
+    
+    /** The y origin. */
+    private final int yOrigin;
+    
+    /** The width. */
+    private int width;
+    
+    /** The height. */
+    private int height;
+    
+    /** The data. */
+    float data[];
+
+    /**
+     * Instantiates a new Kernel with the specified float array.
+     * The width*height elements of the data array are copied. 
+     * 
+     * @param width the width of the Kernel.
+     * @param height the height of the Kernel.
+     * @param data the data of Kernel.
+     */
+    public Kernel(int width, int height, float[] data) {
+        int dataLength = width*height;
+        if (data.length < dataLength) {
+            // awt.22B=Length of data should not be less than width*height
+            throw new IllegalArgumentException(Messages.getString("awt.22B")); //$NON-NLS-1$
+        }
+
+        this.width = width;
+        this.height = height;
+
+        this.data = new float[dataLength];
+        System.arraycopy(data, 0, this.data, 0, dataLength);
+
+        xOrigin = (width-1)/2;
+        yOrigin = (height-1)/2;
+    }
+
+    /**
+     * Gets the width of this Kernel.
+     * 
+     * @return the width of this Kernel.
+     */
+    public final int getWidth() {
+        return width;
+    }
+
+    /**
+     * Gets the height of this Kernel.
+     * 
+     * @return the height of this Kernel.
+     */
+    public final int getHeight() {
+        return height;
+    }
+
+    /**
+     * Gets the float data array of this Kernel.
+     * 
+     * @param data the float array where the resulted data will be stored.
+     * 
+     * @return the float data array of this Kernel.
+     */
+    public final float[] getKernelData(float[] data) {
+        if (data == null) {
+            data = new float[this.data.length];
+        }
+        System.arraycopy(this.data, 0, data, 0, this.data.length);
+
+        return data;
+    }
+
+    /**
+     * Gets the X origin of this Kernel.
+     * 
+     * @return the X origin of this Kernel.
+     */
+    public final int getXOrigin() {
+        return xOrigin;
+    }
+
+    /**
+     * Gets the Y origin of this Kernel.
+     * 
+     * @return the Y origin of this Kernel.
+     */
+    public final int getYOrigin() {
+        return yOrigin;
+    }
+
+    /**
+     * Returns a copy of this Kernel object.
+     * 
+     * @return the copy of this Kernel object.
+     */
+    @Override
+    public Object clone() {
+        return new Kernel(width, height, data);
+    }
+}
diff --git a/awt/java/awt/image/LookupOp.java b/awt/java/awt/image/LookupOp.java
new file mode 100644
index 0000000..f9bd2c7
--- /dev/null
+++ b/awt/java/awt/image/LookupOp.java
@@ -0,0 +1,647 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ *
+ * @date: Oct 14, 2005
+ */
+
+package java.awt.image;
+
+import java.awt.*;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.Point2D;
+import java.util.Arrays;
+
+import org.apache.harmony.awt.gl.AwtImageBackdoorAccessor;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The LookupOp class perfoms a lookup operation which transforms a 
+ * source image by filtering each band using a table of data. 
+ * The table may contain a single array or it may contain a 
+ * different data array for each band of the image.
+ */
+public class LookupOp implements BufferedImageOp, RasterOp {
+    
+    /** The lut. */
+    private final LookupTable lut;
+    
+    /** The hints. */
+    private RenderingHints hints;
+    
+    // TODO remove when this field is used
+    /** The can use ipp. */
+    @SuppressWarnings("unused")
+    private final boolean canUseIpp;
+
+    // We don't create levels/values when it is possible to reuse old
+    /** The cached levels. */
+    private int cachedLevels[];
+    
+    /** The cached values. */
+    private int cachedValues[];
+    // Number of channels for which cache is valid.
+    // If negative number of channels is same as positive but skipAlpha was specified
+    /** The valid for channels. */
+    private int validForChannels;
+
+    /** The level initializer. */
+    static int levelInitializer[] = new int[0x10000];
+
+    static {
+        // TODO
+        // System.loadLibrary("imageops");
+
+        for (int i=1; i<=0x10000; i++) {
+            levelInitializer[i-1] = i;
+        }
+    }
+
+    /**
+     * Instantiates a new LookupOp object from the specified 
+     * LookupTable object and a RenderingHints object.
+     * 
+     * @param lookup the specified LookupTable object. 
+     * @param hints the RenderingHints object or null.
+     */
+    public LookupOp(LookupTable lookup, RenderingHints hints) {
+        if (lookup == null){
+            throw new NullPointerException(Messages.getString("awt.01", "lookup")); //$NON-NLS-1$ //$NON-NLS-2$
+        }
+        lut = lookup;
+        this.hints = hints;
+        canUseIpp = lut instanceof ByteLookupTable || lut instanceof ShortLookupTable;
+    }
+
+    /**
+     * Gets the LookupTable of the specified Object.
+     * 
+     * @return the LookupTable of the specified Object.
+     */
+    public final LookupTable getTable() {
+        return lut;
+    }
+
+    public final RenderingHints getRenderingHints() {
+        return hints;
+    }
+
+    public final Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
+        if (dstPt == null) {
+            dstPt = new Point2D.Float();
+        }
+
+        dstPt.setLocation(srcPt);
+        return dstPt;
+    }
+
+    public final Rectangle2D getBounds2D(Raster src) {
+        return src.getBounds();
+    }
+
+    public final Rectangle2D getBounds2D(BufferedImage src) {
+        return getBounds2D(src.getRaster());
+    }
+
+    public WritableRaster createCompatibleDestRaster(Raster src) {
+        return src.createCompatibleWritableRaster();
+    }
+
+    public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM) {
+        if (dstCM == null) {
+            dstCM = src.getColorModel();
+
+            // Sync transfer type with LUT for component color model
+            if (dstCM instanceof ComponentColorModel) {
+                int transferType = dstCM.getTransferType();
+                if (lut instanceof ByteLookupTable) {
+                    transferType = DataBuffer.TYPE_BYTE;
+                } else if (lut instanceof ShortLookupTable) {
+                    transferType = DataBuffer.TYPE_SHORT;
+                }
+
+                dstCM = new ComponentColorModel(
+                        dstCM.cs,
+                        dstCM.hasAlpha(),
+                        dstCM.isAlphaPremultiplied,
+                        dstCM.transparency,
+                        transferType
+                );
+            }
+        }
+
+        WritableRaster r =
+                dstCM.isCompatibleSampleModel(src.getSampleModel()) ?
+                src.getRaster().createCompatibleWritableRaster(src.getWidth(), src.getHeight()) :
+                dstCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight());
+
+        return new BufferedImage(
+                dstCM,
+                r,
+                dstCM.isAlphaPremultiplied(),
+                null
+        );
+    }
+
+    public final WritableRaster filter(Raster src, WritableRaster dst) {
+        if (dst == null) {
+            dst = createCompatibleDestRaster(src);
+        } else {
+            if (src.getNumBands() != dst.getNumBands()) {
+                throw new IllegalArgumentException(Messages.getString("awt.237")); //$NON-NLS-1$            }
+            }
+            if (src.getWidth() != dst.getWidth()){
+                throw new IllegalArgumentException(Messages.getString("awt.28F")); //$NON-NLS-1$            }
+            }
+            if (src.getHeight() != dst.getHeight()){
+                throw new IllegalArgumentException(Messages.getString("awt.290")); //$NON-NLS-1$            }
+            }
+        }
+
+        if (lut.getNumComponents() != 1 && lut.getNumComponents() != src.getNumBands()) {
+            // awt.238=The number of arrays in the LookupTable does not meet the restrictions
+            throw new IllegalArgumentException(Messages.getString("awt.238")); //$NON-NLS-1$
+        }
+
+        // TODO
+        // if (!canUseIpp || ippFilter(src, dst, BufferedImage.TYPE_CUSTOM, false) != 0)
+            if (slowFilter(src, dst, false) != 0) {
+                // awt.21F=Unable to transform source
+                throw new ImagingOpException (Messages.getString("awt.21F")); //$NON-NLS-1$
+            }
+
+        return dst;
+    }
+
+    public final BufferedImage filter(BufferedImage src, BufferedImage dst) {
+        ColorModel srcCM = src.getColorModel();
+
+        if (srcCM instanceof IndexColorModel) {
+            // awt.220=Source should not have IndexColorModel
+            throw new IllegalArgumentException(Messages.getString("awt.220")); //$NON-NLS-1$
+        }
+
+        // Check if the number of scaling factors matches the number of bands
+        int nComponents = srcCM.getNumComponents();
+        int nLUTComponents = lut.getNumComponents();
+        boolean skipAlpha;
+        if (srcCM.hasAlpha()) {
+            if (nLUTComponents == 1 || nLUTComponents == nComponents-1) {
+                skipAlpha = true;
+            } else if (nLUTComponents == nComponents) {
+                skipAlpha = false;
+            } else {
+                // awt.229=Number of components in the LUT does not match the number of bands
+                throw new IllegalArgumentException(Messages.getString("awt.229")); //$NON-NLS-1$
+            }
+        } else if (nLUTComponents == 1 || nLUTComponents == nComponents) {
+            skipAlpha = false;
+        } else {
+            // awt.229=Number of components in the LUT does not match the number of bands
+            throw new IllegalArgumentException(Messages.getString("awt.229")); //$NON-NLS-1$
+        }
+
+        BufferedImage finalDst = null;
+        if (dst == null) {
+            finalDst = dst;
+            dst = createCompatibleDestImage(src, null);
+        } else {
+            if (src.getWidth() != dst.getWidth()){
+                throw new IllegalArgumentException(Messages.getString("awt.291")); //$NON-NLS-1$
+            }
+
+            if (src.getHeight() != dst.getHeight()){
+                throw new IllegalArgumentException(Messages.getString("awt.292")); //$NON-NLS-1$
+            }
+
+            if (!srcCM.equals(dst.getColorModel())) {
+                // Treat BufferedImage.TYPE_INT_RGB and
+                // BufferedImage.TYPE_INT_ARGB as same
+                if (!((src.getType() == BufferedImage.TYPE_INT_RGB || src
+                        .getType() == BufferedImage.TYPE_INT_ARGB) && (dst
+                        .getType() == BufferedImage.TYPE_INT_RGB || dst
+                        .getType() == BufferedImage.TYPE_INT_ARGB))) {
+                    finalDst = dst;
+                    dst = createCompatibleDestImage(src, null);
+                }
+            }
+        }
+
+        // TODO
+        //if (!canUseIpp || ippFilter(src.getRaster(), dst.getRaster(), src.getType(), skipAlpha) != 0)
+            if (slowFilter(src.getRaster(), dst.getRaster(), skipAlpha) != 0) {
+                // awt.21F=Unable to transform source
+                throw new ImagingOpException (Messages.getString("awt.21F")); //$NON-NLS-1$
+            }
+
+        if (finalDst != null) {
+            Graphics2D g = finalDst.createGraphics();
+            g.setComposite(AlphaComposite.Src);
+            g.drawImage(dst, 0, 0, null);
+        } else {
+            finalDst = dst;
+        }
+
+        return dst;
+    }
+
+    /**
+     * Slow filter.
+     * 
+     * @param src the src
+     * @param dst the dst
+     * @param skipAlpha the skip alpha
+     * 
+     * @return the int
+     */
+    private final int slowFilter(Raster src, WritableRaster dst, boolean skipAlpha) {
+        int minSrcX = src.getMinX();
+        int minDstX = dst.getMinX();
+        int minSrcY = src.getMinY();
+        int minDstY = dst.getMinY();
+
+        int skippingChannels = skipAlpha ? 1 : 0;
+        int numBands2Process = src.getNumBands() - skippingChannels;
+
+        int numBands = src.getNumBands();
+        int srcHeight = src.getHeight();
+        int srcWidth = src.getWidth();
+
+        int[] pixels = null;
+        int offset = lut.getOffset();
+
+        if (lut instanceof ByteLookupTable){
+            byte[][] byteData = ((ByteLookupTable)lut).getTable();
+            pixels = src.getPixels(minSrcX, minSrcY, srcWidth, srcHeight, pixels);
+
+            if (lut.getNumComponents() != 1){
+                for (int i=0; i < pixels.length; i+= numBands){
+                    for (int b = 0; b < numBands2Process; b++){
+                        pixels[i+b] = byteData[b][pixels[i+b]-offset] & 0xFF;
+                    }
+                }
+            } else {
+                for (int i=0; i < pixels.length; i+= numBands){
+                    for (int b = 0; b < numBands2Process; b++){
+                        pixels[i+b] = byteData[0][pixels[i+b]-offset] & 0xFF;
+                    }
+                }
+            }
+
+            dst.setPixels(minDstX, minDstY, srcWidth, srcHeight, pixels);
+        } else if (lut instanceof ShortLookupTable){
+            short[][] shortData  = ((ShortLookupTable)lut).getTable();
+            pixels = src.getPixels(minSrcX, minSrcY, srcWidth, srcHeight, pixels);
+
+            if (lut.getNumComponents() != 1){
+                for (int i=0; i < pixels.length; i+= numBands){
+                    for (int b = 0; b < numBands2Process; b++){
+                        pixels[i+b] = shortData[b][pixels[i+b]-offset] & 0xFFFF;
+                    }
+                }
+            } else {
+                for (int i=0; i < pixels.length; i+= numBands){
+                    for (int b = 0; b < numBands2Process; b++){
+                        pixels[i+b] = shortData[0][pixels[i+b]-offset] & 0xFFFF;
+                    }
+                }
+            }
+
+            dst.setPixels(minDstX, minDstY, srcWidth, srcHeight, pixels);
+        } else {
+            int pixel[] = new int[src.getNumBands()];
+            int maxY = minSrcY + srcHeight;
+            int maxX = minSrcX + srcWidth;
+            for (int srcY=minSrcY, dstY = minDstY; srcY < maxY; srcY++, dstY++){
+                for (int srcX=minSrcX, dstX = minDstX; srcX < maxX; srcX++, dstX++){
+                    src.getPixel(srcX, srcY, pixel);
+                    lut.lookupPixel(pixel, pixel);
+                    dst.setPixel(dstX, dstY, pixel);
+                }
+            }
+        }
+
+        return 0;
+    }
+
+    /**
+     * Creates the byte levels.
+     * 
+     * @param channels the channels
+     * @param skipAlpha the skip alpha
+     * @param levels the levels
+     * @param values the values
+     * @param channelsOrder the channels order
+     */
+    private final void createByteLevels(
+            int channels, boolean skipAlpha,
+            int levels[], int values[], int channelsOrder[]
+    ) {
+        byte data[][] = ((ByteLookupTable)lut).getTable();
+        int nLevels = data[0].length;
+        int offset = lut.getOffset();
+
+        // Use one data array for all channels or use several data arrays
+        int dataIncrement = data.length > 1 ? 1 : 0;
+
+        for (int ch = 0, dataIdx = 0; ch<channels; dataIdx+=dataIncrement, ch++) {
+            int channelOffset = channelsOrder == null ? ch : channelsOrder[ch];
+            int channelBase = nLevels * channelOffset;
+
+            // Skip last channel if needed, zero values are OK -
+            // no changes to the channel information will be done in IPP
+            if ((channelOffset == channels-1 && skipAlpha) || (dataIdx >= data.length)) {
+                continue;
+            }
+
+            System.arraycopy(levelInitializer, offset, levels, channelBase, nLevels);
+            for (int from=0, to=channelBase; from<nLevels; from++, to++) {
+                values[to] = data[dataIdx][from] & 0xFF;
+            }
+        }
+    }
+
+    /**
+     * Creates the short levels.
+     * 
+     * @param channels the channels
+     * @param skipAlpha the skip alpha
+     * @param levels the levels
+     * @param values the values
+     * @param channelsOrder the channels order
+     */
+    private final void createShortLevels(
+            int channels, boolean skipAlpha,
+            int levels[], int values[], int channelsOrder[]
+    ) {
+        short data[][] = ((ShortLookupTable)lut).getTable();
+        int nLevels = data[0].length;
+        int offset = lut.getOffset();
+
+        // Use one data array for all channels or use several data arrays
+        int dataIncrement = data.length > 1 ? 1 : 0;
+
+        for (int ch = 0, dataIdx = 0; ch<channels; dataIdx+=dataIncrement, ch++) {
+            int channelOffset = channelsOrder == null ? ch : channelsOrder[ch];
+
+            // Skip last channel if needed, zero values are OK -
+            // no changes to the channel information will be done in IPP
+            if ((channelOffset == channels-1 && skipAlpha) || (dataIdx >= data.length)) {
+                continue;
+            }
+
+            int channelBase = nLevels * channelOffset;
+            System.arraycopy(levelInitializer, offset, levels, channelBase, nLevels);
+            for (int from=0, to=channelBase; from<nLevels; from++, to++) {
+                values[to] = data[dataIdx][from] & 0xFFFF;
+            }
+        }
+    }
+
+    // TODO remove when this method is used
+    /**
+     * Ipp filter.
+     * 
+     * @param src the src
+     * @param dst the dst
+     * @param imageType the image type
+     * @param skipAlpha the skip alpha
+     * 
+     * @return the int
+     */
+    @SuppressWarnings("unused")
+    private final int ippFilter(
+            Raster src, WritableRaster dst,
+            int imageType, boolean skipAlpha
+    ) {
+        int res;
+
+        int srcStride, dstStride;
+        int channels;
+        int offsets[] = null;
+        int channelsOrder[] = null;
+
+        switch (imageType) {
+            case BufferedImage.TYPE_INT_ARGB:
+            case BufferedImage.TYPE_INT_ARGB_PRE:
+            case BufferedImage.TYPE_INT_RGB: {
+                channels = 4;
+                srcStride = src.getWidth()*4;
+                dstStride = dst.getWidth()*4;
+                channelsOrder = new int[] {2, 1, 0, 3};
+                break;
+            }
+
+            case BufferedImage.TYPE_4BYTE_ABGR:
+            case BufferedImage.TYPE_4BYTE_ABGR_PRE:
+            case BufferedImage.TYPE_INT_BGR: {
+                channels = 4;
+                srcStride = src.getWidth()*4;
+                dstStride = dst.getWidth()*4;
+                break;
+            }
+
+            case BufferedImage.TYPE_BYTE_GRAY: {
+                channels = 1;
+                srcStride = src.getWidth();
+                dstStride = dst.getWidth();
+                break;
+            }
+
+            case BufferedImage.TYPE_3BYTE_BGR: {
+                channels = 3;
+                srcStride = src.getWidth()*3;
+                dstStride = dst.getWidth()*3;
+                channelsOrder = new int[] {2, 1, 0};
+                break;
+            }
+
+            case BufferedImage.TYPE_USHORT_GRAY:
+            case BufferedImage.TYPE_USHORT_565_RGB:
+            case BufferedImage.TYPE_USHORT_555_RGB:
+            case BufferedImage.TYPE_BYTE_BINARY: {
+                return slowFilter(src, dst, skipAlpha);
+            }
+
+            default: {
+                SampleModel srcSM = src.getSampleModel();
+                SampleModel dstSM = dst.getSampleModel();
+
+                if (
+                        srcSM instanceof PixelInterleavedSampleModel &&
+                        dstSM instanceof PixelInterleavedSampleModel
+                ) {
+                    // Check PixelInterleavedSampleModel
+                    if (
+                            srcSM.getDataType() != DataBuffer.TYPE_BYTE ||
+                            dstSM.getDataType() != DataBuffer.TYPE_BYTE
+                    ) {
+                        return slowFilter(src, dst, skipAlpha);
+                    }
+
+                    // Have IPP functions for 1, 3 and 4 channels
+                    channels = srcSM.getNumBands();
+                    if (!(channels == 1 || channels == 3 || channels == 4)) {
+                        return slowFilter(src, dst, skipAlpha);
+                    }
+
+                    srcStride = ((ComponentSampleModel) srcSM).getScanlineStride();
+                    dstStride = ((ComponentSampleModel) dstSM).getScanlineStride();
+
+                    channelsOrder = ((ComponentSampleModel) srcSM).getBandOffsets();
+                } else if (
+                        srcSM instanceof SinglePixelPackedSampleModel &&
+                        dstSM instanceof SinglePixelPackedSampleModel
+                ) {
+                    // Check SinglePixelPackedSampleModel
+                    SinglePixelPackedSampleModel sppsm1 =
+                            (SinglePixelPackedSampleModel) srcSM;
+                    SinglePixelPackedSampleModel sppsm2 =
+                            (SinglePixelPackedSampleModel) dstSM;
+
+                    channels = sppsm1.getNumBands();
+
+                     // TYPE_INT_RGB, TYPE_INT_ARGB...
+                    if (
+                            sppsm1.getDataType() != DataBuffer.TYPE_INT ||
+                            sppsm2.getDataType() != DataBuffer.TYPE_INT ||
+                            !(channels == 3 || channels == 4)
+                    ) {
+                        return slowFilter(src, dst, skipAlpha);
+                    }
+
+                    // Check compatibility of sample models
+                    if (
+                            !Arrays.equals(sppsm1.getBitOffsets(), sppsm2.getBitOffsets()) ||
+                            !Arrays.equals(sppsm1.getBitMasks(), sppsm2.getBitMasks())
+                    ) {
+                        return slowFilter(src, dst, skipAlpha);
+                    }
+
+                    for (int i=0; i<channels; i++) {
+                        if (sppsm1.getSampleSize(i) != 8) {
+                            return slowFilter(src, dst, skipAlpha);
+                        }
+                    }
+
+                    channelsOrder = new int[channels];
+                    int bitOffsets[] = sppsm1.getBitOffsets();
+                    for (int i=0; i<channels; i++) {
+                        channelsOrder[i] = bitOffsets[i] / 8;
+                    }
+
+                    if (channels == 3) { // Don't skip channel now, could be optimized
+                        channels = 4;
+                    }
+
+                    srcStride = sppsm1.getScanlineStride() * 4;
+                    dstStride = sppsm2.getScanlineStride() * 4;
+                } else {
+                    return slowFilter(src, dst, skipAlpha);
+                }
+
+                // Fill offsets if there's a child raster
+                if (src.getParent() != null || dst.getParent() != null) {
+                    if (
+                            src.getSampleModelTranslateX() != 0 ||
+                            src.getSampleModelTranslateY() != 0 ||
+                            dst.getSampleModelTranslateX() != 0 ||
+                            dst.getSampleModelTranslateY() != 0
+                    ) {
+                        offsets = new int[4];
+                        offsets[0] = -src.getSampleModelTranslateX() + src.getMinX();
+                        offsets[1] = -src.getSampleModelTranslateY() + src.getMinY();
+                        offsets[2] = -dst.getSampleModelTranslateX() + dst.getMinX();
+                        offsets[3] = -dst.getSampleModelTranslateY() + dst.getMinY();
+                    }
+                }
+            }
+        }
+
+        int levels[] = null, values[] = null;
+        int channelMultiplier = skipAlpha ? -1 : 1;
+        if (channelMultiplier*channels == validForChannels) { // use existing levels/values
+            levels = cachedLevels;
+            values = cachedValues;
+        } else { // create new levels/values
+            if (lut instanceof ByteLookupTable) {
+                byte data[][] = ((ByteLookupTable)lut).getTable();
+                levels = new int[channels*data[0].length];
+                values = new int[channels*data[0].length];
+                createByteLevels(channels, skipAlpha, levels, values, channelsOrder);
+            } else if (lut instanceof ShortLookupTable) {
+                short data[][] = ((ShortLookupTable)lut).getTable();
+                levels = new int[channels*data[0].length];
+                values = new int[channels*data[0].length];
+                createShortLevels(channels, skipAlpha, levels, values, channelsOrder);
+            }
+
+            // cache levels/values
+            validForChannels = channelMultiplier*channels;
+            cachedLevels = levels;
+            cachedValues = values;
+        }
+
+        Object srcData, dstData;
+        AwtImageBackdoorAccessor dbAccess = AwtImageBackdoorAccessor.getInstance();
+        try {
+            srcData = dbAccess.getData(src.getDataBuffer());
+            dstData = dbAccess.getData(dst.getDataBuffer());
+        } catch (IllegalArgumentException e) {
+            return -1; // Unknown data buffer type
+        }
+
+        res = ippLUT(
+            srcData, src.getWidth(), src.getHeight(), srcStride,
+            dstData, dst.getWidth(), dst.getHeight(), dstStride,
+            levels, values,
+            channels, offsets,
+            false
+        );
+
+        return res;
+    }
+
+    /**
+     * Ipp lut.
+     * 
+     * @param src the src
+     * @param srcWidth the src width
+     * @param srcHeight the src height
+     * @param srcStride the src stride
+     * @param dst the dst
+     * @param dstWidth the dst width
+     * @param dstHeight the dst height
+     * @param dstStride the dst stride
+     * @param levels the levels
+     * @param values the values
+     * @param channels the channels
+     * @param offsets the offsets
+     * @param linear the linear
+     * 
+     * @return the int
+     */
+    final static native int ippLUT(
+            Object src, int srcWidth, int srcHeight, int srcStride,
+            Object dst, int dstWidth, int dstHeight, int dstStride,
+            int levels[], int values[],
+            int channels, int offsets[],
+            boolean linear
+    );
+}
diff --git a/awt/java/awt/image/LookupTable.java b/awt/java/awt/image/LookupTable.java
new file mode 100644
index 0000000..d15f23c
--- /dev/null
+++ b/awt/java/awt/image/LookupTable.java
@@ -0,0 +1,93 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ *
+ * @date: Oct 14, 2005
+ */
+
+package java.awt.image;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * This abstract LookupTable class represents lookup table which
+ * is defined with the number of components and offset value.
+ * ByteLookupTable and ShortLookupTable classes are subclasses of
+ * LookupTable which contains byte and short data tables as
+ * an input arrays for bands or components of image.
+ */
+public abstract class LookupTable {
+    
+    /** The offset. */
+    private int offset;
+    
+    /** The num components. */
+    private int numComponents;
+
+    /**
+     * Instantiates a new LookupTable with the specified offset value
+     * and number of components.
+     * 
+     * @param offset the offset value.
+     * @param numComponents the number of components.
+     */
+    protected LookupTable(int offset, int numComponents) {
+        if (offset < 0) {
+            // awt.232=Offset should be not less than zero
+            throw new IllegalArgumentException(Messages.getString("awt.232")); //$NON-NLS-1$
+        }
+        if (numComponents < 1) {
+            // awt.233=Number of components should be positive
+            throw new IllegalArgumentException(Messages.getString("awt.233")); //$NON-NLS-1$
+        }
+
+        this.offset = offset;
+        this.numComponents = numComponents;
+    }
+
+    /**
+     * Gets the offset value of this Lookup table.
+     * 
+     * @return the offset value of this Lookup table.
+     */
+    public int getOffset() {
+        return offset;
+    }
+
+    /**
+     * Gets the number of components of this Lookup table.
+     * 
+     * @return the number components of this Lookup table.
+     */
+    public int getNumComponents() {
+        return numComponents;
+    }
+
+    /**
+     * Returns a int array which contains samples of the specified
+     * pixel which is translated with the lookup table of this 
+     * LookupTable. The resulted array is stored to the dst array.
+     * 
+     * @param src the source array.
+     * @param dst the destination array where the result can be stored.
+     * 
+     * @return the int array of translated samples of a pixel.
+     */
+    public abstract int[] lookupPixel(int[] src, int[] dst);
+}
diff --git a/awt/java/awt/image/MemoryImageSource.java b/awt/java/awt/image/MemoryImageSource.java
new file mode 100644
index 0000000..983f19e
--- /dev/null
+++ b/awt/java/awt/image/MemoryImageSource.java
@@ -0,0 +1,512 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The MemoryImageSource class is used to produces pixels of an image from
+ * an array. This class can manage a memory image which 
+ * contains an animation or custom rendering.
+ */
+public class MemoryImageSource implements ImageProducer {
+
+    /** The width. */
+    int width;
+    
+    /** The height. */
+    int height;
+    
+    /** The cm. */
+    ColorModel cm;
+    
+    /** The b data. */
+    byte bData[];
+    
+    /** The i data. */
+    int iData[];
+    
+    /** The offset. */
+    int offset;
+    
+    /** The scanline. */
+    int scanline;
+    
+    /** The properties. */
+    Hashtable<?, ?> properties;
+    
+    /** The consumers. */
+    Vector<ImageConsumer> consumers;
+    
+    /** The animated. */
+    boolean animated;
+    
+    /** The fullbuffers. */
+    boolean fullbuffers;
+    
+    /** The data type. */
+    int dataType;
+
+    /** The Constant DATA_TYPE_BYTE. */
+    static final int DATA_TYPE_BYTE = 0;
+    
+    /** The Constant DATA_TYPE_INT. */
+    static final int DATA_TYPE_INT = 1;
+
+    /**
+     * Instantiates a new MemoryImageSource with the specified
+     * parameters.
+     * 
+     * @param w the width of the rectangular area of pixels.
+     * @param h the height of the rectangular area of pixels.
+     * @param cm the specified ColorModel.
+     * @param pix the pixel array.
+     * @param off the offset in the pixel array.
+     * @param scan the distance from one pixel's row to the next 
+     * in the pixel array.
+     * @param props the set of properties to be used for image
+     * processing.
+     */
+    public MemoryImageSource(int w, int h, ColorModel cm, int pix[],
+            int off, int scan, Hashtable<?, ?> props) {
+        init(w, h, cm, pix, off, scan, props);
+    }
+
+    /**
+     * Instantiates a new MemoryImageSource with the specified
+     * parameters.
+     * 
+     * @param w the width of the rectangular area of pixels.
+     * @param h the height of the rectangular area of pixels.
+     * @param cm the specified ColorModel.
+     * @param pix the pixel array.
+     * @param off the offset in the pixel array.
+     * @param scan the distance from one pixel's row to the next 
+     * in the pixel array.
+     * @param props the set of properties to be used for image
+     * processing.
+     */
+    public MemoryImageSource(int w, int h, ColorModel cm, byte pix[],
+            int off, int scan, Hashtable<?, ?> props) {
+        init(w, h, cm, pix, off, scan, props);
+    }
+
+    /**
+     * Instantiates a new MemoryImageSource with the specified
+     * parameters and default RGB ColorModel.
+     * 
+     * @param w the width of the rectangular area of pixels.
+     * @param h the height of the rectangular area of pixels.
+     * @param pix the pixel array.
+     * @param off the offset in the pixel array.
+     * @param scan the distance from one pixel's row to the next 
+     * in the pixel array.
+     * @param props the set of properties to be used for image
+     * processing.
+     */
+    public MemoryImageSource(int w, int h, int pix[], int off, int scan,
+            Hashtable<?, ?> props) {
+        init(w, h, ColorModel.getRGBdefault(), pix, off, scan, props);
+    }
+
+    /**
+     * Instantiates a new MemoryImageSource with the specified
+     * parameters.
+     * 
+     * @param w the width of the rectangular area of pixels.
+     * @param h the height of the rectangular area of pixels.
+     * @param cm the specified ColorModel.
+     * @param pix the pixel array.
+     * @param off the offset in the pixel array.
+     * @param scan the distance from one pixel's row to the next 
+     * in the pixel array.
+     */
+    public MemoryImageSource(int w, int h, ColorModel cm, int pix[],
+            int off, int scan) {
+        init(w, h, cm, pix, off, scan, null);
+    }
+
+    /**
+     * Instantiates a new MemoryImageSource with the specified
+     * parameters.
+     * 
+     * @param w the width of the rectangular area of pixels.
+     * @param h the height of the rectangular area of pixels.
+     * @param cm the specified ColorModel.
+     * @param pix the pixel array.
+     * @param off the offset in the pixel array.
+     * @param scan the distance from one pixel's row to the next 
+     * in the pixel array.
+     */
+    public MemoryImageSource(int w, int h, ColorModel cm, byte pix[],
+            int off, int scan) {
+        init(w, h, cm, pix, off, scan, null);
+    }
+
+    /**
+     * Instantiates a new MemoryImageSource with the specified
+     * parameters and default RGB ColorModel.
+     * 
+     * @param w the width of the rectangular area of pixels.
+     * @param h the height of the rectangular area of pixels.
+     * @param pix the pixels array.
+     * @param off the offset in the pixel array.
+     * @param scan the distance from one pixel's row to the next 
+     * in the pixel array.
+     */
+    public MemoryImageSource(int w, int h, int pix[], int off, int scan) {
+        init(w, h, ColorModel.getRGBdefault(), pix, off, scan, null);
+    }
+
+    public synchronized boolean isConsumer(ImageConsumer ic) {
+        return consumers.contains(ic);
+    }
+
+    public void startProduction(ImageConsumer ic) {
+        if(!isConsumer(ic) && ic != null) {
+            consumers.addElement(ic);
+        }
+        try{
+            setHeader(ic);
+            setPixels(ic, 0, 0, width, height);
+            if(animated){
+                ic.imageComplete(ImageConsumer.SINGLEFRAMEDONE);
+            }else{
+                ic.imageComplete(ImageConsumer.STATICIMAGEDONE);
+                if(isConsumer(ic)) {
+                    removeConsumer(ic);
+                }
+            }
+        }catch(Exception e){
+            if(isConsumer(ic)) {
+                ic.imageComplete(ImageConsumer.IMAGEERROR);
+            }
+            if(isConsumer(ic)) {
+                removeConsumer(ic);
+            }
+        }
+    }
+
+    public void requestTopDownLeftRightResend(ImageConsumer ic) {
+    }
+
+    public synchronized void removeConsumer(ImageConsumer ic) {
+        consumers.removeElement(ic);
+    }
+
+    public synchronized void addConsumer(ImageConsumer ic) {
+        if(ic == null || consumers.contains(ic)) {
+            return;
+        }
+        consumers.addElement(ic);
+    }
+
+    /**
+     * Replaces the pixel data with a new pixel array for holding 
+     * the pixels for this image. If an animation 
+     * flag is set to true value by the setAnimated() method, 
+     * the new pixels will be immediately delivered to the ImageConsumers. 
+     * 
+     * @param newpix the new pixel array.
+     * @param newmodel the new ColorModel.
+     * @param offset the offset in the array.
+     * @param scansize the distance from one row of pixels to the next row
+     * in the pixel array
+     */
+    public synchronized void newPixels(int newpix[], ColorModel newmodel,
+            int offset, int scansize) {
+        this.dataType = DATA_TYPE_INT;
+        this.iData = newpix;
+        this.cm = newmodel;
+        this.offset = offset;
+        this.scanline = scansize;
+        newPixels();
+    }
+
+    /**
+     * Replaces the pixel data with a new pixel array for holding 
+     * the pixels for this image. If an animation 
+     * flag is set to true value by the setAnimated() method, 
+     * the new pixels will be immediately delivered to the ImageConsumers. 
+     * 
+     * @param newpix the new pixel array.
+     * @param newmodel the new ColorModel.
+     * @param offset the offset in the array.
+     * @param scansize the distance from one row of pixels to the next row
+     * in the pixel array
+     */
+    public synchronized void newPixels(byte newpix[], ColorModel newmodel,
+            int offset, int scansize) {
+        this.dataType = DATA_TYPE_BYTE;
+        this.bData = newpix;
+        this.cm = newmodel;
+        this.offset = offset;
+        this.scanline = scansize;
+        newPixels();
+    }
+
+    /**
+     * Sets the full buffer updates flag to true. If this is an 
+     * animated image, the image consumers hints are updated
+     * accordingly.
+     * 
+     * @param fullbuffers the true if the pixel buffer should be sent always.
+     */
+    public synchronized void setFullBufferUpdates(boolean fullbuffers) {
+        if(this.fullbuffers == fullbuffers) {
+            return;
+        }
+        this.fullbuffers = fullbuffers;
+        if(animated){
+            Object consAr[] = consumers.toArray();
+            for (Object element : consAr) {
+                ImageConsumer con = (ImageConsumer)element;
+                try{
+                    if(fullbuffers){
+                        con.setHints(ImageConsumer.TOPDOWNLEFTRIGHT |
+                                ImageConsumer.COMPLETESCANLINES);
+                    }else{
+                        con.setHints(ImageConsumer.RANDOMPIXELORDER);
+                    }
+                }catch(Exception e){
+                    if(isConsumer(con)) {
+                        con.imageComplete(ImageConsumer.IMAGEERROR);
+                    }
+                    if(isConsumer(con)) {
+                        removeConsumer(con);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Sets the flag that tells whether this memory image has more 
+     * than one frame (for animation): true for multiple frames,
+     * false if this class represents a single frame image.
+     *  
+     * @param animated whether this image represents an animation.
+     */
+    public synchronized void setAnimated(boolean animated) {
+        if(this.animated == animated) {
+            return;
+        }
+        Object consAr[] = consumers.toArray();
+        for (Object element : consAr) {
+            ImageConsumer con = (ImageConsumer)element;
+            try{
+                con.imageComplete(ImageConsumer.STATICIMAGEDONE);
+            }catch(Exception e){
+                if(isConsumer(con)) {
+                    con.imageComplete(ImageConsumer.IMAGEERROR);
+                }
+            }
+            if(isConsumer(con)){
+                removeConsumer(con);
+            }
+        }
+        this.animated = animated;
+    }
+
+    /**
+     * Sends the specified rectangular area of the buffer to 
+     * ImageConsumers and notifies them that an animation frame 
+     * is completed only if framenotify parameter is true.
+     * That works only if the animated flag has been set to true 
+     * by the setAnimated() method. If the full buffer update flag 
+     * has been set to true by the setFullBufferUpdates() method, 
+     * then the entire buffer will always be sent ignoring parameters.
+     * 
+     * @param x the X coordinate of the rectangular area.
+     * @param y the Y coordinate of rthe ectangular area.
+     * @param w the width of the rectangular area.
+     * @param h the height of the rectangular area. 
+     * @param framenotify true if a SINGLEFRAMEDONE notification
+     * should be sent to the registered consumers, false otherwise. 
+     */
+    public synchronized void newPixels(int x, int y, int w, int h,
+            boolean framenotify) {
+        if(animated){
+            if(fullbuffers){
+                x = 0;
+                y = 0;
+                w = width;
+                h = height;
+            }else{
+                if(x < 0){
+                    w += x;
+                    x = 0;
+                }
+                if(w > width) {
+                    w = width - x;
+                }
+                if(y < 0){
+                    h += y;
+                    y = 0;
+                }
+            }
+            if(h > height) {
+                h = height - y;
+            }
+            Object consAr[] = consumers.toArray();
+            for (Object element : consAr) {
+                ImageConsumer con = (ImageConsumer)element;
+                try{
+                    if(w > 0 && h > 0) {
+                        setPixels(con, x, y, w, h);
+                    }
+                    if(framenotify) {
+                        con.imageComplete(ImageConsumer.SINGLEFRAMEDONE);
+                    }
+                }catch(Exception ex){
+                    if(isConsumer(con)) {
+                        con.imageComplete(ImageConsumer.IMAGEERROR);
+                    }
+                    if(isConsumer(con)) {
+                        removeConsumer(con);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Sends the specified rectangular area of the buffer to 
+     * the ImageConsumers and notifies them that an animation frame 
+     * is completed if the animated flag has been set to true 
+     * by the setAnimated() method. If the full buffer update flag 
+     * has been set to true by the setFullBufferUpdates() method, 
+     * then the entire buffer will always be sent ignoring parameters.
+     * 
+     * @param x the X coordinate of the rectangular area.
+     * @param y the Y coordinate of the rectangular area.
+     * @param w the width of the rectangular area.
+     * @param h the height of the rectangular area. 
+     */
+    public synchronized void newPixels(int x, int y, int w, int h) {
+        newPixels(x, y, w, h, true);
+    }
+
+    /**
+     * Sends a new buffer of pixels to the ImageConsumers 
+     * and notifies them that an animation frame is completed if
+     * the animated flag has been set to true by the setAnimated() method. 
+     */
+    public void newPixels() {
+        newPixels(0, 0, width, height, true);
+    }
+
+    /**
+     * Inits the.
+     * 
+     * @param width the width
+     * @param height the height
+     * @param model the model
+     * @param pixels the pixels
+     * @param off the off
+     * @param scan the scan
+     * @param prop the prop
+     */
+    private void init(int width, int height, ColorModel model, byte pixels[],
+            int off, int scan, Hashtable<?, ?> prop){
+
+        this.width = width;
+        this.height = height;
+        this.cm = model;
+        this.bData = pixels;
+        this.offset = off;
+        this.scanline = scan;
+        this.properties = prop;
+        this.dataType = DATA_TYPE_BYTE;
+        this.consumers = new Vector<ImageConsumer>();
+
+    }
+
+    /**
+     * Inits the.
+     * 
+     * @param width the width
+     * @param height the height
+     * @param model the model
+     * @param pixels the pixels
+     * @param off the off
+     * @param scan the scan
+     * @param prop the prop
+     */
+    private void init(int width, int height, ColorModel model, int pixels[],
+            int off, int scan, Hashtable<?, ?> prop){
+
+        this.width = width;
+        this.height = height;
+        this.cm = model;
+        this.iData = pixels;
+        this.offset = off;
+        this.scanline = scan;
+        this.properties = prop;
+        this.dataType = DATA_TYPE_INT;
+        this.consumers = new Vector<ImageConsumer>();
+    }
+
+    /**
+     * Sets the pixels.
+     * 
+     * @param con the con
+     * @param x the x
+     * @param y the y
+     * @param w the w
+     * @param h the h
+     */
+    private void setPixels(ImageConsumer con, int x, int y, int w, int h){
+        int pixelOff = scanline * y + offset + x;
+
+        switch(dataType){
+        case DATA_TYPE_BYTE:
+            con.setPixels(x, y, w, h, cm, bData, pixelOff, scanline);
+            break;
+        case DATA_TYPE_INT:
+            con.setPixels(x, y, w, h, cm, iData, pixelOff, scanline);
+            break;
+        default:
+            // awt.22A=Wrong type of pixels array
+            throw new IllegalArgumentException(Messages.getString("awt.22A")); //$NON-NLS-1$
+        }
+    }
+
+    /**
+     * Sets the header.
+     * 
+     * @param con the new header
+     */
+    private synchronized void setHeader(ImageConsumer con){
+        con.setDimensions(width, height);
+        con.setProperties(properties);
+        con.setColorModel(cm);
+        con.setHints(animated ? (fullbuffers ? (ImageConsumer.TOPDOWNLEFTRIGHT |
+                ImageConsumer.COMPLETESCANLINES) : ImageConsumer.RANDOMPIXELORDER) :
+                (ImageConsumer.TOPDOWNLEFTRIGHT | ImageConsumer.COMPLETESCANLINES |
+                 ImageConsumer.SINGLEPASS | ImageConsumer.SINGLEFRAME));
+    }
+
+}
+
diff --git a/awt/java/awt/image/MultiPixelPackedSampleModel.java b/awt/java/awt/image/MultiPixelPackedSampleModel.java
new file mode 100644
index 0000000..dd44b49
--- /dev/null
+++ b/awt/java/awt/image/MultiPixelPackedSampleModel.java
@@ -0,0 +1,454 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The MultiPixelPackedSampleModel class represents image data with one
+ * band. This class packs multiple pixels with one sample in one data 
+ * element and supports the following data types: DataBuffer.TYPE_BYTE, 
+ * DataBuffer.TYPE_USHORT, or DataBuffer.TYPE_INT. 
+ */
+public class MultiPixelPackedSampleModel extends SampleModel {
+
+    /** The pixel bit stride. */
+    private int pixelBitStride;
+
+    /** The scanline stride. */
+    private int scanlineStride;
+
+    /** The data bit offset. */
+    private int dataBitOffset;
+
+    /** The bit mask. */
+    private int bitMask;
+
+    /** The data element size. */
+    private int dataElementSize;
+
+    /** The pixels per data element. */
+    private int pixelsPerDataElement;
+
+    /**
+     * Instantiates a new MultiPixelPackedSampleModel with the specified
+     * parameters.
+     * 
+     * @param dataType the data type of the samples.
+     * @param w the width of the image data.
+     * @param h the height of the image data.
+     * @param numberOfBits the number of bits per pixel.
+     * @param scanlineStride the scanline stride of the of the image data.
+     * @param dataBitOffset the array of the band offsets.
+     */
+    public MultiPixelPackedSampleModel(int dataType, int w, int h,
+            int numberOfBits, int scanlineStride, int dataBitOffset) {
+
+        super(dataType, w, h, 1);
+        if (dataType != DataBuffer.TYPE_BYTE &&
+               dataType != DataBuffer.TYPE_USHORT &&
+               dataType != DataBuffer.TYPE_INT) {
+            // awt.61=Unsupported data type: {0}
+            throw new IllegalArgumentException(Messages.getString("awt.61", //$NON-NLS-1$
+                    dataType));
+        }
+
+        this.scanlineStride = scanlineStride;
+        if(numberOfBits == 0) {
+            // awt.20C=Number of Bits equals to zero
+            throw new RasterFormatException(Messages.getString("awt.20C")); //$NON-NLS-1$
+        }
+        this.pixelBitStride = numberOfBits;
+        this.dataElementSize = DataBuffer.getDataTypeSize(dataType);
+        if(dataElementSize % pixelBitStride != 0) {
+            // awt.20D=The number of bits per pixel is not a power of 2 or pixels span data element boundaries
+            throw new RasterFormatException(Messages.getString("awt.20D")); //$NON-NLS-1$
+        }
+
+        if(dataBitOffset % numberOfBits != 0) {
+            // awt.20E=Data Bit offset is not a multiple of pixel bit stride
+            throw new RasterFormatException(Messages.getString("awt.20E")); //$NON-NLS-1$
+        }
+        this.dataBitOffset = dataBitOffset;
+
+        this.pixelsPerDataElement = dataElementSize / pixelBitStride;
+        this.bitMask = (1 << numberOfBits) - 1;
+    }
+
+    /**
+     * Instantiates a new MultiPixelPackedSampleModel with the specified
+     * parameters.
+     * 
+     * @param dataType the data type of the samples.
+     * @param w the width of the image data.
+     * @param h the height of the image data.
+     * @param numberOfBits the number of bits per pixel.
+     */
+    public MultiPixelPackedSampleModel(int dataType, int w, int h,
+            int numberOfBits) {
+
+        this(dataType, w, h, numberOfBits, (numberOfBits * w +
+               DataBuffer.getDataTypeSize(dataType) - 1) /
+               DataBuffer.getDataTypeSize(dataType), 0);
+    }
+
+    @Override
+    public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
+        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+        switch (getTransferType()) {
+        case DataBuffer.TYPE_BYTE:
+            byte bdata[];
+            if (obj == null) {
+                bdata = new byte[1];
+            } else {
+                bdata = (byte[]) obj;
+            }
+            bdata[0] = (byte) getSample(x, y, 0, data);
+            obj = bdata;
+            break;
+        case DataBuffer.TYPE_USHORT:
+            short sdata[];
+            if (obj == null) {
+                sdata = new short[1];
+            } else {
+                sdata = (short[]) obj;
+            }
+            sdata[0] = (short) getSample(x, y, 0, data);
+            obj = sdata;
+            break;
+        case DataBuffer.TYPE_INT:
+            int idata[];
+            if (obj == null) {
+                idata = new int[1];
+            } else {
+                idata = (int[]) obj;
+            }
+            idata[0] = getSample(x, y, 0, data);
+            obj = idata;
+            break;
+        }
+
+        return obj;
+    }
+
+    @Override
+    public void setDataElements(int x, int y, Object obj, DataBuffer data) {
+        setSample(x, y, obj, data, 1, 0);
+    }
+
+    /**
+     * Compares this MultiPixelPackedSampleModel object with 
+     * the specified object.
+     * 
+     * @param o the Object to be compared.
+     * 
+     * @return true, if the object is a MultiPixelPackedSampleModel 
+     * with the same data parameter values as this MultiPixelPackedSampleModel,
+     * false otherwise.
+     */
+    @Override
+    public boolean equals(Object o) {
+        if ((o == null) || !(o instanceof MultiPixelPackedSampleModel)) {
+            return false;
+        }
+
+        MultiPixelPackedSampleModel model = (MultiPixelPackedSampleModel) o;
+        return this.width == model.width &&
+               this.height == model.height &&
+               this.numBands == model.numBands &&
+               this.dataType == model.dataType &&
+               this.pixelBitStride == model.pixelBitStride &&
+               this.bitMask == model.bitMask &&
+               this.pixelsPerDataElement == model.pixelsPerDataElement &&
+               this.dataElementSize == model.dataElementSize &&
+               this.dataBitOffset == model.dataBitOffset &&
+               this.scanlineStride == model.scanlineStride;
+    }
+
+    @Override
+    public SampleModel createSubsetSampleModel(int bands[]) {
+        if (bands != null && bands.length != 1) {
+            // awt.20F=Number of bands must be only 1
+            throw new RasterFormatException(Messages.getString("awt.20F")); //$NON-NLS-1$
+        }
+        return createCompatibleSampleModel(width, height);
+    }
+
+    @Override
+    public SampleModel createCompatibleSampleModel(int w, int h) {
+        return new MultiPixelPackedSampleModel(dataType, w, h, pixelBitStride);
+    }
+
+    @Override
+    public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
+        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+        int pixel[];
+        if (iArray == null) {
+            pixel = new int[numBands];
+        } else {
+            pixel = iArray;
+        }
+
+        pixel[0] = getSample(x, y, 0, data);
+        return pixel;
+    }
+
+    @Override
+    public void setPixel(int x, int y, int iArray[], DataBuffer data) {
+        setSample(x, y, iArray, data, 2, 0);
+    }
+
+    @Override
+    public int getSample(int x, int y, int b, DataBuffer data) {
+        if (x < 0 || y < 0 || x >= this.width || y >= this.height || b != 0) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+
+        int bitnum = dataBitOffset + x * pixelBitStride;
+        int elem = data.getElem(y * scanlineStride + bitnum / dataElementSize);
+        int shift = dataElementSize - (bitnum & (dataElementSize - 1)) -
+                pixelBitStride;
+
+        return (elem >> shift) & bitMask;
+    }
+
+    @Override
+    public void setSample(int x, int y, int b, int s, DataBuffer data) {
+        if (b != 0) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+
+        setSample(x, y, null, data, 3, s);
+    }
+
+    @Override
+    public DataBuffer createDataBuffer() {
+        DataBuffer dataBuffer = null;
+        int size = scanlineStride * height;
+
+        switch (dataType) {
+        case DataBuffer.TYPE_BYTE:
+            dataBuffer = new DataBufferByte(size + (dataBitOffset + 7) / 8);
+            break;
+        case DataBuffer.TYPE_USHORT:
+            dataBuffer = new DataBufferUShort(size + (dataBitOffset + 15) / 16);
+            break;
+        case DataBuffer.TYPE_INT:
+            dataBuffer = new DataBufferInt(size + (dataBitOffset + 31) / 32);
+            break;
+        }
+        return dataBuffer;
+    }
+
+    /**
+     * Gets the offset of the specified pixel in the data array.
+     * 
+     * @param x the X coordinate of the specified pixel.
+     * @param y the Y coordinate of the specified pixel.
+     * 
+     * @return the offset of the specified pixel.
+     */
+    public int getOffset(int x, int y) {
+        return y * scanlineStride + (x * pixelBitStride + dataBitOffset) /
+               dataElementSize;
+    }
+
+    @Override
+    public int getSampleSize(int band) {
+        return pixelBitStride;
+    }
+
+    /**
+     * Gets the bit offset in the data element which 
+     * is stored for the specified pixel of a scanline.
+     * 
+     * @param x the pixel.
+     * 
+     * @return the bit offset of the pixel in the data element.
+     */
+    public int getBitOffset(int x) {
+        return (x * pixelBitStride + dataBitOffset) % dataElementSize;
+    }
+
+    @Override
+    public int[] getSampleSize() {
+        int sampleSizes[] = { pixelBitStride };
+        return sampleSizes;
+    }
+
+    /**
+     * Returns a hash code of this MultiPixelPackedSampleModel class.
+     * 
+     * @return the hash code of this MultiPixelPackedSampleModel class.
+     */
+    @Override
+    public int hashCode() {
+        int hash = 0;
+        int tmp = 0;
+
+        hash = width;
+        tmp = hash >>> 24;
+        hash <<= 8;
+        hash |= tmp;
+        hash ^= height;
+        tmp = hash >>> 24;
+        hash <<= 8;
+        hash |= tmp;
+        hash ^= numBands;
+        tmp = hash >>> 24;
+        hash <<= 8;
+        hash |= tmp;
+        hash ^= dataType;
+        tmp = hash >>> 24;
+        hash <<= 8;
+        hash |= tmp;
+        hash ^= scanlineStride;
+        tmp = hash >>> 24;
+        hash <<= 8;
+        hash |= tmp;
+        hash ^= pixelBitStride;
+        tmp = hash >>> 24;
+        hash <<= 8;
+        hash |= tmp;
+        hash ^= dataBitOffset;
+        tmp = hash >>> 24;
+        hash <<= 8;
+        hash |= tmp;
+        hash ^= bitMask;
+        tmp = hash >>> 24;
+        hash <<= 8;
+        hash |= tmp;
+        hash ^= dataElementSize;
+        tmp = hash >>> 24;
+        hash <<= 8;
+        hash |= tmp;
+        hash ^= pixelsPerDataElement;
+        return hash;
+    }
+
+    @Override
+    public int getTransferType() {
+        if (pixelBitStride > 16) {
+            return DataBuffer.TYPE_INT;
+        } else if (pixelBitStride > 8) {
+            return DataBuffer.TYPE_USHORT;
+        } else {
+            return DataBuffer.TYPE_BYTE;
+        }
+    }
+
+    /**
+     * Gets the scanline stride of this MultiPixelPackedSampleModel.
+     * 
+     * @return the scanline stride of this MultiPixelPackedSampleModel.
+     */
+    public int getScanlineStride() {
+        return scanlineStride;
+    }
+
+    /**
+     * Gets the pixel bit stride of this MultiPixelPackedSampleModel.
+     * 
+     * @return the pixel bit stride of this MultiPixelPackedSampleModel.
+     */
+    public int getPixelBitStride() {
+        return pixelBitStride;
+    }
+
+    @Override
+    public int getNumDataElements() {
+        return 1;
+    }
+
+    /**
+     * Gets the data bit offset.
+     * 
+     * @return the data bit offset.
+     */
+    public int getDataBitOffset() {
+        return dataBitOffset;
+    }
+
+    /**
+     * This method is used by other methods of this class. The behaviour of
+     * this method depends on the method which has been invoke this one. The
+     * argument methodId is used to choose valid behaviour in a particular case.
+     * If methodId is equal to 1 it means that this method has been invoked by
+     * the setDataElements() method, 2 - means setPixel(), and setSample() in
+     * any other cases.
+     * 
+     * @param x the x
+     * @param y the y
+     * @param obj the obj
+     * @param data the data
+     * @param methodId the method id
+     * @param s the s
+     */
+    private void setSample(final int x, final int y, final Object obj,
+            final DataBuffer data, final int methodId, int s) {
+        if ((x < 0) || (y < 0) || (x >= this.width) || (y >= this.height)) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages
+                    .getString("awt.63")); //$NON-NLS-1$
+        }
+
+        final int bitnum = dataBitOffset + x * pixelBitStride;
+        final int idx = y * scanlineStride + bitnum / dataElementSize;
+        final int shift = dataElementSize - (bitnum & (dataElementSize - 1))
+                - pixelBitStride;
+        final int mask = ~(bitMask << shift);
+        int elem = data.getElem(idx);
+
+        switch (methodId) {
+        case 1: {                        // Invoked from setDataElements()
+            switch (getTransferType()) {
+            case DataBuffer.TYPE_BYTE:
+                s = ((byte[]) obj)[0] & 0xff;
+                break;
+            case DataBuffer.TYPE_USHORT:
+                s = ((short[]) obj)[0] & 0xffff;
+                break;
+            case DataBuffer.TYPE_INT:
+                s = ((int[]) obj)[0];
+                break;
+            }
+            break;
+        }
+        case 2: {                        // Invoked from setPixel()
+            s = ((int[]) obj)[0];
+            break;
+        }
+        }
+
+        elem &= mask;
+        elem |= (s & bitMask) << shift;
+        data.setElem(idx, elem);
+    }
+}
+
diff --git a/awt/java/awt/image/PackedColorModel.java b/awt/java/awt/image/PackedColorModel.java
new file mode 100644
index 0000000..7aaefbf
--- /dev/null
+++ b/awt/java/awt/image/PackedColorModel.java
@@ -0,0 +1,383 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import java.awt.Transparency;
+import java.awt.color.ColorSpace;
+import java.util.Arrays;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Class PackedColorModel represents a color model where the 
+ * components are just the red, green, and blue bands, plus an alpha
+ * band if alpha is supported.
+ */
+public abstract class PackedColorModel extends ColorModel {
+
+    /** The component masks. */
+    int componentMasks[];
+
+    /** The offsets. */
+    int offsets[];
+
+    /** The scales. */
+    float scales[];
+
+    /**
+     * Instantiates a new packed color model.
+     * 
+     * @param space the color space
+     * @param bits the array of component masks
+     * @param colorMaskArray the array that gives the bitmask corresponding
+     * to each color band (red, green, and blue)
+     * @param alphaMask the bitmask corresponding to the alpha band
+     * @param isAlphaPremultiplied whether the alpha is premultiplied in this color model
+     * @param trans the transparency strategy, @see java.awt.Transparency
+     * @param transferType the transfer type (primitive java type 
+     * to use for the components)
+     * 
+     * @throws IllegalArgumentException if the number of bits in the combined 
+     * bitmasks for the color bands is less than one or greater than 32
+     */
+    public PackedColorModel(ColorSpace space, int bits, int colorMaskArray[],
+            int alphaMask, boolean isAlphaPremultiplied, int trans,
+            int transferType) {
+
+        super(bits, createBits(colorMaskArray, alphaMask), space,
+                (alphaMask == 0 ? false : true), isAlphaPremultiplied, trans,
+                validateTransferType(transferType));
+
+        if (pixel_bits < 1 || pixel_bits > 32) {
+            // awt.236=The bits is less than 1 or greater than 32
+            throw new IllegalArgumentException(Messages.getString("awt.236")); //$NON-NLS-1$
+        }
+
+        componentMasks = new int[numComponents];
+        for (int i = 0; i < numColorComponents; i++) {
+            componentMasks[i] = colorMaskArray[i];
+        }
+
+        if (hasAlpha) {
+            componentMasks[numColorComponents] = alphaMask;
+            if (this.bits[numColorComponents] == 1) {
+                transparency = Transparency.BITMASK;
+            }
+        }
+
+        parseComponents();
+    }
+
+    /**
+     * Instantiates a new packed color model.
+     * 
+     * @param space the color space
+     * @param bits the array of component masks
+     * @param rmask the bitmask corresponding to the red band
+     * @param gmask the bitmask corresponding to the green band
+     * @param bmask the bitmask corresponding to the blue band
+     * @param amask the bitmask corresponding to the alpha band
+     * @param isAlphaPremultiplied whether the alpha is premultiplied in this color model
+     * @param trans the transparency strategy, @see java.awt.Transparency
+     * @param transferType the transfer type (primitive java type 
+     * to use for the components)
+     * 
+     * @throws IllegalArgumentException if the number of bits in the combined 
+     * bitmasks for the color bands is less than one or greater than 32
+     */
+    public PackedColorModel(ColorSpace space, int bits, int rmask, int gmask,
+            int bmask, int amask, boolean isAlphaPremultiplied, int trans,
+            int transferType) {
+
+        super(bits, createBits(rmask, gmask, bmask, amask), space,
+                (amask == 0 ? false : true), isAlphaPremultiplied, trans,
+                validateTransferType(transferType));
+
+        if (pixel_bits < 1 || pixel_bits > 32) {
+            // awt.236=The bits is less than 1 or greater than 32
+            throw new IllegalArgumentException(Messages.getString("awt.236")); //$NON-NLS-1$
+        }
+
+        if (cs.getType() != ColorSpace.TYPE_RGB) {
+            // awt.239=The space is not a TYPE_RGB space
+            throw new IllegalArgumentException(Messages.getString("awt.239")); //$NON-NLS-1$
+        }
+
+        for (int i = 0; i < numColorComponents; i++) {
+            if (cs.getMinValue(i) != 0.0f || cs.getMaxValue(i) != 1.0f) {
+                // awt.23A=The min/max normalized component values are not 0.0/1.0
+                throw new IllegalArgumentException(Messages.getString("awt.23A")); //$NON-NLS-1$
+            }
+        }
+        componentMasks = new int[numComponents];
+        componentMasks[0] = rmask;
+        componentMasks[1] = gmask;
+        componentMasks[2] = bmask;
+
+        if (hasAlpha) {
+            componentMasks[3] = amask;
+            if (this.bits[3] == 1) {
+                transparency = Transparency.BITMASK;
+            }
+        }
+
+        parseComponents();
+    }
+
+    @Override
+    public WritableRaster getAlphaRaster(WritableRaster raster) {
+        if(!hasAlpha) {
+            return null;
+        }
+
+        int x = raster.getMinX();
+        int y = raster.getMinY();
+        int w = raster.getWidth();
+        int h = raster.getHeight();
+        int band[] = new int[1];
+        band[0] = raster.getNumBands() - 1;
+        return raster.createWritableChild(x, y, w, h, x, y, band);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (!(obj instanceof PackedColorModel)) {
+            return false;
+        }
+        PackedColorModel cm = (PackedColorModel) obj;
+
+        return (pixel_bits == cm.getPixelSize() &&
+                transferType == cm.getTransferType() &&
+                cs.getType() == cm.getColorSpace().getType() &&
+                hasAlpha == cm.hasAlpha() &&
+                isAlphaPremultiplied == cm.isAlphaPremultiplied() &&
+                transparency == cm.getTransparency() &&
+                numColorComponents == cm.getNumColorComponents()&&
+                numComponents == cm.getNumComponents() &&
+                Arrays.equals(bits, cm.getComponentSize()) &&
+                Arrays.equals(componentMasks, cm.getMasks()));
+    }
+
+    @Override
+    public boolean isCompatibleSampleModel(SampleModel sm) {
+        if (sm == null) {
+            return false;
+        }
+        if (!(sm instanceof SinglePixelPackedSampleModel)) {
+            return false;
+        }
+        SinglePixelPackedSampleModel esm = (SinglePixelPackedSampleModel) sm;
+
+        return ((esm.getNumBands() == numComponents) &&
+                (esm.getTransferType() == transferType) &&
+                Arrays.equals(esm.getBitMasks(), componentMasks));
+    }
+
+    @Override
+    public SampleModel createCompatibleSampleModel(int w, int h) {
+        return new SinglePixelPackedSampleModel(transferType, w, h,
+                componentMasks);
+    }
+
+    /**
+     * Gets the bitmask corresponding to the specified color component.
+     * 
+     * @param index the index of the desired color
+     * 
+     * @return the mask
+     */
+    public final int getMask(int index) {
+        return componentMasks[index];
+    }
+
+    /**
+     * Gets the bitmasks of the components.
+     * 
+     * @return the masks
+     */
+    public final int[] getMasks() {
+        return (componentMasks.clone());
+    }
+
+    /**
+     * Creates the bits.
+     * 
+     * @param colorMaskArray the color mask array
+     * @param alphaMask the alpha mask
+     * 
+     * @return the int[]
+     */
+    private static int[] createBits(int colorMaskArray[], int alphaMask) {
+        int bits[];
+        int numComp;
+        if (alphaMask == 0) {
+            numComp = colorMaskArray.length;
+        } else {
+            numComp = colorMaskArray.length + 1;
+        }
+
+        bits = new int[numComp];
+        int i = 0;
+        for (; i < colorMaskArray.length; i++) {
+            bits[i] = countCompBits(colorMaskArray[i]);
+            if (bits[i] < 0) {
+                // awt.23B=The mask of the {0} component is not contiguous
+                throw new IllegalArgumentException(Messages.getString("awt.23B", i)); //$NON-NLS-1$
+            }
+        }
+
+        if (i < numComp) {
+            bits[i] = countCompBits(alphaMask);
+
+            if (bits[i] < 0) {
+                // awt.23C=The mask of the alpha component is not contiguous
+                throw new IllegalArgumentException(Messages.getString("awt.23C")); //$NON-NLS-1$
+            }
+        }
+
+        return bits;
+    }
+
+    /**
+     * Creates the bits.
+     * 
+     * @param rmask the rmask
+     * @param gmask the gmask
+     * @param bmask the bmask
+     * @param amask the amask
+     * 
+     * @return the int[]
+     */
+    private static int[] createBits(int rmask, int gmask, int bmask,
+            int amask) {
+
+        int numComp;
+        if (amask == 0) {
+            numComp = 3;
+        } else {
+            numComp = 4;
+        }
+        int bits[] = new int[numComp];
+
+        bits[0] = countCompBits(rmask);
+        if (bits[0] < 0) {
+            // awt.23D=The mask of the red component is not contiguous
+            throw new IllegalArgumentException(Messages.getString("awt.23D")); //$NON-NLS-1$
+        }
+
+        bits[1] = countCompBits(gmask);
+        if (bits[1] < 0) {
+            // awt.23E=The mask of the green component is not contiguous
+            throw new IllegalArgumentException(Messages.getString("awt.23E")); //$NON-NLS-1$
+        }
+
+        bits[2] = countCompBits(bmask);
+        if (bits[2] < 0) {
+            // awt.23F=The mask of the blue component is not contiguous
+            throw new IllegalArgumentException(Messages.getString("awt.23F")); //$NON-NLS-1$
+        }
+
+        if (amask != 0) {
+            bits[3] = countCompBits(amask);
+            if (bits[3] < 0) {
+                // awt.23C=The mask of the alpha component is not contiguous
+                throw new IllegalArgumentException(Messages.getString("awt.23C")); //$NON-NLS-1$
+            }
+        }
+
+        return bits;
+    }
+
+    /**
+     * Count comp bits.
+     * 
+     * @param compMask the comp mask
+     * 
+     * @return the int
+     */
+    private static int countCompBits(int compMask) {
+        int bits = 0;
+        if (compMask != 0) {
+            // Deleting final zeros
+            while ((compMask & 1) == 0) {
+                compMask >>>= 1;
+            }
+            // Counting component bits
+            while ((compMask & 1) == 1) {
+                compMask >>>= 1;
+                bits++;
+            }
+        }
+
+        if (compMask != 0) {
+            return -1;
+        }
+
+        return bits;
+    }
+
+    /**
+     * Validate transfer type.
+     * 
+     * @param transferType the transfer type
+     * 
+     * @return the int
+     */
+    private static int validateTransferType(int transferType) {
+        if (transferType != DataBuffer.TYPE_BYTE &&
+                transferType != DataBuffer.TYPE_USHORT &&
+                transferType != DataBuffer.TYPE_INT) {
+            // awt.240=The transferType not is one of DataBuffer.TYPE_BYTE,
+            //          DataBuffer.TYPE_USHORT or DataBuffer.TYPE_INT
+            throw new IllegalArgumentException(Messages.getString("awt.240")); //$NON-NLS-1$
+        }
+        return transferType;
+}
+
+    /**
+     * Parses the components.
+     */
+    private void parseComponents() {
+        offsets = new int[numComponents];
+        scales = new float[numComponents];
+        for (int i = 0; i < numComponents; i++) {
+            int off = 0;
+            int mask = componentMasks[i];
+            while ((mask & 1) == 0) {
+                mask >>>= 1;
+                off++;
+            }
+            offsets[i] = off;
+            if (bits[i] == 0) {
+                scales[i] = 256.0f; // May be any value different from zero,
+                // because will dividing by zero
+            } else {
+                scales[i] = 255.0f / maxValues[i];
+            }
+        }
+
+    }
+
+}
+
diff --git a/awt/java/awt/image/PixelGrabber.java b/awt/java/awt/image/PixelGrabber.java
new file mode 100644
index 0000000..cecd5c8
--- /dev/null
+++ b/awt/java/awt/image/PixelGrabber.java
@@ -0,0 +1,408 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import java.awt.Image;
+import java.util.Hashtable;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+public class PixelGrabber implements ImageConsumer {
+
+    int width;
+    int height;
+    int X;
+    int Y;
+    int offset;
+    int scanline;
+    ImageProducer producer;
+
+    byte bData[];
+    int iData[];
+    ColorModel cm;
+
+    private int grabberStatus;
+    private int dataType;
+    private boolean isGrabbing;
+    private boolean isRGB;
+
+
+    private static final int DATA_TYPE_BYTE = 0;
+    private static final int DATA_TYPE_INT = 1;
+    private static final int DATA_TYPE_UNDEFINED = 2;
+
+    private static final int ALL_BITS = (ImageObserver.FRAMEBITS |
+            ImageObserver.ALLBITS);
+
+    private static final int GRABBING_STOP = ALL_BITS | ImageObserver.ERROR;
+
+
+
+    public PixelGrabber(ImageProducer ip, int x, int y, int w, int h, int[] pix,
+            int off, int scansize) {
+        initialize(ip, x, y, w, h, pix, off, scansize, true);
+    }
+
+    public PixelGrabber(Image img, int x, int y, int w, int h, int[] pix,
+            int off, int scansize) {
+        initialize(img.getSource(), x, y, w, h, pix, off, scansize, true);
+    }
+
+    public PixelGrabber(Image img, int x, int y, int w, int h, boolean forceRGB) {
+        initialize(img.getSource(), x, y, w, h, null, 0, 0, forceRGB);
+    }
+
+    public void setProperties(Hashtable<?, ?> props) {
+        return;
+    }
+
+    public synchronized Object getPixels() {
+        switch(dataType){
+        case DATA_TYPE_BYTE:
+            return bData;
+        case DATA_TYPE_INT:
+            return iData;
+        default:
+            return null;
+        }
+    }
+
+    public void setColorModel(ColorModel model) {
+        return;
+    }
+
+    public void setPixels(int srcX, int srcY, int srcW, int srcH,
+            ColorModel model, byte[] pixels, int srcOff, int srcScan) {
+        if(srcY < Y){
+            int delta = Y - srcY;
+            if(delta >= height) {
+                return;
+            }
+            srcY += delta;
+            srcH -= delta;
+            srcOff += srcScan * delta;
+        }
+
+        if(srcY + srcH > Y + height){
+            srcH = Y + height - srcY;
+            if(srcH <= 0) {
+                return;
+            }
+        }
+
+        if(srcX < X){
+            int delta = X - srcX;
+            if(delta >= width) {
+                return;
+            }
+            srcW -= delta;
+            srcX += delta;
+            srcOff += delta;
+        }
+
+        if(srcX + srcW > X + width){
+            srcW = X + width - srcX;
+            if(srcW <= 0) {
+                return;
+            }
+        }
+        if(scanline == 0) {
+            scanline = width;
+        }
+        int realOff = offset + (srcY - Y) * scanline + (srcX - X);
+        switch(dataType){
+        case DATA_TYPE_UNDEFINED:
+            cm = model;
+            if(model != ColorModel.getRGBdefault()){
+                bData = new byte[width * height];
+                isRGB = false;
+                dataType = DATA_TYPE_BYTE;
+            }else{
+                iData = new int[width * height];
+                isRGB = true;
+                dataType = DATA_TYPE_INT;
+            }
+        case DATA_TYPE_BYTE:
+            if(!isRGB && cm == model){
+                for(int y = 0; y < srcH; y++){
+                    System.arraycopy(pixels, srcOff, bData, realOff, srcW);
+                    srcOff += srcScan;
+                    realOff += scanline;
+                }
+                break;
+            }
+            forceToRGB();
+        case DATA_TYPE_INT:
+            for(int y = 0; y < srcH; y++){
+                for(int x = 0; x < srcW; x++){
+                    iData[realOff + x] = cm.getRGB(pixels[srcOff + x] & 0xff);                    
+                }
+                srcOff += srcScan;
+                realOff += scanline;
+            }
+        }
+
+        return;
+    }
+
+    public void setPixels(int srcX, int srcY, int srcW, int srcH,
+            ColorModel model, int[] pixels, int srcOff, int srcScan) {
+
+        if(srcY < Y){
+            int delta = Y - srcY;
+            if(delta >= height) {
+                return;
+            }
+            srcY += delta;
+            srcH -= delta;
+            srcOff += srcScan * delta;
+        }
+
+        if(srcY + srcH > Y + height){
+            srcH = Y + height - srcY;
+            if(srcH <= 0) {
+                return;
+            }
+        }
+
+        if(srcX < X){
+            int delta = X - srcX;
+            if(delta >= width) {
+                return;
+            }
+            srcW -= delta;
+            srcX += delta;
+            srcOff += delta;
+        }
+
+        if(srcX + srcW > X + width){
+            srcW = X + width - srcX;
+            if(srcW <= 0) {
+                return;
+            }
+        }
+        if(scanline == 0) {
+            scanline = width;
+        }
+        int realOff = offset + (srcY - Y) * scanline + (srcX - X);
+
+        int mask = 0xFF;
+
+        switch(dataType){
+        case DATA_TYPE_UNDEFINED:
+            cm = model;
+            iData = new int[width * height];
+            dataType = DATA_TYPE_INT;
+            isRGB = (cm == ColorModel.getRGBdefault());
+
+        case DATA_TYPE_INT:
+            if(cm == model){
+                for(int y = 0; y < srcH; y++){
+                    System.arraycopy(pixels, srcOff, iData, realOff, srcW);
+                    srcOff += srcScan;
+                    realOff += scanline;
+                }
+                break;
+            }
+            mask = 0xFFFFFFFF;
+
+        case DATA_TYPE_BYTE:
+            forceToRGB();
+            for(int y = 0; y < srcH; y++){
+                for(int x = 0; x < srcW; x++){
+                    iData[realOff+x] = cm.getRGB(pixels[srcOff+x] & mask);
+                }
+                srcOff += srcScan;
+                realOff += scanline;
+            }
+        }
+    }
+
+    public synchronized ColorModel getColorModel() {
+        return cm;
+    }
+
+    public synchronized boolean grabPixels(long ms) 
+    throws InterruptedException {
+        if((grabberStatus & GRABBING_STOP) != 0){
+            return ((grabberStatus & ALL_BITS) != 0);
+        }
+
+        long start = System.currentTimeMillis();
+
+        if(!isGrabbing){
+            isGrabbing = true;
+            grabberStatus &= ~ImageObserver.ABORT;
+            producer.startProduction(this);
+        }
+        while((grabberStatus & GRABBING_STOP) == 0){
+            if(ms != 0){
+                ms = start + ms - System.currentTimeMillis();
+                if(ms <= 0) {
+                    break;
+                }
+            }
+            wait(ms);
+        }
+
+        return ((grabberStatus & ALL_BITS) != 0);
+    }
+
+    public void setDimensions(int w, int h) {
+        if(width < 0) {
+            width = w - X;
+        }
+        if(height < 0) {
+            height = h - Y;
+        }
+
+        grabberStatus |= ImageObserver.WIDTH | ImageObserver.HEIGHT;
+
+        if(width <=0 || height <=0){
+            imageComplete(STATICIMAGEDONE);
+            return;
+        }
+
+        if(isRGB && dataType == DATA_TYPE_UNDEFINED){
+            iData = new int[width * height];
+            dataType = DATA_TYPE_INT;
+            scanline = width;
+        }
+    }
+
+    public void setHints(int hints) {
+        return;
+    }
+
+    public synchronized void imageComplete(int status) {
+        switch(status){
+        case IMAGEABORTED:
+            grabberStatus |= ImageObserver.ABORT;
+            break;
+        case IMAGEERROR:
+            grabberStatus |= ImageObserver.ERROR | ImageObserver.ABORT;
+            break;
+        case SINGLEFRAMEDONE:
+            grabberStatus |= ImageObserver.FRAMEBITS;
+            break;
+        case STATICIMAGEDONE:
+            grabberStatus |= ImageObserver.ALLBITS;
+            break;
+        default:
+            // awt.26A=Incorrect ImageConsumer completion status
+            throw new IllegalArgumentException(Messages.getString("awt.26A")); //$NON-NLS-1$
+        }
+        isGrabbing = false;
+        producer.removeConsumer(this);
+        notifyAll();
+    }
+
+    public boolean grabPixels() throws InterruptedException {
+        return grabPixels(0);
+    }
+
+    public synchronized void startGrabbing() {
+        if((grabberStatus & GRABBING_STOP) != 0){
+            return;
+        }
+        if(!isGrabbing){
+            isGrabbing = true;
+            grabberStatus &= ~ImageObserver.ABORT;
+            producer.startProduction(this);
+        }
+    }
+
+    public synchronized void abortGrabbing() {
+        imageComplete(IMAGEABORTED);
+    }
+
+    public synchronized int status() {
+        return grabberStatus;
+    }
+
+    public synchronized int getWidth() {
+        if(width < 0) {
+            return -1;
+        }
+        return width;
+    }
+
+    public synchronized int getStatus() {
+        return grabberStatus;
+    }
+
+    public synchronized int getHeight() {
+        if(height < 0) {
+            return -1;
+        }
+        return height;
+    }
+
+    private void initialize(ImageProducer ip, int x, int y, int w, int h,
+            int pixels[], int off, int scansize, boolean forceRGB){
+
+        producer = ip;
+        X = x;
+        Y = y;
+        width = w;
+        height = h;
+        iData = pixels;
+        dataType = (pixels == null) ? DATA_TYPE_UNDEFINED : DATA_TYPE_INT;
+        offset = off;
+        scanline = scansize;
+        if(forceRGB){
+            cm = ColorModel.getRGBdefault();
+            isRGB = true;
+        }
+    }
+
+    /**
+     * Force pixels to INT RGB mode
+     */
+    private void forceToRGB(){
+        if (isRGB)
+            return;
+    
+        switch(dataType){
+        case DATA_TYPE_BYTE:
+            iData = new int[width * height];
+            for(int i = 0; i < iData.length; i++){
+                iData[i] = cm.getRGB(bData[i] & 0xff);
+            }
+            dataType = DATA_TYPE_INT;
+            bData = null;
+            break;
+
+        case DATA_TYPE_INT:
+            int buff[] = new int[width * height];
+            for(int i = 0; i < iData.length; i++){
+                buff[i] = cm.getRGB(iData[i]);
+            }
+            iData = buff;
+            break;
+        }
+        offset = 0;
+        scanline = width;
+        cm = ColorModel.getRGBdefault();
+        isRGB = true;
+    }
+
+}
diff --git a/awt/java/awt/image/PixelInterleavedSampleModel.java b/awt/java/awt/image/PixelInterleavedSampleModel.java
new file mode 100644
index 0000000..e41473e
--- /dev/null
+++ b/awt/java/awt/image/PixelInterleavedSampleModel.java
@@ -0,0 +1,124 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The PixelInterleavedSampleModel class represents image data 
+ * as represented as interleaved pixels and for which each sample of 
+ * a pixel takes one data element of the DataBuffer.
+ */
+public class PixelInterleavedSampleModel extends ComponentSampleModel {
+
+    /**
+     * Instantiates a new PixelInterleavedSampleModel with the 
+     * specified parameters.
+     * 
+     * @param dataType the data type of the samples.
+     * @param w the width of the image data.
+     * @param h the height of the image data.
+     * @param pixelStride the pixel stride of the image data.
+     * @param scanlineStride the scanline stride of the of the image data.
+     * @param bandOffsets the array of the band offsets.
+     */
+    public PixelInterleavedSampleModel(int dataType, int w, int h,
+            int pixelStride, int scanlineStride, int bandOffsets[]) {
+
+        super(dataType, w, h, pixelStride, scanlineStride, bandOffsets);
+
+        int maxOffset = bandOffsets[0];
+        int minOffset = bandOffsets[0];
+        for (int i = 1; i < bandOffsets.length; i++) {
+            if (bandOffsets[i] > maxOffset) {
+                maxOffset = bandOffsets[i];
+            }
+            if (bandOffsets[i] < minOffset) {
+                minOffset = bandOffsets[i];
+            }
+        }
+
+        maxOffset -= minOffset;
+
+        if (maxOffset > scanlineStride) {
+            // awt.241=Any offset between bands is greater than the Scanline stride
+            throw new IllegalArgumentException(Messages.getString("awt.241")); //$NON-NLS-1$
+        }
+
+        if (maxOffset > pixelStride) {
+            // awt.242=Pixel stride is less than any offset between bands
+            throw new IllegalArgumentException(Messages.getString("awt.242")); //$NON-NLS-1$
+        }
+
+        if (pixelStride * w > scanlineStride) {
+            // awt.243=Product of Pixel stride and w is greater than Scanline stride
+            throw new IllegalArgumentException(Messages.getString("awt.243")); //$NON-NLS-1$
+        }
+
+    }
+
+    @Override
+    public SampleModel createSubsetSampleModel(int bands[]) {
+        int newOffsets[] = new int[bands.length];
+        for (int i = 0; i < bands.length; i++) {
+            newOffsets[i] = bandOffsets[bands[i]];
+        }
+
+        return new PixelInterleavedSampleModel(dataType, width, height,
+                pixelStride, scanlineStride, newOffsets);
+    }
+
+    @Override
+    public SampleModel createCompatibleSampleModel(int w, int h) {
+        int newOffsets[];
+        int minOffset = bandOffsets[0];
+
+        for (int i = 1; i < numBands; i++) {
+            if (bandOffsets[i] < minOffset) {
+                minOffset = bandOffsets[i];
+            }
+        }
+
+        if (minOffset > 0) {
+            newOffsets = new int[numBands];
+            for (int i = 0; i < numBands; i++) {
+                newOffsets[i] = bandOffsets[i] - minOffset;
+            }
+        } else {
+            newOffsets = bandOffsets;
+        }
+
+        return new PixelInterleavedSampleModel(dataType, w, h, pixelStride,
+                pixelStride * w, newOffsets);
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = super.hashCode();
+        int tmp = hash >>> 8;
+        hash <<= 8;
+        hash |= tmp;
+
+        return hash ^ 0x66;
+    }
+
+}
+
diff --git a/awt/java/awt/image/RGBImageFilter.java b/awt/java/awt/image/RGBImageFilter.java
new file mode 100644
index 0000000..9a76997
--- /dev/null
+++ b/awt/java/awt/image/RGBImageFilter.java
@@ -0,0 +1,190 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+
+/**
+ * The RGBImageFilter class represents a filter which modifies
+ * pixels of an image in the default RGB ColorModel. 
+ */
+public abstract class RGBImageFilter extends ImageFilter {
+
+    /** 
+     * The origmodel is the ColorModel to be replaced by newmodel 
+     * when substituteColorModel is called.
+     */
+    protected ColorModel origmodel;
+
+    /** 
+     * The newmodel is the ColorModel with which to replace origmodel 
+     * when substituteColorModel is called. 
+     */
+    protected ColorModel newmodel;
+
+    /** 
+     * The canFilterIndexColorModel indicates if it is 
+     * acceptable to apply the color filtering of the filterRGB 
+     * method to the color table entries of an IndexColorModel 
+     * object.
+     * */
+    protected boolean canFilterIndexColorModel;
+
+    /**
+     * Instantiates a new RGBImageFilter.
+     */
+    public RGBImageFilter() {}
+
+    /**
+     * Filters an IndexColorModel object by calling filterRGB function for
+     * each entry of IndexColorModel.
+     * 
+     * @param icm the IndexColorModel to be filtered.
+     * 
+     * @return the IndexColorModel.
+     */
+    public IndexColorModel filterIndexColorModel(IndexColorModel icm) {
+        int transferType = icm.getTransferType();
+        int bits = icm.getPixelSize();
+        int mapSize = icm.getMapSize();
+        int colorMap[] = new int[mapSize];
+        int filteredColorMap[] = new int[mapSize];
+        icm.getRGBs(colorMap);
+        int trans = -1;
+        boolean hasAlpha = false;
+        for(int i = 0; i < mapSize; i++){
+            filteredColorMap[i] = filterRGB(-1, -1, colorMap[i]);
+            int alpha = filteredColorMap[i] >>> 24;
+            if(alpha != 0xff){
+                if(!hasAlpha) {
+                    hasAlpha = true;
+                }
+                if(alpha == 0 && trans < 0) {
+                    trans = i;
+                }
+            }
+        }
+
+        return new IndexColorModel(bits, mapSize, filteredColorMap, 0,
+                hasAlpha, trans, transferType);
+    }
+
+    /**
+     * Replaces the original color model and the new one.
+     * 
+     * @param oldcm the old ColorModel.
+     * @param newcm the new ColorModel.
+     */
+    public void substituteColorModel(ColorModel oldcm, ColorModel newcm) {
+        origmodel = oldcm;
+        newmodel = newcm;
+    }
+
+    @Override
+    public void setColorModel(ColorModel model) {
+        if(model instanceof IndexColorModel &&
+                canFilterIndexColorModel){
+            IndexColorModel icm = (IndexColorModel) model;
+            ColorModel filteredModel = filterIndexColorModel(icm);
+            substituteColorModel(model, filteredModel);
+            consumer.setColorModel(filteredModel);
+        }else{
+            consumer.setColorModel(ColorModel.getRGBdefault());
+        }
+    }
+
+    @Override
+    public void setPixels(int x, int y, int w, int h, ColorModel model, 
+            int[] pixels, int off, int scansize) {
+        
+        if(model == null || model == origmodel){
+            consumer.setPixels(x, y, w, h, newmodel, pixels, off, scansize);
+        }else{
+            int rgbPixels[] = new int[w];
+            for(int sy = y, pixelsOff = off; sy < y + h; 
+                sy++, pixelsOff += scansize){
+                
+                for(int sx = x, idx = 0; sx < x + w; sx++, idx++){
+                    rgbPixels[idx] = model.getRGB(pixels[pixelsOff + idx]);
+                }
+                filterRGBPixels(x, sy, w, 1, rgbPixels, 0, w);
+            }
+        }
+    }
+
+    @Override
+    public void setPixels(int x, int y, int w, int h, ColorModel model, 
+            byte[] pixels, int off, int scansize) {
+        
+        if(model == null || model == origmodel){
+            consumer.setPixels(x, y, w, h, newmodel, pixels, off, scansize);
+        }else{
+            int rgbPixels[] = new int[w];
+            for(int sy = y, pixelsOff = off; sy < y + h; 
+                sy++, pixelsOff += scansize){
+                
+                for(int sx = x, idx = 0; sx < x + w; sx++, idx++){
+                    rgbPixels[idx] = 
+                        model.getRGB(pixels[pixelsOff + idx] & 0xff);
+                }
+                filterRGBPixels(x, sy, w, 1, rgbPixels, 0, w);
+            }
+        }
+    }
+
+    /**
+     * Filters a region of pixels in the default RGB ColorModel 
+     * by calling the filterRGB method for them.
+     * 
+     * @param x the X coordinate of region.
+     * @param y the Y coordinate of region.
+     * @param w the width ofregion.
+     * @param h the height of region.
+     * @param pixels the pixels array.
+     * @param off the offset of array.
+     * @param scansize the distance between rows of pixels in the array.
+     */
+    public void filterRGBPixels(int x, int y, int w, int h, 
+            int[] pixels, int off, int scansize) {
+        
+        for(int sy = y, lineOff = off; sy < y + h; sy++, lineOff += scansize){
+            for(int sx = x, idx = 0; sx < x + w; sx++, idx++){
+                pixels[lineOff + idx] = 
+                    filterRGB(sx, sy, pixels[lineOff + idx]);
+            }
+        }
+        consumer.setPixels(x, y, w, h, ColorModel.getRGBdefault(), 
+                pixels, off, scansize);
+    }
+
+    /**
+     * Coverts a single input pixel in the default RGB ColorModel 
+     * to a single output pixel.
+     * 
+     * @param x the X pixel's coordinate.
+     * @param y the Y pixel's coordinate.
+     * @param rgb a pixel in the default RGB color model.
+     * 
+     * @return a filtered pixel in the default RGB color model.
+     */
+    public abstract int filterRGB(int x, int y, int rgb);
+
+}
+
diff --git a/awt/java/awt/image/Raster.java b/awt/java/awt/image/Raster.java
new file mode 100644
index 0000000..4b2426e
--- /dev/null
+++ b/awt/java/awt/image/Raster.java
@@ -0,0 +1,1412 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import java.awt.Point;
+import java.awt.Rectangle;
+
+import org.apache.harmony.awt.gl.image.OrdinaryWritableRaster;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Raster class represents a rectangular area of pixels.
+ * This class is defined by DataBuffer and SampleModel objects. 
+ * The DataBuffer object stores sample values and DSampleModel defines 
+ * the location of sample in this DataBuffer. 
+ */
+public class Raster {
+
+    /** The DataBuffer of this Raster. */
+    protected DataBuffer dataBuffer;
+
+    /** The height of this Raster. */
+    protected int height;
+
+    /** The X coordinate of the upper left pixel in this Raster. */
+    protected int minX;
+
+    /** The Y coordinate of the upper left pixel in this Raster. */
+    protected int minY;
+
+    /** The number of bands in this Raster. */
+    protected int numBands;
+
+    /** The number of data elements. */
+    protected int numDataElements;
+
+    /** The parent of this Raster. */
+    protected Raster parent;
+
+    /** The SampleModel of this Raster. */
+    protected SampleModel sampleModel;
+
+    /** 
+     * The X translation from the coordinate space of the 
+     * SampleModel of this Raster.
+     */
+    protected int sampleModelTranslateX;
+
+    /** 
+     * The Y translation from the coordinate space of the 
+     * SampleModel of this Raster.
+     */
+    protected int sampleModelTranslateY;
+
+    /** The width of this Raster. */
+    protected int width;
+
+    /**
+     * Creates a Raster object with a BandedSampleModel and the specified 
+     * DataBuffer. The number of bands is defined by the length of bandOffsets
+     * or bankIndices arrays.
+     * 
+     * @param dataBuffer the specified DataBuffer.
+     * @param w the width of the image data.
+     * @param h the height of the image data. 
+     * @param bankIndices the bank indices of bands.
+     * @param bandOffsets the band offsets of bands.
+     * @param location the location which defines the upper left corner 
+     * of Raster.
+     * 
+     * @return the WritableRaster object.
+     */
+    public static WritableRaster createBandedRaster(DataBuffer dataBuffer,
+            int w, int h, int scanlineStride, int bankIndices[],
+            int bandOffsets[], Point location) {
+
+        if (w <= 0 || h <= 0) {
+            // awt.22E=w or h is less than or equal to zero
+            throw new RasterFormatException(Messages.getString("awt.22E")); //$NON-NLS-1$
+        }
+
+        if (location == null) {
+            location = new Point(0, 0);
+        }
+
+        if ((long) location.x + w > Integer.MAX_VALUE
+                || (long) location.y + h > Integer.MAX_VALUE) {
+            // awt.276=location.x + w or location.y + h results in integer overflow
+            throw new RasterFormatException(Messages.getString("awt.276")); //$NON-NLS-1$
+        }
+
+        if (bankIndices == null || bandOffsets == null) {
+            // awt.277=bankIndices or bandOffsets is null
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.277")); //$NON-NLS-1$
+        }
+
+        if (dataBuffer == null) {
+            // awt.278=dataBuffer is null
+            throw new NullPointerException(Messages.getString("awt.278")); //$NON-NLS-1$
+        }
+
+        int dataType = dataBuffer.getDataType();
+
+        if (dataType != DataBuffer.TYPE_BYTE
+                && dataType != DataBuffer.TYPE_USHORT
+                && dataType != DataBuffer.TYPE_INT) {
+            // awt.230=dataType is not one of the supported data types
+            throw new IllegalArgumentException(Messages.getString("awt.230")); //$NON-NLS-1$
+        }
+
+        BandedSampleModel sampleModel = new BandedSampleModel(dataType, w, h,
+                scanlineStride, bankIndices, bandOffsets);
+
+        return new OrdinaryWritableRaster(sampleModel, dataBuffer, location);
+    }
+
+    /**
+     * Creates a Raster object with a BandedSampleModel and the specified
+     * data type. The Data type can be one of the following values:
+     * TYPE_BYTE, TYPE_USHORT, or TYPE_INT. 
+     * 
+     * @param dataType the data type of the samples:
+     * TYPE_BYTE, TYPE_USHORT, or TYPE_INT. 
+     * @param w the width of the image data.
+     * @param h the height of the image data. 
+     * @param scanlineStride the scanline stride of the image data.
+     * @param bankIndices the bank indices of bands.
+     * @param bandOffsets the band offsets of bands.
+     * @param location the location which defines the upper left corner 
+     * of the Raster.
+     * 
+     * @return the WritableRaster object.
+     */
+    public static WritableRaster createBandedRaster(int dataType, int w, int h,
+            int scanlineStride, int bankIndices[], int bandOffsets[],
+            Point location) {
+
+        if (w <= 0 || h <= 0) {
+            // awt.22E=w or h is less than or equal to zero
+            throw new RasterFormatException(Messages.getString("awt.22E")); //$NON-NLS-1$
+        }
+
+        if (location == null) {
+            location = new Point(0, 0);
+        }
+
+        if ((long) location.x + w > Integer.MAX_VALUE
+                || (long) location.y + h > Integer.MAX_VALUE) {
+            // awt.276=location.x + w or location.y + h results in integer overflow
+            throw new RasterFormatException(Messages.getString("awt.276")); //$NON-NLS-1$
+        }
+
+        if (bankIndices == null || bandOffsets == null) {
+            // awt.277=bankIndices or bandOffsets is null
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.277")); //$NON-NLS-1$
+        }
+
+        if (dataType != DataBuffer.TYPE_BYTE
+                && dataType != DataBuffer.TYPE_USHORT
+                && dataType != DataBuffer.TYPE_INT) {
+            // awt.230=dataType is not one of the supported data types
+            throw new IllegalArgumentException(Messages.getString("awt.230")); //$NON-NLS-1$
+        }
+
+        int maxOffset = bandOffsets[0];
+        int maxBank = bankIndices[0];
+
+        for (int i = 0; i < bankIndices.length; i++) {
+            if (bandOffsets[i] > maxOffset) {
+                maxOffset = bandOffsets[i];
+            }
+            if (bankIndices[i] > maxBank) {
+                maxBank = bankIndices[i];
+            }
+        }
+
+        int numBanks = maxBank + 1;
+        int dataSize = scanlineStride * (h - 1) + w + maxOffset;
+
+        DataBuffer data = null;
+
+        switch (dataType) {
+        case DataBuffer.TYPE_BYTE:
+            data = new DataBufferByte(dataSize, numBanks);
+            break;
+        case DataBuffer.TYPE_USHORT:
+            data = new DataBufferUShort(dataSize, numBanks);
+            break;
+        case DataBuffer.TYPE_INT:
+            data = new DataBufferInt(dataSize, numBanks);
+            break;
+        }
+        return createBandedRaster(data, w, h, scanlineStride, bankIndices,
+                bandOffsets, location);
+    }
+
+    /**
+     * Creates a Raster object with a BandedSampleModel and the specified
+     * data type. The Data type can be one of the following values:
+     * TYPE_BYTE, TYPE_USHORT, or TYPE_INT. 
+     * 
+     * @param dataType the data type of the samples:
+     * TYPE_BYTE, TYPE_USHORT, or TYPE_INT. 
+     * @param w the width of the image data.
+     * @param h the height of the image data. 
+     * @param bands the number of bands.
+     * @param location the location which defines the upper left corner 
+     * of the Raster.
+     * 
+     * @return the WritableRaster object.
+     */
+    public static WritableRaster createBandedRaster(int dataType, int w, int h,
+            int bands, Point location) {
+
+        if (w <= 0 || h <= 0) {
+            // awt.22E=w or h is less than or equal to zero
+            throw new RasterFormatException(Messages.getString("awt.22E")); //$NON-NLS-1$
+        }
+
+        if (location == null) {
+            location = new Point(0, 0);
+        }
+
+        if ((long) location.x + w > Integer.MAX_VALUE
+                || (long) location.y + h > Integer.MAX_VALUE) {
+            // awt.276=location.x + w or location.y + h results in integer overflow
+            throw new RasterFormatException(Messages.getString("awt.276")); //$NON-NLS-1$
+        }
+
+        if (bands < 1) {
+            // awt.279=bands is less than 1
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.279")); //$NON-NLS-1$
+        }
+
+        int bandOffsets[] = new int[bands];
+        int bankIndices[] = new int[bands];
+
+        for (int i = 0; i < bands; i++) {
+            bandOffsets[i] = 0;
+            bankIndices[i] = i;
+        }
+        return createBandedRaster(dataType, w, h, w, bankIndices, bandOffsets,
+                location);
+    }
+
+    /**
+     * Creates a Raster object with a PixelInterleavedSampleModel 
+     * and the specified DataBuffer. 
+     * 
+     * @param dataBuffer the DataBuffer.
+     * @param w the width of image data.
+     * @param h the height of image data.
+     * @param scanlineStride the scanline stride of the image data.
+     * @param pixelStride the pixel stride of image data.
+     * @param bandOffsets the band offsets of bands.
+     * @param location the location which defines the upper left corner 
+     * of the Raster.
+     * 
+     * @return the WritableRaster object.
+     */
+    public static WritableRaster createInterleavedRaster(DataBuffer dataBuffer,
+            int w, int h, int scanlineStride, int pixelStride,
+            int bandOffsets[], Point location) {
+
+        if (w <= 0 || h <= 0) {
+            // awt.22E=w or h is less than or equal to zero
+            throw new RasterFormatException(Messages.getString("awt.22E")); //$NON-NLS-1$
+        }
+
+        if (location == null) {
+            location = new Point(0, 0);
+        }
+
+        if ((long) location.x + w > Integer.MAX_VALUE
+                || (long) location.y + h > Integer.MAX_VALUE) {
+            // awt.276=location.x + w or location.y + h results in integer overflow
+            throw new RasterFormatException(Messages.getString("awt.276")); //$NON-NLS-1$
+        }
+
+        if (dataBuffer == null) {
+            // awt.278=dataBuffer is null
+            throw new NullPointerException(Messages.getString("awt.278")); //$NON-NLS-1$
+        }
+
+        int dataType = dataBuffer.getDataType();
+        if (dataType != DataBuffer.TYPE_BYTE
+                && dataType != DataBuffer.TYPE_USHORT) {
+            // awt.230=dataType is not one of the supported data types
+            throw new IllegalArgumentException(Messages.getString("awt.230")); //$NON-NLS-1$
+        }
+
+        if (dataBuffer.getNumBanks() > 1) {
+            // awt.27A=dataBuffer has more than one bank
+            throw new RasterFormatException(Messages.getString("awt.27A")); //$NON-NLS-1$
+        }
+
+        if (bandOffsets == null) {
+            // awt.27B=bandOffsets is null
+            throw new NullPointerException(Messages.getString("awt.27B")); //$NON-NLS-1$
+        }
+
+        PixelInterleavedSampleModel sampleModel = 
+            new PixelInterleavedSampleModel(dataType, w, h, 
+                    pixelStride, scanlineStride, bandOffsets);
+
+        return new OrdinaryWritableRaster(sampleModel, dataBuffer, location);
+
+    }
+
+    /**
+     * Creates a Raster object with a PixelInterleavedSampleModel 
+     * and the specified data type. The Data type can be one of the 
+     * following values:
+     * TYPE_BYTE, TYPE_USHORT, or TYPE_INT. 
+     * 
+     * @param dataType the data type of the samples:
+     * TYPE_BYTE, TYPE_USHORT, or TYPE_INT. 
+     * @param w the width of image data.
+     * @param h the height of image data.
+     * @param scanlineStride the scanline stride of the image data.
+     * @param pixelStride the pixel stride of image data.
+     * @param bandOffsets the band offsets of bands.
+     * @param location the location which defines the upper left corner 
+     * of the Raster.
+     * 
+     * @return the WritableRaster object.
+     */
+    public static WritableRaster createInterleavedRaster(int dataType, int w,
+            int h, int scanlineStride, int pixelStride, int bandOffsets[],
+            Point location) {
+
+        if (w <= 0 || h <= 0) {
+            // awt.22E=w or h is less than or equal to zero
+            throw new RasterFormatException(Messages.getString("awt.22E")); //$NON-NLS-1$
+        }
+
+        if (location == null) {
+            location = new Point(0, 0);
+        }
+
+        if ((long) location.x + w > Integer.MAX_VALUE
+                || (long) location.y + h > Integer.MAX_VALUE) {
+            // awt.276=location.x + w or location.y + h results in integer overflow
+            throw new RasterFormatException(Messages.getString("awt.276")); //$NON-NLS-1$
+        }
+
+        if (dataType != DataBuffer.TYPE_BYTE
+                && dataType != DataBuffer.TYPE_USHORT) {
+            // awt.230=dataType is not one of the supported data types
+            throw new IllegalArgumentException(Messages.getString("awt.230")); //$NON-NLS-1$
+        }
+
+        if (bandOffsets == null) {
+            // awt.27B=bandOffsets is null
+            throw new NullPointerException(Messages.getString("awt.27B")); //$NON-NLS-1$
+        }
+
+        int minOffset = bandOffsets[0];
+        for (int i = 1; i < bandOffsets.length; i++) {
+            if (bandOffsets[i] < minOffset) {
+                minOffset = bandOffsets[i];
+            }
+        }
+        int size = (h - 1) * scanlineStride + w * pixelStride + minOffset;
+        DataBuffer data = null;
+
+        switch (dataType) {
+        case DataBuffer.TYPE_BYTE:
+            data = new DataBufferByte(size);
+            break;
+        case DataBuffer.TYPE_USHORT:
+            data = new DataBufferUShort(size);
+            break;
+        }
+
+        return createInterleavedRaster(data, w, h, scanlineStride, pixelStride,
+                bandOffsets, location);
+    }
+
+    /**
+     * Creates a Raster object with a PixelInterleavedSampleModel 
+     * and the specified data type. The Data type can be one of the 
+     * following values:
+     * TYPE_BYTE, TYPE_USHORT, or TYPE_INT. 
+     * 
+     * @param dataType the data type of samples:
+     * TYPE_BYTE, TYPE_USHORT, or TYPE_INT. 
+     * @param w the width of image data.
+     * @param h the height of image data.
+     * @param bands the number of bands.
+     * @param location the location which defines the upper left corner 
+     * of the Raster.
+     * 
+     * @return the WritableRaster.
+     */
+    public static WritableRaster createInterleavedRaster(int dataType, int w,
+            int h, int bands, Point location) {
+
+        if (w <= 0 || h <= 0) {
+            // awt.22E=w or h is less than or equal to zero
+            throw new RasterFormatException(Messages.getString("awt.22E")); //$NON-NLS-1$
+        }
+
+        if (location == null) {
+            location = new Point(0, 0);
+        }
+
+        if ((long) location.x + w > Integer.MAX_VALUE
+                || (long) location.y + h > Integer.MAX_VALUE) {
+            // awt.276=location.x + w or location.y + h results in integer overflow
+            throw new RasterFormatException(Messages.getString("awt.276")); //$NON-NLS-1$
+        }
+
+        if (dataType != DataBuffer.TYPE_BYTE
+                && dataType != DataBuffer.TYPE_USHORT) {
+            // awt.230=dataType is not one of the supported data types
+            throw new IllegalArgumentException(Messages.getString("awt.230")); //$NON-NLS-1$
+        }
+
+        int bandOffsets[] = new int[bands];
+        for (int i = 0; i < bands; i++) {
+            bandOffsets[i] = i;
+        }
+
+        return createInterleavedRaster(dataType, w, h, w * bands, bands,
+                bandOffsets, location);
+    }
+
+    /**
+     * Creates a Raster object with a SinglePixelPackedSampleModel  
+     * and the specified DataBuffer. 
+     * 
+     * @param dataBuffer the DataBuffer.
+     * @param w the width of the image data.
+     * @param h the height of the image data.
+     * @param scanlineStride the scanline stride of the image data.
+     * @param bandMasks the band masks.
+     * @param location the location which defines the upper left corner 
+     * of the Raster.
+     * 
+     * @return the WritableRaster.
+     */
+    public static WritableRaster createPackedRaster(DataBuffer dataBuffer,
+            int w, int h, int scanlineStride, int bandMasks[], Point location) {
+        if (dataBuffer == null) {
+            // awt.278=dataBuffer is null
+            throw new NullPointerException(Messages.getString("awt.278")); //$NON-NLS-1$
+        }
+
+        if (w <= 0 || h <= 0) {
+            // awt.22E=w or h is less than or equal to zero
+            throw new RasterFormatException(Messages.getString("awt.22E")); //$NON-NLS-1$
+        }
+
+        if (location == null) {
+            location = new Point(0, 0);
+        }
+
+        if ((long) location.x + w > Integer.MAX_VALUE
+                || (long) location.y + h > Integer.MAX_VALUE) {
+            // awt.276=location.x + w or location.y + h results in integer overflow
+            throw new RasterFormatException(Messages.getString("awt.276")); //$NON-NLS-1$
+        }
+
+        if (bandMasks == null) {
+            // awt.27C=bandMasks is null
+            throw new RasterFormatException(Messages.getString("awt.27C")); //$NON-NLS-1$
+        }
+
+        if (dataBuffer.getNumBanks() > 1) {
+            // awt.27A=dataBuffer has more than one bank
+            throw new RasterFormatException(Messages.getString("awt.27A")); //$NON-NLS-1$
+        }
+
+        int dataType = dataBuffer.getDataType();
+        if (dataType != DataBuffer.TYPE_BYTE
+                && dataType != DataBuffer.TYPE_USHORT
+                && dataType != DataBuffer.TYPE_INT) {
+            // awt.230=dataType is not one of the supported data types
+            throw new IllegalArgumentException(Messages.getString("awt.230")); //$NON-NLS-1$
+        }
+
+        SinglePixelPackedSampleModel sampleModel = 
+            new SinglePixelPackedSampleModel(dataType, w, h, 
+                    scanlineStride, bandMasks);
+
+        return new OrdinaryWritableRaster(sampleModel, dataBuffer, location);
+    }
+
+    /**
+     * Creates a Raster object with a MultiPixelPackedSampleModel   
+     * and the specified DataBuffer.
+     * 
+     * @param dataBuffer the DataBuffer.
+     * @param w the width of the image data.
+     * @param h the height of the image data.
+     * @param bitsPerPixel the number of bits per pixel.
+     * @param location the location which defines the upper left corner 
+     * of the Raster.
+     * 
+     * @return the WritableRaster.
+     */
+    public static WritableRaster createPackedRaster(DataBuffer dataBuffer,
+            int w, int h, int bitsPerPixel, Point location) {
+
+        if (w <= 0 || h <= 0) {
+            // awt.22E=w or h is less than or equal to zero
+            throw new RasterFormatException(Messages.getString("awt.22E")); //$NON-NLS-1$
+        }
+
+        if (location == null) {
+            location = new Point(0, 0);
+        }
+
+        if ((long) location.x + w > Integer.MAX_VALUE
+                || (long) location.y + h > Integer.MAX_VALUE) {
+            // awt.276=location.x + w or location.y + h results in integer overflow
+            throw new RasterFormatException(Messages.getString("awt.276")); //$NON-NLS-1$
+        }
+
+        if (dataBuffer == null) {
+            // awt.278=dataBuffer is null
+            throw new NullPointerException(Messages.getString("awt.278")); //$NON-NLS-1$
+        }
+
+        if (dataBuffer.getNumBanks() > 1) {
+            // awt.27A=dataBuffer has more than one bank
+            throw new RasterFormatException(Messages.getString("awt.27A")); //$NON-NLS-1$
+        }
+
+        int dataType = dataBuffer.getDataType();
+        if (dataType != DataBuffer.TYPE_BYTE
+                && dataType != DataBuffer.TYPE_USHORT
+                && dataType != DataBuffer.TYPE_INT) {
+            // awt.230=dataType is not one of the supported data types
+            throw new IllegalArgumentException(Messages.getString("awt.230")); //$NON-NLS-1$
+        }
+
+        MultiPixelPackedSampleModel sampleModel = 
+            new MultiPixelPackedSampleModel(dataType, w, h, bitsPerPixel);
+
+        return new OrdinaryWritableRaster(sampleModel, dataBuffer, location);
+
+    }
+
+    /**
+     * Creates a Raster object with a MultiPixelPackedSampleModel   
+     * and the specified DataBuffer.
+     * 
+     * @param dataType the data type of samples:
+     * TYPE_BYTE, TYPE_USHORT, or TYPE_INT. 
+     * @param w the width of the image data.
+     * @param h the height of the image data.
+     * @param bands the number of bands.
+     * @param bitsPerBand the number of bits per band.
+     * @param location the location which defines the upper left corner 
+     * of the Raster.
+     * 
+     * @return the WritableRaster.
+     */
+    public static WritableRaster createPackedRaster(int dataType, int w, int h,
+            int bands, int bitsPerBand, Point location) {
+
+        if (w <= 0 || h <= 0) {
+            // awt.22E=w or h is less than or equal to zero
+            throw new RasterFormatException(Messages.getString("awt.22E")); //$NON-NLS-1$
+        }
+
+        if (location == null) {
+            location = new Point(0, 0);
+        }
+
+        if ((long) location.x + w > Integer.MAX_VALUE
+                || (long) location.y + h > Integer.MAX_VALUE) {
+            // awt.276=location.x + w or location.y + h results in integer overflow
+            throw new RasterFormatException(Messages.getString("awt.276")); //$NON-NLS-1$
+        }
+
+        if (bands < 1 || bitsPerBand < 1) {
+            // awt.27D=bitsPerBand or bands is not greater than zero
+            throw new IllegalArgumentException(Messages.getString("awt.27D")); //$NON-NLS-1$
+        }
+
+        if (dataType != DataBuffer.TYPE_BYTE
+                && dataType != DataBuffer.TYPE_USHORT
+                && dataType != DataBuffer.TYPE_INT) {
+            // awt.230=dataType is not one of the supported data types
+            throw new IllegalArgumentException(Messages.getString("awt.230")); //$NON-NLS-1$
+        }
+
+        if (bitsPerBand * bands > DataBuffer.getDataTypeSize(dataType)) {
+            // awt.27E=The product of bitsPerBand and bands is greater than the number of bits held by dataType
+            throw new IllegalArgumentException(Messages.getString("awt.27E")); //$NON-NLS-1$
+        }
+
+        if (bands > 1) {
+
+            int bandMasks[] = new int[bands];
+            int mask = (1 << bitsPerBand) - 1;
+
+            for (int i = 0; i < bands; i++) {
+                bandMasks[i] = mask << (bitsPerBand * (bands - 1 - i));
+            }
+
+            return createPackedRaster(dataType, w, h, bandMasks, location);
+        }
+        DataBuffer data = null;
+        int size = ((bitsPerBand * w + 
+                DataBuffer.getDataTypeSize(dataType) - 1) / 
+                DataBuffer.getDataTypeSize(dataType)) * h;
+
+        switch (dataType) {
+        case DataBuffer.TYPE_BYTE:
+            data = new DataBufferByte(size);
+            break;
+        case DataBuffer.TYPE_USHORT:
+            data = new DataBufferUShort(size);
+            break;
+        case DataBuffer.TYPE_INT:
+            data = new DataBufferInt(size);
+            break;
+        }
+        return createPackedRaster(data, w, h, bitsPerBand, location);
+    }
+
+    /**
+     * Creates a Raster object with a SinglePixelPackedSampleModel    
+     * and the specified DataBuffer.
+     * 
+     * @param dataType the data type of samples:
+     * TYPE_BYTE, TYPE_USHORT, or TYPE_INT. 
+     * @param w the width of the image data.
+     * @param h the height of the image data.
+     * @param bandMasks the band masks.
+     * @param location the location which defines the upper left corner 
+     * of the Raster.
+     * 
+     * @return the WritableRaster.
+     */
+    public static WritableRaster createPackedRaster(int dataType, int w, int h,
+            int bandMasks[], Point location) {
+        
+        if (dataType != DataBuffer.TYPE_BYTE
+                && dataType != DataBuffer.TYPE_USHORT
+                && dataType != DataBuffer.TYPE_INT) {
+            // awt.230=dataType is not one of the supported data types
+            throw new IllegalArgumentException(Messages.getString("awt.230")); //$NON-NLS-1$
+        }
+
+        if (w <= 0 || h <= 0) {
+            // awt.22E=w or h is less than or equal to zero
+            throw new RasterFormatException(Messages.getString("awt.22E")); //$NON-NLS-1$
+        }
+
+        if (location == null) {
+            location = new Point(0, 0);
+        }
+
+        if ((long) location.x + w > Integer.MAX_VALUE
+                || (long) location.y + h > Integer.MAX_VALUE) {
+            // awt.276=location.x + w or location.y + h results in integer overflow
+            throw new RasterFormatException(Messages.getString("awt.276")); //$NON-NLS-1$
+        }
+
+        if (bandMasks == null) {
+            // awt.27C=bandMasks is null
+            throw new NullPointerException(Messages.getString("awt.27C")); //$NON-NLS-1$
+        }
+
+        DataBuffer data = null;
+
+        switch (dataType) {
+        case DataBuffer.TYPE_BYTE:
+            data = new DataBufferByte(w * h);
+            break;
+        case DataBuffer.TYPE_USHORT:
+            data = new DataBufferUShort(w * h);
+            break;
+        case DataBuffer.TYPE_INT:
+            data = new DataBufferInt(w * h);
+            break;
+        }
+
+        return createPackedRaster(data, w, h, w, bandMasks, location);
+    }
+
+    /**
+     * Creates a Raster object with the specified DataBuffer and SampleModel.
+     * 
+     * @param sm the specified SampleModel.
+     * @param db the specified DataBuffer.
+     * @param location the location which defines the upper left corner 
+     * of the Raster.
+     * 
+     * @return the Raster.
+     */
+    public static Raster createRaster(SampleModel sm, DataBuffer db,
+            Point location) {
+
+        if (sm == null || db == null) {
+            // awt.27F=SampleModel or DataBuffer is null
+            throw new NullPointerException(Messages.getString("awt.27F")); //$NON-NLS-1$
+        }
+
+        if (location == null) {
+            location = new Point(0, 0);
+        }
+
+        return new Raster(sm, db, location);
+    }
+
+    /**
+     * Creates a WritableRaster with the specified SampleModel and DataBuffer.
+     * 
+     * @param sm the specified SampleModel.
+     * @param db the specified DataBuffer.
+     * @param location the location which defines the upper left corner 
+     * of the Raster.
+     * 
+     * @return the WritableRaster.
+     */
+    public static WritableRaster createWritableRaster(SampleModel sm,
+            DataBuffer db, Point location) {
+
+        if (sm == null || db == null) {
+            // awt.27F=SampleModel or DataBuffer is null
+            throw new NullPointerException(Messages.getString("awt.27F")); //$NON-NLS-1$
+        }
+
+        if (location == null) {
+            location = new Point(0, 0);
+        }
+
+        return new OrdinaryWritableRaster(sm, db, location);
+    }
+
+    /**
+     * Creates a WritableRaster with the specified SampleModel.
+     * 
+     * @param sm the specified SampleModel.
+     * @param location the location which defines the upper left corner 
+     * of the Raster.
+     * 
+     * @return the WritableRaster.
+     */
+    public static WritableRaster createWritableRaster(SampleModel sm,
+            Point location) {
+
+        if (sm == null) {
+            // awt.280=SampleModel is null
+            throw new NullPointerException(Messages.getString("awt.280")); //$NON-NLS-1$
+        }
+
+        if (location == null) {
+            location = new Point(0, 0);
+        }
+
+        return createWritableRaster(sm, sm.createDataBuffer(), location);
+    }
+
+    /**
+     * Instantiates a new Raster object with the specified SampleModel and
+     * DataBuffer.
+     * 
+     * @param sampleModel the specified SampleModel.
+     * @param dataBuffer the specified  DataBuffer.
+     * @param origin the specified origin.
+     */
+    protected Raster(SampleModel sampleModel, DataBuffer dataBuffer,
+            Point origin) {
+
+        this(sampleModel, dataBuffer, new Rectangle(origin.x, origin.y,
+                sampleModel.getWidth(), sampleModel.getHeight()), origin, null);
+    }
+
+    /**
+     * Instantiates a new Raster object with the specified SampleModel,
+     * DataBuffer, rectangular region and parent Raster. 
+     * 
+     * @param sampleModel the specified SampleModel.
+     * @param dataBuffer the specified DataBuffer.
+     * @param aRegion the a rectangular region which defines the new image bounds. 
+     * @param sampleModelTranslate this point defines the translation point
+     * from the SampleModel coordinates to the new Raster coordinates.
+     * @param parent the parent of this Raster.
+     */
+    protected Raster(SampleModel sampleModel, DataBuffer dataBuffer,
+            Rectangle aRegion, Point sampleModelTranslate, Raster parent) {
+
+        if (sampleModel == null || dataBuffer == null || aRegion == null
+                || sampleModelTranslate == null) {
+            // awt.281=sampleModel, dataBuffer, aRegion or sampleModelTranslate is null
+            throw new NullPointerException(Messages.getString("awt.281")); //$NON-NLS-1$
+        }
+
+        if (aRegion.width <= 0 || aRegion.height <= 0) {
+            // awt.282=aRegion has width or height less than or equal to zero
+            throw new RasterFormatException(Messages.getString("awt.282")); //$NON-NLS-1$
+        }
+
+        if ((long) aRegion.x + (long) aRegion.width > Integer.MAX_VALUE) {
+            // awt.283=Overflow X coordinate of Raster
+            throw new RasterFormatException(Messages.getString("awt.283")); //$NON-NLS-1$
+        }
+
+        if ((long) aRegion.y + (long) aRegion.height > Integer.MAX_VALUE) {
+            // awt.284=Overflow Y coordinate of Raster
+            throw new RasterFormatException(Messages.getString("awt.284")); //$NON-NLS-1$
+        }
+        
+        if (sampleModel instanceof ComponentSampleModel) {
+            validateDataBuffer(dataBuffer, aRegion.width, aRegion.height,
+                    ((ComponentSampleModel) sampleModel).getScanlineStride());
+        } else if (sampleModel instanceof MultiPixelPackedSampleModel) {
+            validateDataBuffer(dataBuffer, aRegion.width, aRegion.height,
+                    ((MultiPixelPackedSampleModel) sampleModel)
+                            .getScanlineStride());
+        } else if (sampleModel instanceof SinglePixelPackedSampleModel) {
+            validateDataBuffer(dataBuffer, aRegion.width, aRegion.height,
+                    ((SinglePixelPackedSampleModel) sampleModel)
+                            .getScanlineStride());
+        }
+
+        this.sampleModel = sampleModel;
+        this.dataBuffer = dataBuffer;
+        this.minX = aRegion.x;
+        this.minY = aRegion.y;
+        this.width = aRegion.width;
+        this.height = aRegion.height;
+        this.sampleModelTranslateX = sampleModelTranslate.x;
+        this.sampleModelTranslateY = sampleModelTranslate.y;
+        this.parent = parent;
+        this.numBands = sampleModel.getNumBands();
+        this.numDataElements = sampleModel.getNumDataElements();
+
+    }
+
+    /**
+     * Instantiates a new Raster with the specified SampleModel.
+     * 
+     * @param sampleModel the specified SampleModel.
+     * @param origin the origin.
+     */
+    protected Raster(SampleModel sampleModel, Point origin) {
+        this(sampleModel, sampleModel.createDataBuffer(), new Rectangle(
+                origin.x, origin.y, sampleModel.getWidth(), sampleModel
+                        .getHeight()), origin, null);
+    }
+
+    /**
+     * Creates the child of this Raster by sharing the specified rectangular
+     * area in this Raste. The parentX, parentY, width 
+     * and height parameters specify the rectangular area to be shared.
+     * 
+     * @param parentX the X coordinate of the upper left corner of this Raster. 
+     * @param parentY the Y coordinate of the upper left corner of this Raster.
+     * @param width the width of the child area.
+     * @param height the height of the child area.
+     * @param childMinX the X coordinate of child area mapped to the parentX
+     * coordinate.
+     * @param childMinY the Y coordinate of child area mapped to the parentY
+     * coordinate.
+     * @param bandList the array of band indicies.
+     * 
+     * @return the Raster.
+     */
+    public Raster createChild(int parentX, int parentY, int width, int height,
+            int childMinX, int childMinY, int bandList[]) {
+        if (width <= 0 || height <= 0) {
+            // awt.285=Width or Height of child Raster is less than or equal to zero
+            throw new RasterFormatException(Messages.getString("awt.285")); //$NON-NLS-1$
+        }
+
+        if (parentX < this.minX || parentX + width > this.minX + this.width) {
+            // awt.286=parentX disposes outside Raster
+            throw new RasterFormatException(Messages.getString("awt.286")); //$NON-NLS-1$
+        }
+
+        if (parentY < this.minY || parentY + height > this.minY + this.height) {
+            // awt.287=parentY disposes outside Raster
+            throw new RasterFormatException(Messages.getString("awt.287")); //$NON-NLS-1$
+        }
+
+        if ((long) parentX + width > Integer.MAX_VALUE) {
+            // awt.288=parentX + width results in integer overflow
+            throw new RasterFormatException(Messages.getString("awt.288")); //$NON-NLS-1$
+        }
+
+        if ((long) parentY + height > Integer.MAX_VALUE) {
+            // awt.289=parentY + height results in integer overflow
+            throw new RasterFormatException(Messages.getString("awt.289")); //$NON-NLS-1$
+        }
+
+        if ((long) childMinX + width > Integer.MAX_VALUE) {
+            // awt.28A=childMinX + width results in integer overflow
+            throw new RasterFormatException(Messages.getString("awt.28A")); //$NON-NLS-1$
+        }
+
+        if ((long) childMinY + height > Integer.MAX_VALUE) {
+            // awt.28B=childMinY + height results in integer overflow
+            throw new RasterFormatException(Messages.getString("awt.28B")); //$NON-NLS-1$
+        }
+
+        SampleModel childModel;
+
+        if (bandList == null) {
+            childModel = sampleModel;
+        } else {
+            childModel = sampleModel.createSubsetSampleModel(bandList);
+        }
+
+        int childTranslateX = childMinX - parentX;
+        int childTranslateY = childMinY - parentY;
+
+        return new Raster(childModel, dataBuffer, new Rectangle(childMinX,
+                childMinY, width, height), new Point(childTranslateX
+                + sampleModelTranslateX, childTranslateY
+                + sampleModelTranslateY), this);
+    }
+
+    /**
+     * Create a compatible WritableRaster with the same parameters 
+     * as this Raster.
+     * 
+     * @return the WritableRaster.
+     */
+    public WritableRaster createCompatibleWritableRaster() {
+        return new OrdinaryWritableRaster(sampleModel, new Point(0, 0));
+    }
+
+    /**
+     * Create a compatible WritableRaster with the same parameters 
+     * as this Raster and the specified size.
+     * 
+     * @param w the width of the new WritableRaster.
+     * @param h the height of the new WritableRaster.
+     * 
+     * @return the WritableRaster.
+     */
+    public WritableRaster createCompatibleWritableRaster(int w, int h) {
+        if (w <= 0 || h <= 0) {
+            // awt.22E=w or h is less than or equal to zero
+            throw new RasterFormatException(Messages.getString("awt.22E")); //$NON-NLS-1$
+        }
+
+        SampleModel sm = sampleModel.createCompatibleSampleModel(w, h);
+
+        return new OrdinaryWritableRaster(sm, new Point(0, 0));
+    }
+
+    /**
+     * Create a compatible WritableRaster with the same parameters 
+     * as this Raster and the specified size and location.
+     * 
+     * @param x the X coordinate of the new WritableRaster.
+     * @param y the Y coordinate of the new WritableRaster.
+     * @param w the width of the new WritableRaster.
+     * @param h the height of the new WritableRaster.
+     * 
+     * @return the WritableRaster.
+     */
+    public WritableRaster createCompatibleWritableRaster(int x, int y, int w,
+            int h) {
+
+        WritableRaster raster = createCompatibleWritableRaster(w, h);
+
+        return raster.createWritableChild(0, 0, w, h, x, y, null);
+    }
+
+    /**
+     * Create a compatible WritableRaster with the same parameters 
+     * as this Raster and the specified rectangle which determines
+     * new WritableRaster's location and size.
+     * 
+     * @param rect the specified Rectangle.
+     * 
+     * @return the WritableRaster.
+     */
+    public WritableRaster createCompatibleWritableRaster(Rectangle rect) {
+        if (rect == null) {
+            // awt.28C=Rect is null
+            throw new NullPointerException(Messages.getString("awt.28C")); //$NON-NLS-1$
+        }
+
+        return createCompatibleWritableRaster(rect.x, rect.y, rect.width,
+                rect.height);
+    }
+
+    /**
+     * Creates the translated child of this Raster. The New Raster
+     * object is a reference to the this Raster with a 
+     * different location. 
+     *  
+     * @param childMinX the X coordinate of the new Raster.
+     * @param childMinY the Y coordinate of the new Raster.
+     * 
+     * @return the Raster.
+     */
+    public Raster createTranslatedChild(int childMinX, int childMinY) {
+        return createChild(minX, minY, width, height, childMinX, childMinY,
+                null);
+    }
+
+    /**
+     * Gets the bounds of this Raster as a rectangle.
+     * 
+     * @return the bounds of this Raster.
+     */
+    public Rectangle getBounds() {
+        return new Rectangle(minX, minY, width, height);
+    }
+
+    /**
+     * Gets the DataBuffer associated with this Raster.
+     * 
+     * @return the DataBuffer associated with this Raster.
+     */
+    public DataBuffer getDataBuffer() {
+        return dataBuffer;
+    }
+
+    /**
+     * Gets the data elements which represent the pixel data of the specified 
+     * rectangle area as a primitive array. The following image data types
+     * are supported: DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, 
+     * DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT, DataBuffer.TYPE_FLOAT, 
+     * or DataBuffer.TYPE_DOUBLE.
+     * 
+     * @param x the X coordinate of the area of pixels.
+     * @param y the Y coordinate of the area of pixels.
+     * @param w the width of the area of pixels.
+     * @param h the height of the area of pixels.
+     * @param outData the resulting array.
+     * 
+     * @return the data elements of the specified area of this Raster.
+     */
+    public Object getDataElements(int x, int y, int w, int h, Object outData) {
+        return sampleModel.getDataElements(x - sampleModelTranslateX, y
+                - sampleModelTranslateY, w, h, outData, dataBuffer);
+    }
+
+    /**
+     * Gets the data elements which represent the specified pixel of 
+     * this Raster as a primitive array. The following image data types
+     * are supported: DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, 
+     * DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT, DataBuffer.TYPE_FLOAT, 
+     * or DataBuffer.TYPE_DOUBLE.
+     * 
+     * @param x the X coordinate of the pixel.
+     * @param y the Y coordinate of the pixel.
+     * @param outData the resulting data.
+     * 
+     * @return the data elements of the specified pixel of this Raster.
+     */
+    public Object getDataElements(int x, int y, Object outData) {
+        return sampleModel.getDataElements(x - sampleModelTranslateX, y
+                - sampleModelTranslateY, outData, dataBuffer);
+    }
+
+    /**
+     * Gets the height of this Raster.
+     * 
+     * @return the height of this Raster.
+     */
+    public final int getHeight() {
+        return height;
+    }
+
+    /**
+     * Gets the minimum X coordinate of this Raster.
+     * 
+     * @return the minimum X coordinate of this Raster.
+     */
+    public final int getMinX() {
+        return minX;
+    }
+
+    /**
+     * Gets the minimum Y coordinate of this Raster.
+     * 
+     * @return the minimum Y coordinate of this Raster.
+     */
+    public final int getMinY() {
+        return minY;
+    }
+
+    /**
+     * Gets the number of bands in this Raster.
+     * 
+     * @return the number of bands in this Raster.
+     */
+    public final int getNumBands() {
+        return numBands;
+    }
+
+    /**
+     * Gets the number of data elements for one pixel.
+     * 
+     * @return the number of data elements for one pixel.
+     */
+    public final int getNumDataElements() {
+        return numDataElements;
+    }
+
+    /**
+     * Gets the parent Raster for this Raster object. 
+     * 
+     * @return the parent Raster for this Raster object.
+     */
+    public Raster getParent() {
+        return parent;
+    }
+
+    /**
+     * Gets a double array of samples for the specified pixel in this Raster. 
+     * 
+     * @param x the pixel's X coordinate.
+     * @param y the pixel's Y coordinate.
+     * @param dArray the double array where result array will be stored.
+     * 
+     * @return the double array of samples for the specified pixel in 
+     * this Raster.
+     */
+    public double[] getPixel(int x, int y, double dArray[]) {
+        return sampleModel.getPixel(x - sampleModelTranslateX, y
+                - sampleModelTranslateY, dArray, dataBuffer);
+    }
+
+    /**
+     * Gets a float array of samples for the specified pixel in this Raster. 
+     * 
+     * @param x the pixel's X coordinate.
+     * @param y the pixel's Y coordinate.
+     * @param fArray the float array where the result array will be stored.
+     * 
+     * @return the float array of samples for the specified pixel in 
+     * this Raster.
+     */
+    public float[] getPixel(int x, int y, float fArray[]) {
+        return sampleModel.getPixel(x - sampleModelTranslateX, y
+                - sampleModelTranslateY, fArray, dataBuffer);
+    }
+
+    /**
+     * Gets an int array of samples for the specified pixel in this Raster. 
+     * 
+     * @param x the pixel's X coordinate.
+     * @param y the pixel's Y coordinate.
+     * @param iArray the int array where the result array will be stored.
+     * 
+     * @return the int array of samples for the specified pixel in 
+     * this Raster.
+     */
+    public int[] getPixel(int x, int y, int iArray[]) {
+        return sampleModel.getPixel(x - sampleModelTranslateX, y
+                - sampleModelTranslateY, iArray, dataBuffer);
+    }
+
+    /**
+     * Gets an double array of samples for the specified rectangular
+     * area of pixels in this Raster.
+     * 
+     * @param x the X coordinate of the area of pixels.
+     * @param y the Y coordinate of the area of pixels.
+     * @param w the width of the area of pixels.
+     * @param h the height of the area of pixels.
+     * @param dArray the resulting array.
+     * 
+     * @return the double array of samples for the specified rectangular
+     * area of pixels in this Raster.
+     */
+    public double[] getPixels(int x, int y, int w, int h, double dArray[]) {
+        return sampleModel.getPixels(x - sampleModelTranslateX, y
+                - sampleModelTranslateY, w, h, dArray, dataBuffer);
+    }
+
+    /**
+     * Gets an float array of samples for the specified rectangular
+     * area of pixels in this Raster.
+     * 
+     * @param x the X coordinate of the area of pixels.
+     * @param y the Y coordinate of the area of pixels.
+     * @param w the width of the area of pixels.
+     * @param h the height of the area of pixels.
+     * @param fArray the resulting array.
+     * 
+     * @return the float array of samples for the specified rectangular
+     * area of pixels in this Raster.
+     */
+    public float[] getPixels(int x, int y, int w, int h, float fArray[]) {
+        return sampleModel.getPixels(x - sampleModelTranslateX, y
+                - sampleModelTranslateY, w, h, fArray, dataBuffer);
+    }
+
+    /**
+     * Gets an int array of samples for the specified rectangular
+     * area of pixels in this Raster.
+     * 
+     * @param x the X coordinate of the area of pixels.
+     * @param y the Y coordinate of the area of pixels.
+     * @param w the width of pixel's the area of pixels.
+     * @param h the height of pixel's the area of pixels.
+     * @param iArray the resulting array.
+     * 
+     * @return the int array of samples for the specified rectangular
+     * area of pixels in this Raster.
+     */
+    public int[] getPixels(int x, int y, int w, int h, int iArray[]) {
+        return sampleModel.getPixels(x - sampleModelTranslateX, y
+                - sampleModelTranslateY, w, h, iArray, dataBuffer);
+    }
+
+    /**
+     * Gets the sample for the specified band of the specified
+     * pixel as an int.
+     * 
+     * @param x the X coordinate of the pixel.
+     * @param y the Y coordinate of the pixel.
+     * @param b the band.
+     * 
+     * @return the sample for the specified band of the specified
+     * pixel as an int.
+     */
+    public int getSample(int x, int y, int b) {
+        return sampleModel.getSample(x - sampleModelTranslateX, y
+                - sampleModelTranslateY, b, dataBuffer);
+    }
+
+    /**
+     * Gets the sample for the specified band of the specified
+     * pixel as a double.
+     * 
+     * @param x the X coordinate of the pixel.
+     * @param y the Y coordinate of the pixel.
+     * @param b the band.
+     * 
+     * @return the sample for the specified band of the specified
+     * pixel as a double.
+     */
+    public double getSampleDouble(int x, int y, int b) {
+        return sampleModel.getSampleDouble(x - sampleModelTranslateX, y
+                - sampleModelTranslateY, b, dataBuffer);
+    }
+
+    /**
+     * Gets the sample for the specified band of the specified
+     * pixel as a float.
+     * 
+     * @param x the X coordinate of the pixel.
+     * @param y the Y coordinate of the pixel.
+     * @param b the band.
+     * 
+     * @return the sample for the specified band of the specified
+     * pixel as a float.
+     */
+    public float getSampleFloat(int x, int y, int b) {
+        return sampleModel.getSampleFloat(x - sampleModelTranslateX, y
+                - sampleModelTranslateY, b, dataBuffer);
+    }
+
+    /**
+     * Gets the SampleModel associated with this Raster.
+     * 
+     * @return the SampleModel associated with this Raster.
+     */
+    public SampleModel getSampleModel() {
+        return sampleModel;
+    }
+
+    /**
+     * Gets the translation of the X coordinate from the SampleModel
+     * coordinate system to the Rasters's coordinate system.
+     * 
+     * @return the value of the translation of the X coordinate from 
+     * the SampleModel coordinate system to the Rasters's 
+     * coordinate system.
+     */
+    public final int getSampleModelTranslateX() {
+        return sampleModelTranslateX;
+    }
+
+    /**
+     * Gets the translation of the Y coordinate from the SampleModel
+     * coordinate system to the Rasters's coordinate system.
+     * 
+     * @return the value of the translation of the Y coordinate from 
+     * the SampleModel coordinate system to the Rasters's 
+     * coordinate system.
+
+     */
+    public final int getSampleModelTranslateY() {
+        return sampleModelTranslateY;
+    }
+
+    /**
+     * Gets the double array of samples for the specified band 
+     * of the specified rectangular area of pixels in this Raster
+     * as a double array.
+     * 
+     * @param x the X coordinate of the rectangular area of pixels. 
+     * @param y the Y coordinate of the rectangular area of pixels.
+     * @param w the width of the rectangular area of pixels.
+     * @param h the height of the rectangular area of pixels.
+     * @param b the band.
+     * @param dArray the resulting double array.
+     * 
+     * @return the double array of samples for the specified band 
+     * of the specified rectangular area of pixels.
+     */
+    public double[] getSamples(int x, int y, int w, int h, int b,
+            double dArray[]) {
+
+        return sampleModel.getSamples(x - sampleModelTranslateX, y
+                - sampleModelTranslateY, w, h, b, dArray, dataBuffer);
+    }
+
+    /**
+     * Gets the float array of samples for the specified band 
+     * of the specified rectangular area of pixels in this Raster
+     * as a float array.
+     * 
+     * @param x the X coordinate of the rectangular area of pixels. 
+     * @param y the Y coordinate of the rectangular area of pixels.
+     * @param w the width of the rectangular area of pixels.
+     * @param h the height of the rectangular area of pixels.
+     * @param b the band.
+     * @param fArray the resulting float array.
+     * 
+     * @return the float array of samples for the specified band 
+     * of the specified rectangular area of pixels.
+     */
+    public float[] getSamples(int x, int y, int w, int h, int b, float fArray[]) {
+
+        return sampleModel.getSamples(x - sampleModelTranslateX, y
+                - sampleModelTranslateY, w, h, b, fArray, dataBuffer);
+    }
+
+    /**
+     * Gets the int array of samples for the specified band 
+     * of the specified rectangular area of pixels in this Raster
+     * as a int array.
+     * 
+     * @param x the X coordinate of the rectangular area of pixels. 
+     * @param y the Y coordinate of the rectangular area of pixels.
+     * @param w the width of the rectangular area of pixels.
+     * @param h the height of the rectangular area of pixels.
+     * @param b the band.
+     * @param iArray the resulting int array.
+     * 
+     * @return the int array of samples for the specified band 
+     * of the specified rectangular area of pixels.
+     */
+    public int[] getSamples(int x, int y, int w, int h, int b, int iArray[]) {
+        return sampleModel.getSamples(x - sampleModelTranslateX, y
+                - sampleModelTranslateY, w, h, b, iArray, dataBuffer);
+    }
+
+    /**
+     * Gets the transfer type for pixels of this Raster.
+     * @see SampleModel#getTransferType()
+     * 
+     * @return the transfer type for pixels of this Raster.
+     */
+    public final int getTransferType() {
+        return sampleModel.getTransferType();
+    }
+
+    /**
+     * Gets the width of this Raster.
+     * 
+     * @return the width of this Raster.
+     */
+    public final int getWidth() {
+        return width;
+    }
+
+    /**
+     * Validate data buffer.
+     * 
+     * @param dataBuffer the data buffer
+     * @param w the w
+     * @param h the h
+     * @param scanlineStride the scanline stride
+     */
+    private static void validateDataBuffer(final DataBuffer dataBuffer, final int w,
+            final int h, final int scanlineStride) {
+        if (dataBuffer.getSize() < (scanlineStride * (h - 1) + w - 1)) {
+            // awt.298=dataBuffer is too small
+            throw new RasterFormatException(Messages.getString("awt.298")); //$NON-NLS-1$
+        }
+    }
+}
+
+
diff --git a/awt/java/awt/image/RasterFormatException.java b/awt/java/awt/image/RasterFormatException.java
new file mode 100644
index 0000000..8577dad
--- /dev/null
+++ b/awt/java/awt/image/RasterFormatException.java
@@ -0,0 +1,45 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+
+/**
+ * The RasterFormatException class represents the exception 
+ * that is thrown when there's an invalid layout
+ * in the Raster.
+ */
+public class RasterFormatException extends RuntimeException {
+
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = 96598996116164315L;
+
+    /**
+     * Instantiates a new RasterFormatException with the 
+     * specified detail message.
+     * 
+     * @param s the detail message.
+     */
+    public RasterFormatException(String s) {
+        super(s);
+    }
+
+}
+
diff --git a/awt/java/awt/image/RasterOp.java b/awt/java/awt/image/RasterOp.java
new file mode 100644
index 0000000..e8933ee
--- /dev/null
+++ b/awt/java/awt/image/RasterOp.java
@@ -0,0 +1,83 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Alexey A. Petrenko
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import java.awt.RenderingHints;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * The RasterOp interface provides methods for performing transformations
+ * from source data to destination data for Raster objects. The source and 
+ * destination objects should contain the appropriate number of bands for 
+ * the particular classes which implement this interface.
+ */
+public interface RasterOp {
+    
+    /**
+     * Creates a destination WritableRaster with the specified Raster;
+     * this destination image data is empty and has the correct size 
+     * and number of bands.   
+     * 
+     * @param src the source Raster.
+     * 
+     * @return the WritableRaster.
+     */
+    public WritableRaster createCompatibleDestRaster(Raster src);
+
+    /**
+     * Performs a filter operation on the source Raster and stores the resulting
+     * image data to the destination WritableRaster.
+     * 
+     * @param src the source Raster.
+     * @param dst the destination WritableRaster, where the result is stored.
+     * 
+     * @return the filtered WritableRaster.
+     */
+    public WritableRaster filter(Raster src, WritableRaster dst);
+
+    /**
+     * Gets the bounds of the filtered Raster.
+     * 
+     * @param src the source Raster to be filtered.
+     * 
+     * @return the rectangle bounds of the filtered Raster.
+     */
+    public Rectangle2D getBounds2D(Raster src);
+
+    /**
+     * Gets the point of the destination image which corresponds
+     * to the specified point in the source raster.
+     * 
+     * @param srcPoint the point of the source raster.
+     * @param dstPoint the point where the result will be stored.
+     * 
+     * @return the destination point.
+     */
+    public Point2D getPoint2D(Point2D srcPoint, Point2D dstPoint);
+
+    /**
+     * Gets the RenderingHints of the RasterOp.
+     * 
+     * @return the RenderingHints of the RasterOp.
+     */
+    public RenderingHints getRenderingHints();
+}
diff --git a/awt/java/awt/image/RenderedImage.java b/awt/java/awt/image/RenderedImage.java
new file mode 100644
index 0000000..db3a4c8
--- /dev/null
+++ b/awt/java/awt/image/RenderedImage.java
@@ -0,0 +1,198 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import java.awt.Rectangle;
+import java.util.Vector;
+
+/**
+ * The RenderedImage interface should be implemented by all objects which 
+ * contains image data. The image data is represented as a single tile or 
+ * an array of tiles.
+ */
+public interface RenderedImage {
+
+    /**
+     * Gets the property with the specified name from the property set 
+     * of this RenderedImage.
+     * 
+     * @param name the property's name.
+     * 
+     * @return the property value corresponded to this property's name.
+     */
+    public Object getProperty(String name);
+
+    /**
+     * Copies the region of this RenderedImage to the specified 
+     * WritableRaster. The bounds of the region are the bounds of the 
+     * WritableRaster.
+     * 
+     * @param raster the WritableRaster.
+     * 
+     * @return the created WritableRaster.
+     */
+    public WritableRaster copyData(WritableRaster raster);
+
+    /**
+     * Gets the image data of the image's region as one tile.
+     * 
+     * @param rect the rectangular region of RenderedImage.
+     * 
+     * @return the image data of the image's region as one tile.
+     */
+    public Raster getData(Rectangle rect);
+
+    /**
+     * Gets all RenderedImage objects which are the source of this
+     * RenderedImage object.
+     * 
+     * @return a Vector of RenderedImage objects which are the source 
+     * of this RenderedImage object or null, if there is no information
+     * about them.
+     */
+    public Vector<RenderedImage> getSources();
+
+    /**
+     * Gets the set of all property names for this RenderedImage.
+     * 
+     * @return the array of all property names for this RenderedImage.
+     */
+    public String[] getPropertyNames();
+
+    /**
+     * Gets the SampleModel of this RenderedImage.
+     * 
+     * @return the SampleModel of this RenderedImage.
+     */
+    public SampleModel getSampleModel();
+
+    /**
+     * Gets the tile corresponded to the specified indices in the tile
+     * array.
+     * 
+     * @param tileX the X index of the tile.  
+     * @param tileY the Y index of the tile. 
+     * 
+     * @return the tile corresponded to the specified indices in the tile
+     * array.
+     */
+    public Raster getTile(int tileX, int tileY);
+
+    /**
+     * Gets the image data of this image as one tile.
+     * 
+     * @return the image data of this image as one tile.
+     */
+    public Raster getData();
+
+    /**
+     * Gets the ColorModel of this RenderedImage.
+     * 
+     * @return the ColorModel of this RenderedImage.
+     */
+    public ColorModel getColorModel();
+
+    /**
+     * Gets the width of the RenderedImage.
+     * 
+     * @return the width of the RenderedImage.
+     */
+    public int getWidth();
+
+    /**
+     * Gets the tile width.
+     * 
+     * @return the tile width in pixels.
+     */
+    public int getTileWidth();
+
+    /**
+     * Gets the tile height.
+     * 
+     * @return the tile height in pixels.
+     */
+    public int getTileHeight();
+
+    /**
+     * Gets the Y offset of the tile grid.
+     * 
+     * @return the Y offset of the tile grid.
+     */
+    public int getTileGridYOffset();
+
+    /**
+     * Gets the X offset of the tile grid.
+     * 
+     * @return the X offset of the tile grid.
+     */
+    public int getTileGridXOffset();
+
+    /**
+     * Gets the number of tiles along Y direction.
+     * 
+     * @return the number of tiles along Y direction.
+     */
+    public int getNumYTiles();
+
+    /**
+     * Gets the number of tiles along X direction.
+     * 
+     * @return the number of tiles along X direction.
+     */
+    public int getNumXTiles();
+
+    /**
+     * Gets the minimum Y coordinate of this RenderedImage.
+     * 
+     * @return the minimum Y coordinate of this RenderedImage.
+     */
+    public int getMinY();
+
+    /**
+     * Gets the minimum X coordinate of this RenderedImage.
+     * 
+     * @return the minimum X coordinate of this RenderedImage.
+     */
+    public int getMinX();
+
+    /**
+     * Gets the minimum tile's index along the Y direction.
+     * 
+     * @return the minimum tile's index along the Y direction.
+     */
+    public int getMinTileY();
+
+    /**
+     * Gets the minimum tile's index along the X direction.
+     * 
+     * @return the minimum tile's index along the X direction.
+     */
+    public int getMinTileX();
+
+    /**
+     * Gets the height of the RenderedImage.
+     * 
+     * @return the height of the RenderedImage.
+     */
+    public int getHeight();
+
+}
+
diff --git a/awt/java/awt/image/ReplicateScaleFilter.java b/awt/java/awt/image/ReplicateScaleFilter.java
new file mode 100644
index 0000000..9298125
--- /dev/null
+++ b/awt/java/awt/image/ReplicateScaleFilter.java
@@ -0,0 +1,213 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import java.util.Hashtable;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+
+/**
+ * The ReplicateScaleFilter class scales an source image 
+ * by replicating rows and columns of pixels to scale up or 
+ * omitting rows and columns of pixels to scale down.
+ */
+public class ReplicateScaleFilter extends ImageFilter {
+
+    /** The width of a source image. */
+    protected int srcWidth;
+
+    /** The height of a source image. */
+    protected int srcHeight;
+
+    /** The width of a destination image. */
+    protected int destWidth;
+
+    /** The height of a destination image. */
+    protected int destHeight;
+
+    /** The int array of source rows. */
+    protected int[] srcrows;
+
+    /** The int array of source columns. */
+    protected int[] srccols;
+
+    /** 
+     * An Object (byte array with a destination width) provides 
+     * a row of pixel data to the ImageConsumer. 
+     */
+    protected Object outpixbuf;
+
+    /**
+     * Instantiates a new ReplicateScaleFilter that filters 
+     * the image with the specified width and height.
+     * 
+     * @param width the width of scaled image.
+     * @param height the height of scaled image.
+     */
+    public ReplicateScaleFilter(int width, int height) {
+        if(width == 0 || height == 0) {
+            // awt.234=Width or Height equals zero
+            throw new IllegalArgumentException(Messages.getString("awt.234")); //$NON-NLS-1$
+        }
+
+        this.destWidth = width;
+        this.destHeight = height;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public void setProperties(Hashtable<?, ?> props) {
+        Hashtable<Object, Object> fprops;
+        if(props == null) {
+            fprops = new Hashtable<Object, Object>();
+        } else {
+            fprops = (Hashtable<Object, Object>) props.clone();
+        }
+        String propName = "Rescale Filters"; //$NON-NLS-1$
+        String prop = "destWidth=" + destWidth + "; " +  //$NON-NLS-1$ //$NON-NLS-2$
+        "destHeight=" + destHeight; //$NON-NLS-1$
+        Object o = fprops.get(propName);
+        if(o != null){
+            if(o instanceof String){
+                prop = (String)o + "; " + prop; //$NON-NLS-1$
+            }else{
+                prop =  o.toString() + "; " + prop; //$NON-NLS-1$
+            }
+        }
+        fprops.put(propName, prop);
+        consumer.setProperties(fprops);
+     }
+
+    // setPixels methods produce pixels according to Java API Spacification
+
+    @Override
+    public void setPixels(int x, int y, int w, int h, 
+            ColorModel model, int[] pixels, int off, int scansize) {
+        
+        if(srccols == null) {
+            initArrays();
+        }
+        int buff[];
+        if(outpixbuf == null || !(outpixbuf instanceof int[])){
+            buff = new int[destWidth];
+            outpixbuf = buff;
+        }else{
+            buff = (int[])outpixbuf;
+        }
+
+        int wa = (srcWidth - 1) >>> 1;
+        int ha = (srcHeight - 1) >>> 1;
+        int dstX = (x * destWidth + wa) / srcWidth;
+        int dstY = (y * destHeight + ha) / srcHeight;
+
+        int sx, sy, dx, dy;
+        dy = dstY;
+        while((dy < destHeight) && ((sy = srcrows[dy]) < y + h)){
+            dx = dstX;
+            int srcOff = off + (sy - y) * scansize;
+            while((dx < destWidth) && ((sx = srccols[dx]) < x + w)){
+                buff[dx] = pixels[srcOff + (sx - x)];
+                dx++;
+            }
+
+            consumer.setPixels(dstX, dy, dx - dstX, 1, model, buff, 
+                    dstX, destWidth);
+            dy++;
+        }
+    }
+
+    @Override
+    public void setPixels(int x, int y, int w, int h, 
+            ColorModel model, byte[] pixels, int off, int scansize) {
+        
+        if(srccols == null) {
+            initArrays();
+        }
+        byte buff[];
+        if(outpixbuf == null || !(outpixbuf instanceof byte[])){
+            buff = new byte[destWidth];
+            outpixbuf = buff;
+        }else{
+            buff = (byte[])outpixbuf;
+        }
+
+        int wa = (srcWidth - 1) >>> 1;
+        int ha = (srcHeight - 1) >>> 1;
+        int dstX = (x * destWidth + wa) / srcWidth;
+        int dstY = (y * destHeight + ha) / srcHeight;
+
+        int sx, sy, dx, dy;
+        dy = dstY;
+        while((dy < destHeight) && ((sy = srcrows[dy]) < y + h)){
+            dx = dstX;
+            int srcOff = off + (sy - y) * scansize;
+            while((dx < destWidth) && ((sx = srccols[dx]) < x + w)){
+                buff[dx] = pixels[srcOff + (sx - x)];
+                dx++;
+            }
+
+            consumer.setPixels(dstX, dy, dx - dstX, 1, model, buff, 
+                    dstX, destWidth);
+            dy++;
+        }
+    }
+
+    @Override
+    public void setDimensions(int w, int h) {
+        srcWidth = w;
+        srcHeight = h;
+
+        if(destWidth < 0 && destHeight < 0){
+            destWidth = srcWidth;
+            destHeight = srcHeight;
+        }else if(destWidth < 0){
+            destWidth = destHeight * srcWidth / srcHeight;
+        }else if(destHeight < 0){
+            destHeight = destWidth * srcHeight / srcWidth;
+        }
+        consumer.setDimensions(destWidth, destHeight);
+    }
+
+    /**
+     * Initialization of srccols and srcrows arrays.
+     */
+    private void initArrays(){
+        if ((destWidth < 0) || (destHeight < 0)) {
+            throw new IndexOutOfBoundsException();
+        }
+        
+        srccols = new int[destWidth];
+        int ca = srcWidth >>> 1;
+        for(int i = 0; i < destWidth; i++){
+            srccols[i] = (i * srcWidth + ca) / destWidth;
+        }
+
+        srcrows = new int[destHeight];
+        int ra = srcHeight >>> 1;
+        for(int i = 0; i < destHeight; i++){
+            srcrows[i] = (i * srcHeight + ra) / destHeight;
+        }
+    }
+
+}
+
+
diff --git a/awt/java/awt/image/RescaleOp.java b/awt/java/awt/image/RescaleOp.java
new file mode 100644
index 0000000..0e96031
--- /dev/null
+++ b/awt/java/awt/image/RescaleOp.java
@@ -0,0 +1,659 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ *
+ * @date: Oct 6, 2005
+ */
+
+package java.awt.image;
+
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.*;
+import java.util.Arrays;
+
+import org.apache.harmony.awt.gl.AwtImageBackdoorAccessor;
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Class RescaleOp performs rescaling of the source image data
+ * by multiplying the pixel values with a scale factor 
+ * and then adding an offset.
+ */
+public class RescaleOp implements BufferedImageOp, RasterOp {
+    
+    /** The scale factors. */
+    private float scaleFactors[];
+    
+    /** The offsets. */
+    private float offsets[];
+    
+    /** The hints. */
+    private RenderingHints hints;
+
+    static {
+        // TODO
+        //System.loadLibrary("imageops");
+    }
+
+    /**
+     * Instantiates a new RescaleOp object with the specified 
+     * scale factors and offsets.
+     * 
+     * @param scaleFactors the array of scale factor values.
+     * @param offsets the array of offset values.
+     * @param hints the RenderingHints or null.
+     */
+    public RescaleOp(float[] scaleFactors, float[] offsets, RenderingHints hints) {
+        int numFactors = Math.min(scaleFactors.length, offsets.length);
+
+        this.scaleFactors = new float[numFactors];
+        this.offsets = new float[numFactors];
+
+        System.arraycopy(scaleFactors, 0, this.scaleFactors, 0, numFactors);
+        System.arraycopy(offsets, 0, this.offsets, 0, numFactors);
+
+        this.hints = hints;
+    }
+
+    /**
+     * Instantiates a new RescaleOp object with the specified 
+     * scale factor and offset.
+     * 
+     * @param scaleFactor the scale factor.
+     * @param offset the offset.
+     * @param hints the RenderingHints or null.
+     */
+    public RescaleOp(float scaleFactor, float offset, RenderingHints hints) {
+        scaleFactors = new float[1];
+        offsets = new float[1];
+
+        scaleFactors[0] = scaleFactor;
+        offsets[0] = offset;
+
+        this.hints = hints;
+    }
+
+    /**
+     * Gets the number of scaling factors.
+     * 
+     * @return the number of scaling factors.
+     */
+    public final int getNumFactors() {
+        return scaleFactors.length;
+    }
+
+    public final RenderingHints getRenderingHints() {
+        return hints;
+    }
+
+    /**
+     * Gets the scale factors of this RescaleOp.
+     * 
+     * @param scaleFactors the desired scale factors array will be copied 
+     * to this array.
+     * 
+     * @return the scale factors array.
+     */
+    public final float[] getScaleFactors(float[] scaleFactors) {
+        if (scaleFactors == null) {
+            scaleFactors = new float[this.scaleFactors.length];
+        }
+
+        int minLength = Math.min(scaleFactors.length, this.scaleFactors.length);
+        System.arraycopy(this.scaleFactors, 0, scaleFactors, 0, minLength);
+        return scaleFactors;
+    }
+
+    /**
+     * Gets the offsets array of this RescaleOp.
+     * 
+     * @param offsets the desired offsets array will be copied to this array.
+     * 
+     * @return the offsets array of this RescaleOp.
+     */
+    public final float[] getOffsets(float[] offsets) {
+        if (offsets == null) {
+            offsets = new float[this.offsets.length];
+        }
+
+        int minLength = Math.min(offsets.length, this.offsets.length);
+        System.arraycopy(this.offsets, 0, offsets, 0, minLength);
+        return offsets;
+    }
+
+    public final Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
+        if (dstPt == null) {
+            dstPt = new Point2D.Float();
+        }
+
+        dstPt.setLocation(srcPt);
+        return dstPt;
+    }
+
+    public final Rectangle2D getBounds2D(Raster src) {
+        return src.getBounds();
+    }
+
+    public final Rectangle2D getBounds2D(BufferedImage src) {
+        return getBounds2D(src.getRaster());
+    }
+
+    public WritableRaster createCompatibleDestRaster(Raster src) {
+        return src.createCompatibleWritableRaster();
+    }
+
+    public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM) {
+        if (dstCM == null) {
+            dstCM = src.getColorModel();
+        }
+
+        if (dstCM instanceof IndexColorModel) {
+            dstCM = ColorModel.getRGBdefault();
+        }
+
+        WritableRaster r =
+                dstCM.isCompatibleSampleModel(src.getSampleModel()) ?
+                src.getRaster().createCompatibleWritableRaster(src.getWidth(), src.getHeight()) :
+                dstCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight());
+
+        return new BufferedImage(
+                dstCM,
+                r,
+                dstCM.isAlphaPremultiplied(),
+                null
+        );
+    }
+
+    public final WritableRaster filter(Raster src, WritableRaster dst) {
+        if (dst == null) {
+            dst = createCompatibleDestRaster(src);
+        } else {
+            if (src.getNumBands() != dst.getNumBands()) {
+                // awt.21D=Number of src bands ({0}) does not match number of dst bands ({1})
+                throw new IllegalArgumentException(Messages.getString("awt.21D", //$NON-NLS-1$
+                        src.getNumBands(), dst.getNumBands()));
+            }
+        }
+
+        if (
+                this.scaleFactors.length != 1 &&
+                this.scaleFactors.length != src.getNumBands()
+        ) {
+            // awt.21E=Number of scaling constants is not equal to the number of bands
+            throw new IllegalArgumentException(Messages.getString("awt.21E")); //$NON-NLS-1$
+        }
+
+        // TODO
+        //if (ippFilter(src, dst, BufferedImage.TYPE_CUSTOM, false) != 0)
+            if (slowFilter(src, dst, false) != 0) {
+                // awt.21F=Unable to transform source
+                throw new ImagingOpException (Messages.getString("awt.21F")); //$NON-NLS-1$
+            }
+
+        return dst;
+    }
+
+    /**
+     * Slow filter.
+     * 
+     * @param src the src
+     * @param dst the dst
+     * @param skipAlpha the skip alpha
+     * 
+     * @return the int
+     */
+    private final int slowFilter(Raster src, WritableRaster dst, boolean skipAlpha) {
+        SampleModel sm = src.getSampleModel();
+
+        int numBands = src.getNumBands();
+        int srcHeight = src.getHeight();
+        int srcWidth = src.getWidth();
+
+        int srcMinX = src.getMinX();
+        int srcMinY = src.getMinY();
+        int dstMinX = dst.getMinX();
+        int dstMinY = dst.getMinY();
+
+        int[] maxValues = new int[numBands];
+        int[] masks = new int[numBands];
+        int[] sampleSizes = sm.getSampleSize();
+
+        for (int i=0; i < numBands; i++){
+            maxValues[i] = (1 << sampleSizes[i]) - 1;
+            masks[i] = ~(maxValues[i]);
+        }
+
+        // Processing bounds
+        float[] pixels = null;
+        pixels = src.getPixels(srcMinX, srcMinY, srcWidth, srcHeight, pixels);
+
+        // Cycle over pixels to be calculated
+        if (skipAlpha) { // Always suppose that alpha channel is the last band
+            if (scaleFactors.length > 1) {
+                for (int i = 0; i < pixels.length; ){
+                    for (int bandIdx = 0; bandIdx < numBands-1; bandIdx++, i++){
+                        pixels[i] = pixels[i] * scaleFactors[bandIdx] + offsets[bandIdx];
+                        // Check for overflow now
+                        if (((int)pixels[i] & masks[bandIdx]) != 0) {
+                            if (pixels[i] < 0) {
+                                pixels[i] = 0;
+                            } else {
+                                pixels[i] = maxValues[bandIdx];
+                            }
+                        }
+                    }
+
+                    i++;
+                }
+            } else {
+                for (int i = 0; i < pixels.length; ){
+                    for (int bandIdx = 0; bandIdx < numBands-1; bandIdx++, i++){
+                        pixels[i] = pixels[i] * scaleFactors[0] + offsets[0];
+                        // Check for overflow now
+                        if (((int)pixels[i] & masks[bandIdx]) != 0) {
+                            if (pixels[i] < 0) {
+                                pixels[i] = 0;
+                            } else {
+                                pixels[i] = maxValues[bandIdx];
+                            }
+                        }
+                    }
+
+                    i++;
+                }
+            }
+        } else {
+            if (scaleFactors.length > 1) {
+                for (int i = 0; i < pixels.length; ){
+                    for (int bandIdx = 0; bandIdx < numBands; bandIdx++, i++){
+                        pixels[i] = pixels[i] * scaleFactors[bandIdx] + offsets[bandIdx];
+                        // Check for overflow now
+                        if (((int)pixels[i] & masks[bandIdx]) != 0) {
+                            if (pixels[i] < 0) {
+                                pixels[i] = 0;
+                            } else {
+                                pixels[i] = maxValues[bandIdx];
+                            }
+                        }
+                    }
+                }
+            } else {
+                for (int i = 0; i < pixels.length; ){
+                    for (int bandIdx = 0; bandIdx < numBands; bandIdx++, i++){
+                        pixels[i] = pixels[i] * scaleFactors[0] + offsets[0];
+                        // Check for overflow now
+                        if (((int)pixels[i] & masks[bandIdx]) != 0) {
+                            if (pixels[i] < 0) {
+                                pixels[i] = 0;
+                            } else {
+                                pixels[i] = maxValues[bandIdx];
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        dst.setPixels(dstMinX, dstMinY, srcWidth, srcHeight, pixels);
+
+        return 0;
+    }
+
+    public final BufferedImage filter(BufferedImage src, BufferedImage dst) {
+        ColorModel srcCM = src.getColorModel();
+
+        if (srcCM instanceof IndexColorModel) {
+            // awt.220=Source should not have IndexColorModel
+            throw new IllegalArgumentException(Messages.getString("awt.220")); //$NON-NLS-1$
+        }
+
+        // Check if the number of scaling factors matches the number of bands
+        int nComponents = srcCM.getNumComponents();
+        boolean skipAlpha;
+        if (srcCM.hasAlpha()) {
+            if (scaleFactors.length == 1 || scaleFactors.length == nComponents-1) {
+                skipAlpha = true;
+            } else if (scaleFactors.length == nComponents) {
+                skipAlpha = false;
+            } else {
+                // awt.21E=Number of scaling constants is not equal to the number of bands
+                throw new IllegalArgumentException(Messages.getString("awt.21E")); //$NON-NLS-1$
+            }
+        } else if (scaleFactors.length == 1 || scaleFactors.length == nComponents) {
+            skipAlpha = false;
+        } else {
+            // awt.21E=Number of scaling constants is not equal to the number of bands
+            throw new IllegalArgumentException(Messages.getString("awt.21E")); //$NON-NLS-1$
+        }
+
+        BufferedImage finalDst = null;
+        if (dst == null) {
+            finalDst = dst;
+            dst = createCompatibleDestImage(src, srcCM);
+        } else if (!srcCM.equals(dst.getColorModel())) {
+            // Treat BufferedImage.TYPE_INT_RGB and BufferedImage.TYPE_INT_ARGB as same
+            if (
+                    !((src.getType() == BufferedImage.TYPE_INT_RGB ||
+                       src.getType() == BufferedImage.TYPE_INT_ARGB) &&
+                      (dst.getType() == BufferedImage.TYPE_INT_RGB ||
+                       dst.getType() == BufferedImage.TYPE_INT_ARGB))
+            ) {
+                finalDst = dst;
+                dst = createCompatibleDestImage(src, srcCM);
+            }
+        }
+
+        // TODO
+        //if (ippFilter(src.getRaster(), dst.getRaster(), src.getType(), skipAlpha) != 0)
+            if (slowFilter(src.getRaster(), dst.getRaster(), skipAlpha) != 0) {
+                // awt.21F=Unable to transform source
+                throw new ImagingOpException (Messages.getString("awt.21F")); //$NON-NLS-1$
+            }
+
+        if (finalDst != null) {
+            Graphics2D g = finalDst.createGraphics();
+            g.setComposite(AlphaComposite.Src);
+            g.drawImage(dst, 0, 0, null);
+        } else {
+            finalDst = dst;
+        }
+
+        return finalDst;
+    }
+
+    // Don't forget to pass allocated arrays for levels and values, size should be numBands*4
+    /**
+     * Creates the levels.
+     * 
+     * @param sm the sm
+     * @param numBands the num bands
+     * @param skipAlpha the skip alpha
+     * @param levels the levels
+     * @param values the values
+     * @param channelsOrder the channels order
+     */
+    private final void createLevels(
+            SampleModel sm, int numBands, boolean skipAlpha,
+            int levels[], int values[], int channelsOrder[]
+    ) {
+        // Suppose same sample size for all channels, otherwise use slow filter
+        int maxValue = (1 << sm.getSampleSize(0)) - 1;
+
+        // For simplicity introduce these arrays
+        float extScaleFactors[] = new float[numBands];
+        float extOffsets[] = new float[numBands];
+
+        if (scaleFactors.length != 1) {
+            System.arraycopy(scaleFactors, 0, extScaleFactors, 0, scaleFactors.length);
+            System.arraycopy(offsets, 0, extOffsets, 0, scaleFactors.length);
+        } else {
+            for (int i = 0; i < numBands; i++) {
+                extScaleFactors[i] = scaleFactors[0];
+                extOffsets[i] = offsets[0];
+            }
+        }
+
+        if (skipAlpha) {
+            extScaleFactors[numBands-1] = 1;
+            extOffsets[numBands-1] = 0;
+        }
+
+        // Create a levels
+        for (int i=0; i<numBands; i++) {
+            if (extScaleFactors[i] == 0) {
+                levels[i*4] = 0;
+                levels[i*4+1] = 0;
+                levels[i*4+2] = maxValue+1;
+                levels[i*4+3] = maxValue+1;
+            }
+
+            float minLevel = -extOffsets[i] / extScaleFactors[i];
+            float maxLevel = (maxValue - extOffsets[i]) / extScaleFactors[i];
+
+            if (minLevel < 0) {
+                minLevel = 0;
+            } else if (minLevel > maxValue){
+                minLevel = maxValue;
+            }
+
+            if (maxLevel < 0) {
+                maxLevel = 0;
+            } else if (maxLevel > maxValue){
+                maxLevel = maxValue;
+            }
+
+            levels[i*4] = 0;
+            if (minLevel > maxLevel) {
+                levels[i*4+1] = (int) maxLevel;
+                levels[i*4+2] = (int) minLevel;
+            } else {
+                levels[i*4+1] = (int) minLevel;
+                levels[i*4+2] = (int) maxLevel;
+            }
+            levels[i*4+3] = maxValue+1;
+
+            // Fill values
+            for (int k=0; k<4; k++) {
+                int idx = i*4+k;
+                values[idx] = (int) (extScaleFactors[i] * levels[idx] + extOffsets[i]);
+                if (values[idx] < 0) {
+                    values[idx] = 0;
+                } else if (values[idx] > maxValue){
+                    values[idx] = maxValue;
+                }
+            }
+        }
+
+        // Reorder data if channels are stored in different order
+        if (channelsOrder != null) {
+            int len = numBands*4;
+            int savedLevels[] = new int[len];
+            int savedValues[] = new int[len];
+            System.arraycopy(levels, 0, savedLevels, 0, len);
+            System.arraycopy(values, 0, savedValues, 0, len);
+            for (int i = 0; i < channelsOrder.length; i++) {
+                System.arraycopy(savedLevels, i*4, levels, channelsOrder[i]*4, 4);
+                System.arraycopy(savedValues, i*4, values, channelsOrder[i]*4, 4);
+            }
+        }
+    }
+
+    // TODO remove when this method is used
+    /**
+     * Ipp filter.
+     * 
+     * @param src the src
+     * @param dst the dst
+     * @param imageType the image type
+     * @param skipAlpha the skip alpha
+     * 
+     * @return the int
+     */
+    @SuppressWarnings("unused")
+    private final int ippFilter(
+            Raster src, WritableRaster dst,
+            int imageType, boolean skipAlpha
+    ) {
+        int res;
+
+        int srcStride, dstStride;
+        int channels;
+        int offsets[] = null;
+        int channelsOrder[] = null;
+
+        switch (imageType) {
+            case BufferedImage.TYPE_INT_ARGB:
+            case BufferedImage.TYPE_INT_ARGB_PRE:
+            case BufferedImage.TYPE_INT_RGB: {
+                channels = 4;
+                srcStride = src.getWidth()*4;
+                dstStride = dst.getWidth()*4;
+                channelsOrder = new int[] {2, 1, 0, 3};
+                break;
+            }
+
+            case BufferedImage.TYPE_4BYTE_ABGR:
+            case BufferedImage.TYPE_4BYTE_ABGR_PRE:
+            case BufferedImage.TYPE_INT_BGR: {
+                channels = 4;
+                srcStride = src.getWidth()*4;
+                dstStride = dst.getWidth()*4;
+                break;
+            }
+
+            case BufferedImage.TYPE_BYTE_GRAY: {
+                channels = 1;
+                srcStride = src.getWidth();
+                dstStride = dst.getWidth();
+                break;
+            }
+
+            case BufferedImage.TYPE_3BYTE_BGR: {
+                channels = 3;
+                srcStride = src.getWidth()*3;
+                dstStride = dst.getWidth()*3;
+                channelsOrder = new int[] {2, 1, 0};
+                break;
+            }
+
+            case BufferedImage.TYPE_USHORT_GRAY:
+            case BufferedImage.TYPE_USHORT_565_RGB:
+            case BufferedImage.TYPE_USHORT_555_RGB:
+            case BufferedImage.TYPE_BYTE_BINARY: {
+                return slowFilter(src, dst, skipAlpha);
+            }
+
+            default: {
+                SampleModel srcSM = src.getSampleModel();
+                SampleModel dstSM = dst.getSampleModel();
+
+                if (
+                        srcSM instanceof PixelInterleavedSampleModel &&
+                        dstSM instanceof PixelInterleavedSampleModel
+                ) {
+                    // Check PixelInterleavedSampleModel
+                    if (
+                            srcSM.getDataType() != DataBuffer.TYPE_BYTE ||
+                            dstSM.getDataType() != DataBuffer.TYPE_BYTE
+                    ) {
+                        return slowFilter(src, dst, skipAlpha);
+                    }
+
+                    channels = srcSM.getNumBands(); // Have IPP functions for 1, 3 and 4 channels
+                    if (!(channels == 1 || channels == 3 || channels == 4)) {
+                        return slowFilter(src, dst, skipAlpha);
+                    }
+
+                    srcStride = ((ComponentSampleModel) srcSM).getScanlineStride();
+                    dstStride = ((ComponentSampleModel) dstSM).getScanlineStride();
+
+                    channelsOrder = ((ComponentSampleModel) srcSM).getBandOffsets();
+                } else if (
+                        srcSM instanceof SinglePixelPackedSampleModel &&
+                        dstSM instanceof SinglePixelPackedSampleModel
+                ) {
+                    // Check SinglePixelPackedSampleModel
+                    SinglePixelPackedSampleModel sppsm1 = (SinglePixelPackedSampleModel) srcSM;
+                    SinglePixelPackedSampleModel sppsm2 = (SinglePixelPackedSampleModel) dstSM;
+
+                    channels = sppsm1.getNumBands();
+
+                     // TYPE_INT_RGB, TYPE_INT_ARGB...
+                    if (
+                            sppsm1.getDataType() != DataBuffer.TYPE_INT ||
+                            sppsm2.getDataType() != DataBuffer.TYPE_INT ||
+                            !(channels == 3 || channels == 4)
+                    ) {
+                        return slowFilter(src, dst, skipAlpha);
+                    }
+
+                    // Check compatibility of sample models
+                    if (
+                            !Arrays.equals(sppsm1.getBitOffsets(), sppsm2.getBitOffsets()) ||
+                            !Arrays.equals(sppsm1.getBitMasks(), sppsm2.getBitMasks())
+                    ) {
+                        return slowFilter(src, dst, skipAlpha);
+                    }
+
+                    for (int i=0; i<channels; i++) {
+                        if (sppsm1.getSampleSize(i) != 8) {
+                            return slowFilter(src, dst, skipAlpha);
+                        }
+                    }
+
+                    channelsOrder = new int[channels];
+                    int bitOffsets[] = sppsm1.getBitOffsets();
+                    for (int i=0; i<channels; i++) {
+                        channelsOrder[i] = bitOffsets[i] / 8;
+                    }
+
+                    if (channels == 3) { // Don't skip channel now, could be optimized
+                        channels = 4;
+                    }
+
+                    srcStride = sppsm1.getScanlineStride() * 4;
+                    dstStride = sppsm2.getScanlineStride() * 4;
+                } else {
+                    return slowFilter(src, dst, skipAlpha);
+                }
+
+                // Fill offsets if there's a child raster
+                if (src.getParent() != null || dst.getParent() != null) {
+                    if (
+                            src.getSampleModelTranslateX() != 0 ||
+                            src.getSampleModelTranslateY() != 0 ||
+                            dst.getSampleModelTranslateX() != 0 ||
+                            dst.getSampleModelTranslateY() != 0
+                    ) {
+                        offsets = new int[4];
+                        offsets[0] = -src.getSampleModelTranslateX() + src.getMinX();
+                        offsets[1] = -src.getSampleModelTranslateY() + src.getMinY();
+                        offsets[2] = -dst.getSampleModelTranslateX() + dst.getMinX();
+                        offsets[3] = -dst.getSampleModelTranslateY() + dst.getMinY();
+                    }
+                }
+            }
+        }
+
+        int levels[] = new int[4*channels];
+        int values[] = new int[4*channels];
+
+        createLevels(src.getSampleModel(), channels, skipAlpha, levels, values, channelsOrder);
+
+        Object srcData, dstData;
+        AwtImageBackdoorAccessor dbAccess = AwtImageBackdoorAccessor.getInstance();
+        try {
+            srcData = dbAccess.getData(src.getDataBuffer());
+            dstData = dbAccess.getData(dst.getDataBuffer());
+        } catch (IllegalArgumentException e) {
+            return -1; // Unknown data buffer type
+        }
+
+        res = LookupOp.ippLUT(
+            srcData, src.getWidth(), src.getHeight(), srcStride,
+            dstData, dst.getWidth(), dst.getHeight(), dstStride,
+            levels, values,
+            channels, offsets,
+            true
+        );
+
+        return res;
+    }
+}
diff --git a/awt/java/awt/image/SampleModel.java b/awt/java/awt/image/SampleModel.java
new file mode 100644
index 0000000..44059a0
--- /dev/null
+++ b/awt/java/awt/image/SampleModel.java
@@ -0,0 +1,1053 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The SampleModel class is abstract class for retrieving pixel's samples
+ * in the data of an image. Each pixel contains several samples. A 
+ * sample is the set of values of the bands for single pixel. 
+ * For example, each pixel in the RGB model contains three samples 
+ * and there are three corresponding bands in the image 
+ * data of such pixels representing red, green and blue components.
+ * <p> 
+ * The image data is represented as a Raster with a DataBuffer 
+ * and a SampleModel. The SampleModel allows access to the samples in the 
+ * DataBuffer. 
+ */
+public abstract class SampleModel {
+
+    /** The width of the image data which this SampleModel describes. */
+    protected int width;
+
+    /** The height of the image data which this SampleModel describes. */
+    protected int height;
+
+    /** The number of bands of image data which this SampleModel describes. */
+    protected int numBands;
+
+    /** The data type of the image data which this SampleModel describes. */
+    protected int dataType;
+
+    /**
+     * Instantiates a new SampleModel with the specified data type,
+     * width, height and number of bands.
+     * 
+     * @param dataType the data type of the image data.
+     * @param w the width of the image data.
+     * @param h the height of the image data.
+     * @param numBands the number of bands of the image data.
+     */
+    public SampleModel(int dataType, int w, int h, int numBands) {
+        if (w <= 0 || h <= 0) {
+            // awt.22E=w or h is less than or equal to zero
+            throw new IllegalArgumentException(Messages.getString("awt.22E")); //$NON-NLS-1$
+        }
+
+        double squre = ((double) w) * ((double) h);
+        if (squre >= Integer.MAX_VALUE) {
+            // awt.22F=The product of w and h is greater than Integer.MAX_VALUE
+            throw new IllegalArgumentException(Messages.getString("awt.22F")); //$NON-NLS-1$
+        }
+
+        if (dataType < DataBuffer.TYPE_BYTE ||
+                dataType > DataBuffer.TYPE_DOUBLE &&
+                dataType != DataBuffer.TYPE_UNDEFINED) {
+            // awt.230=dataType is not one of the supported data types
+            throw new IllegalArgumentException(Messages.getString("awt.230")); //$NON-NLS-1$
+        }
+
+        if (numBands < 1) {
+            // awt.231=Number of bands must be more then 0
+            throw new IllegalArgumentException(Messages.getString("awt.231")); //$NON-NLS-1$
+        }
+
+        this.dataType = dataType;
+        this.width = w;
+        this.height = h;
+        this.numBands = numBands;
+
+    }
+
+    /**
+     * Gets the data array for the specified pixel of the specified 
+     * DataBuffer with one of the following types: 
+     * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, 
+     * DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT, 
+     * DataBuffer.TYPE_FLOAT, or DataBuffer.TYPE_DOUBLE.
+     * 
+     * @param x the X coordinate of pixel.
+     * @param y the Y coordinate of pixel.
+     * @param obj the Object is a data where the result will be stored.
+     * @param data the image data.
+     * 
+     * @return the data array for the specified pixel of the specified 
+     * DataBuffer.
+     */
+    public abstract Object getDataElements(int x, int y, Object obj,
+            DataBuffer data);
+
+    /**
+     * Gets the array of pixel data for the specified rectangular 
+     * area of pixels of the specified DataBuffer with one of 
+     * the following types: 
+     * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, 
+     * DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT, 
+     * DataBuffer.TYPE_FLOAT, or DataBuffer.TYPE_DOUBLE.
+     * 
+     * 
+     * @param x the X coordinate of the rectangular pixel area.
+     * @param y the Y coordinate of the rectangular pixel area.
+     * @param w the width of the rectangular pixel area.
+     * @param h the height of the rectangular pixel area.
+     * @param obj the Object is an array with the primitive type,
+     * where the result array will be stored.
+     * @param data the image data.
+     * 
+     * @return the array of pixel data for the specified rectangular 
+     * area of pixels of the specified DataBuffer object.
+     */
+    public Object getDataElements(int x, int y, int w, int h, Object obj,
+            DataBuffer data) {
+        int numDataElements = getNumDataElements();
+        int idx = 0;
+
+        switch (getTransferType()) {
+        case DataBuffer.TYPE_BYTE:
+            byte bdata[];
+            byte bbuf[] = null;
+
+            if (obj == null) {
+                bdata = new byte[numDataElements * w * h];
+            } else {
+                bdata = (byte[]) obj;
+            }
+
+            for (int i = y; i < y + h; i++) {
+                for (int j = x; j < x + w; j++) {
+                    bbuf = (byte[]) getDataElements(j, i, bbuf, data);
+                    for (int n = 0; n < numDataElements; n++) {
+                        bdata[idx++] = bbuf[n];
+                    }
+                }
+            }
+            obj = bdata;
+            break;
+
+        case DataBuffer.TYPE_SHORT:
+        case DataBuffer.TYPE_USHORT:
+            short sdata[];
+            short sbuf[] = null;
+
+            if (obj == null) {
+                sdata = new short[numDataElements * w * h];
+            } else {
+                sdata = (short[]) obj;
+            }
+
+            for (int i = y; i < y + h; i++) {
+                for (int j = x; j < x + w; j++) {
+                    sbuf = (short[]) getDataElements(j, i, sbuf, data);
+                    for (int n = 0; n < numDataElements; n++) {
+                        sdata[idx++] = sbuf[n];
+                    }
+                }
+            }
+            obj = sdata;
+            break;
+
+        case DataBuffer.TYPE_INT:
+            int idata[];
+            int ibuf[] = null;
+
+            if (obj == null) {
+                idata = new int[numDataElements * w * h];
+            } else {
+                idata = (int[]) obj;
+            }
+
+            for (int i = y; i < y + h; i++) {
+                for (int j = x; j < x + w; j++) {
+                    ibuf = (int[]) getDataElements(j, i, ibuf, data);
+                    for (int n = 0; n < numDataElements; n++) {
+                        idata[idx++] = ibuf[n];
+                    }
+                }
+            }
+            obj = idata;
+            break;
+
+        case DataBuffer.TYPE_FLOAT:
+            float fdata[];
+            float fbuf[] = null;
+
+            if (obj == null) {
+                fdata = new float[numDataElements * w * h];
+            } else {
+                fdata = (float[]) obj;
+            }
+
+            for (int i = y; i < y + h; i++) {
+                for (int j = x; j < x + w; j++) {
+                    fbuf = (float[]) getDataElements(j, i, fbuf, data);
+                    for (int n = 0; n < numDataElements; n++) {
+                        fdata[idx++] = fbuf[n];
+                    }
+                }
+            }
+            obj = fdata;
+            break;
+
+        case DataBuffer.TYPE_DOUBLE:
+            double ddata[];
+            double dbuf[] = null;
+
+            if (obj == null) {
+                ddata = new double[numDataElements * w * h];
+            } else {
+                ddata = (double[]) obj;
+            }
+
+            for (int i = y; i < y + h; i++) {
+                for (int j = x; j < x + w; j++) {
+                    dbuf = (double[]) getDataElements(j, i, dbuf, data);
+                    for (int n = 0; n < numDataElements; n++) {
+                        ddata[idx++] = dbuf[n];
+                    }
+                }
+            }
+            obj = ddata;
+            break;
+
+        }
+
+        return obj;
+    }
+
+    /**
+     * Sets the data for a single pixel in the specified DataBuffer
+     * from a primitive array with one of the following types: 
+     * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, 
+     * DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT, 
+     * DataBuffer.TYPE_FLOAT, or DataBuffer.TYPE_DOUBLE. 
+     * 
+     * @param x the X coordinate of pixel.
+     * @param y the Y coordinate of pixel.
+     * @param obj the Object - the array of primitive pixel data
+     * to be set. 
+     * @param data the image data.
+     */
+    public abstract void setDataElements(int x, int y, Object obj,
+            DataBuffer data);
+
+    /**
+     * Sets the data elements for a rectangular area of pixels in 
+     * the specified DataBuffer from a primitive array with one of 
+     * the following types: DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, 
+     * DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT, 
+     * DataBuffer.TYPE_FLOAT, or DataBuffer.TYPE_DOUBLE. 
+     * 
+     * @param x the X coordinate of the specified rectangular area.
+     * @param y the Y coordinate of the specified rectangular area.
+     * @param w the width of rectangle.
+     * @param h the height of rectangle.
+     * @param obj the Object - the array of primitive pixel data
+     * to be set. 
+     * @param data the image data.
+     */
+    public void setDataElements(int x, int y, int w, int h, Object obj,
+            DataBuffer data) {
+        int numDataElements = getNumDataElements();
+        int idx = 0;
+
+        switch (getTransferType()) {
+        case DataBuffer.TYPE_BYTE:
+            byte bbuf[] = new byte[numDataElements];
+            for (int i = y; i < y + h; i++) {
+                for (int j = x; j < x + w; j++) {
+                    for (int n = 0; n < numDataElements; n++) {
+                        bbuf[n] = ((byte[]) obj)[idx++];
+                    }
+                    setDataElements(j, i, bbuf, data);
+                }
+            }
+
+            break;
+
+        case DataBuffer.TYPE_SHORT:
+        case DataBuffer.TYPE_USHORT:
+            short sbuf[] = new short[numDataElements];
+            for (int i = y; i < y + h; i++) {
+                for (int j = x; j < x + w; j++) {
+                    for (int n = 0; n < numDataElements; n++) {
+                        sbuf[n] = ((short[]) obj)[idx++];
+                    }
+                    setDataElements(j, i, sbuf, data);
+                }
+            }
+            break;
+
+        case DataBuffer.TYPE_INT:
+            int ibuf[] = new int[numDataElements];
+            for (int i = y; i < y + h; i++) {
+                for (int j = x; j < x + w; j++) {
+                    for (int n = 0; n < numDataElements; n++) {
+                        ibuf[n] = ((int[]) obj)[idx++];
+                    }
+                    setDataElements(j, i, ibuf, data);
+                }
+            }
+            break;
+
+        case DataBuffer.TYPE_FLOAT:
+            float fbuf[] = new float[numDataElements];
+            for (int i = y; i < y + h; i++) {
+                for (int j = x; j < x + w; j++) {
+                    for (int n = 0; n < numDataElements; n++) {
+                        fbuf[n] = ((float[]) obj)[idx++];
+                    }
+                    setDataElements(j, i, fbuf, data);
+                }
+            }
+            break;
+
+        case DataBuffer.TYPE_DOUBLE:
+            double dbuf[] = new double[numDataElements];
+            for (int i = y; i < y + h; i++) {
+                for (int j = x; j < x + w; j++) {
+                    for (int n = 0; n < numDataElements; n++) {
+                        dbuf[n] = ((double[]) obj)[idx++];
+                    }
+                    setDataElements(j, i, dbuf, data);
+                }
+            }
+            break;
+
+        }
+    }
+
+    /**
+     * Creates a new SampleModel with the specified bands of 
+     * this SampleModel.
+     * 
+     * @param bands the array of bands from this SampleModel.
+     * 
+     * @return the SampleModel with the specified bands of 
+     * this SampleModel.
+     */
+    public abstract SampleModel createSubsetSampleModel(int bands[]);
+
+    /**
+     * Creates the SampleModel which has the same data as in 
+     * this SampleModel with a different width and height.
+     * 
+     * @param a0 the width of the image data.
+     * @param a1 the height of the image data.
+     * 
+     * @return the SampleModel which has the same data as in 
+     * this SampleModel with a different width and height.
+     */
+    public abstract SampleModel createCompatibleSampleModel(int a0, int a1);
+
+    /**
+     * Gets the samples of the specified pixel as a int array.
+     * 
+     * @param x the X coordinate of pixel.
+     * @param y the Y coordinate of pixel.
+     * @param iArray the int array where result will be stored.
+     * @param data the image data.
+     * 
+     * @return the int array with the samples of the specified pixel.
+
+     */
+    public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
+        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+        int pixel[];
+
+        if (iArray == null) {
+            pixel = new int[numBands];
+        } else {
+            pixel = iArray;
+        }
+
+        for (int i = 0; i < numBands; i++) {
+            pixel[i] = getSample(x, y, i, data);
+        }
+
+        return pixel;
+    }
+
+    /**
+     * Sets a pixel of the DataBuffer from a int array of samples. 
+     * 
+     * @param x the X coordinate of pixel.
+     * @param y the Y coordinate of pixel.
+     * @param iArray the int array.
+     * @param data the image data.
+     */
+    public void setPixel(int x, int y, int iArray[], DataBuffer data) {
+        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+        for (int i = 0; i < numBands; i++) {
+            setSample(x, y, i, iArray[i], data);
+        }
+    }
+
+    /**
+     * Gets the samples of the specified pixel as a float array.
+     * 
+     * @param x the X coordinate of pixel.
+     * @param y the Y coordinate of pixel.
+     * @param fArray the float array where result will be stored.
+     * @param data the image data.
+     * 
+     * @return the float array with the samples of the specified pixel.
+     */
+    public float[] getPixel(int x, int y, float fArray[], DataBuffer data) {
+        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+        float pixel[];
+
+        if (fArray == null) {
+            pixel = new float[numBands];
+        } else {
+            pixel = fArray;
+        }
+
+        for (int i = 0; i < numBands; i++) {
+            pixel[i] = getSampleFloat(x, y, i, data);
+        }
+
+        return pixel;
+    }
+
+    /**
+     * Sets a pixel of the DataBuffer from a float array of samples. 
+     * 
+     * @param x the X coordinate of pixel.
+     * @param y the Y coordinate of pixel.
+     * @param fArray the float array.
+     * @param data the image data.
+     */
+    public void setPixel(int x, int y, float fArray[], DataBuffer data) {
+        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+        for (int i = 0; i < numBands; i++) {
+            setSample(x, y, i, fArray[i], data);
+        }
+    }
+
+    /**
+     * Gets the samples of the specified pixel as a double array.
+     * 
+     * @param x the X coordinate of pixel.
+     * @param y the Y coordinate of pixel.
+     * @param dArray the double array where result will be stored.
+     * @param data the image data.
+     * 
+     * @return the double array with the samples of the specified pixel.
+     */
+    public double[] getPixel(int x, int y, double dArray[], DataBuffer data) {
+        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+        double pixel[];
+
+        if (dArray == null) {
+            pixel = new double[numBands];
+        } else {
+            pixel = dArray;
+        }
+
+        for (int i = 0; i < numBands; i++) {
+            pixel[i] = getSampleDouble(x, y, i, data);
+        }
+
+        return pixel;
+    }
+
+    /**
+     * Sets a pixel of the DataBuffer from a double array of samples. 
+     * 
+     * @param x the X coordinate of pixel.
+     * @param y the Y coordinate of pixel.
+     * @param dArray the double array.
+     * @param data the image data.
+     */
+    public void setPixel(int x, int y, double dArray[], DataBuffer data) {
+        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+        for (int i = 0; i < numBands; i++) {
+            setSample(x, y, i, dArray[i], data);
+        }
+    }
+
+    /**
+     * Gets the sample of a specified band for the specified pixel
+     * as an int.
+     * 
+     * @param x the X coordinate of pixel.
+     * @param y the Y coordinate of pixel.
+     * @param b the specified band.
+     * @param data the image data.
+     * 
+     * @return the sample of a specified band for the specified pixel.
+     */
+    public abstract int getSample(int x, int y, int b, DataBuffer data);
+
+    /**
+     * Gets the sample of a specified band for the specified pixel
+     * as a float.
+     * 
+     * @param x the X coordinate of pixel.
+     * @param y the Y coordinate of pixel.
+     * @param b the specified band.
+     * @param data the image data.
+     * 
+     * @return the sample of a specified band for the specified pixel.
+
+     */
+    public float getSampleFloat(int x, int y, int b, DataBuffer data) {
+        return getSample(x, y, b, data);
+    }
+
+    /**
+     * Gets the sample of a specified band for the specified pixel
+     * as a double.
+     * 
+     * @param x the X coordinate of pixel.
+     * @param y the Y coordinate of pixel.
+     * @param b the specified band.
+     * @param data the image data.
+     * 
+     * @return the sample of a specified band for the specified pixel.
+     */
+    public double getSampleDouble(int x, int y, int b, DataBuffer data) {
+        return getSample(x, y, b, data);
+    }
+
+    /**
+     * Gets the samples of the specified rectangular area of pixels
+     * as a int array.
+     * 
+     * @param x the X coordinate of the rectangle of pixels.
+     * @param y the Y coordinate of the rectangle of pixels.
+     * @param w the width of the rectangle of pixels.
+     * @param h the height of the rectangle of pixels.
+     * @param iArray the int array where result will be stored.
+     * @param data the image data.
+     * 
+     * @return the int array with the samples of the specified 
+     * rectangular area of pixels.
+     */
+    public int[] getPixels(int x, int y, int w, int h, int iArray[],
+            DataBuffer data) {
+        if (x < 0 || y < 0 || x + w > this.width || y + h > this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+        int pixels[];
+        int idx = 0;
+
+        if (iArray == null) {
+            pixels = new int[w * h * numBands];
+        } else {
+            pixels = iArray;
+        }
+
+        for (int i = y; i < y + h; i++) {
+            for (int j = x; j < x + w; j++) {
+                for (int n = 0; n < numBands; n++) {
+                    pixels[idx++] = getSample(j, i, n, data);
+                }
+            }
+        }
+        return pixels;
+    }
+
+    /**
+     * Sets all of the samples for a rectangular area of pixels of the DataBuffer
+     * from an int array. 
+     * 
+     * @param x the X coordinate of the rectangle of pixels.
+     * @param y the Y coordinate of the rectangle of pixels.
+     * @param w the width of the rectangle of pixels.
+     * @param h the height of the rectangle of pixels.
+     * @param iArray the int array.
+     * @param data the image data.
+     */
+    public void setPixels(int x, int y, int w, int h, int iArray[],
+            DataBuffer data) {
+        if (x < 0 || y < 0 || x + w > this.width || y + h > this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+        int idx = 0;
+        for (int i = y; i < y + h; i++) {
+            for (int j = x; j < x + w; j++) {
+                for (int n = 0; n < numBands; n++) {
+                    setSample(j, i, n, iArray[idx++], data);
+                }
+            }
+        }
+    }
+
+    /**
+     * Gets the samples of the specified rectangular area of pixels 
+     * as a float array.
+     * 
+     * @param x the X coordinate of the rectangle of pixels.
+     * @param y the Y coordinate of the rectangle of pixels.
+     * @param w the width of the rectangle of pixels.
+     * @param h the height of the rectangle of pixels.
+     * @param fArray the float array where result will be stored.
+     * @param data the image data.
+     * 
+     * @return the float array with the samples of the specified 
+     * rectangular area of pixels.
+     */
+    public float[] getPixels(int x, int y, int w, int h, float fArray[],
+            DataBuffer data) {
+        if (x < 0 || y < 0 || x + w > this.width || y + h > this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+        float pixels[];
+        int idx = 0;
+
+        if (fArray == null) {
+            pixels = new float[w * h * numBands];
+        } else {
+            pixels = fArray;
+        }
+
+        for (int i = y; i < y + h; i++) {
+            for (int j = x; j < x + w; j++) {
+                for (int n = 0; n < numBands; n++) {
+                    pixels[idx++] = getSampleFloat(j, i, n, data);
+                }
+            }
+        }
+        return pixels;
+    }
+
+    /**
+     * Sets all of the samples for a rectangular area of pixels of the DataBuffer
+     * from a float array. 
+     * 
+     * @param x the X coordinate of the rectangle of pixels.
+     * @param y the Y coordinate of the rectangle of pixels.
+     * @param w the width of the rectangle of pixels.
+     * @param h the height of the rectangle of pixels.
+     * @param fArray the float array.
+     * @param data the image data.
+     */
+    public void setPixels(int x, int y, int w, int h, float fArray[],
+            DataBuffer data) {
+        if (x < 0 || y < 0 || x + w > this.width || y + h > this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+        int idx = 0;
+        for (int i = y; i < y + h; i++) {
+            for (int j = x; j < x + w; j++) {
+                for (int n = 0; n < numBands; n++) {
+                    setSample(j, i, n, fArray[idx++], data);
+                }
+            }
+        }
+    }
+
+    /**
+     * Gets the samples of the specified rectangular area of pixels 
+     * as a double array.
+     * 
+     * @param x the X coordinate of the rectangle of pixels.
+     * @param y the Y coordinate of the rectangle of pixels.
+     * @param w the width of the rectangle of pixels.
+     * @param h the height of the rectangle of pixels.
+     * @param dArray the double array where result will be stored.
+     * @param data the image data.
+     * 
+     * @return the double array with the samples of the specified 
+     * rectangular area of pixels.
+     */
+    public double[] getPixels(int x, int y, int w, int h, double dArray[],
+            DataBuffer data) {
+        if (x < 0 || y < 0 || x + w > this.width || y + h > this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+        double pixels[];
+        int idx = 0;
+
+        if (dArray == null) {
+            pixels = new double[w * h * numBands];
+        } else {
+            pixels = dArray;
+        }
+
+        for (int i = y; i < y + h; i++) {
+            for (int j = x; j < x + w; j++) {
+                for (int n = 0; n < numBands; n++) {
+                    pixels[idx++] = getSampleDouble(j, i, n, data);
+                }
+            }
+        }
+        return pixels;
+    }
+
+    /**
+     * Sets all of the samples for a rectangular area of pixels of the DataBuffer
+     * from a double array. 
+     * 
+     * @param x the X coordinate of the rectangle of pixels.
+     * @param y the Y coordinate of the rectangle of pixels.
+     * @param w the width of the rectangle of pixels.
+     * @param h the height of the rectangle of pixels.
+     * @param dArray the double array.
+     * @param data the image data.
+     */
+    public void setPixels(int x, int y, int w, int h, double dArray[],
+            DataBuffer data) {
+        if (x < 0 || y < 0 || x + w > this.width || y + h > this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+        int idx = 0;
+        for (int i = y; i < y + h; i++) {
+            for (int j = x; j < x + w; j++) {
+                for (int n = 0; n < numBands; n++) {
+                    setSample(j, i, n, dArray[idx++], data);
+                }
+            }
+        }
+    }
+
+    /**
+     * Sets a sample of the specified band for the specified pixel
+     * in the DataBuffer as int value.
+     * 
+     * @param x the X coordinate of the pixel.
+     * @param y the Y coordinate of the pixel.
+     * @param b the specified band.
+     * @param s the sample as an int value.
+     * @param data the image data.
+     */
+    public abstract void setSample(int x, int y, int b, int s, DataBuffer data);
+
+    /**
+     * Gets the samples of a specified band for a specified rectangular
+     * area of pixels as a int array.
+     * 
+     * @param x the X coordinate of the rectangle.
+     * @param y the Y coordinate of the rectangle.
+     * @param w the width of the rectangle.
+     * @param h the height of the rectangle.
+     * @param b the specified band.
+     * @param iArray the int array where result will be stored.
+     * @param data the image data.
+     * 
+     * @return the samples of a specified band for a specified rectangular
+     * area of pixels.
+     */
+    public int[] getSamples(int x, int y, int w, int h, int b, int iArray[],
+            DataBuffer data) {
+        int samples[];
+        int idx = 0;
+
+        if (iArray == null) {
+            samples = new int[w * h];
+        } else {
+            samples = iArray;
+        }
+
+        for (int i = y; i < y + h; i++) {
+            for (int j = x; j < x + w; j++) {
+                samples[idx++] = getSample(j, i, b, data);
+            }
+        }
+
+        return samples;
+    }
+
+    /**
+     * Sets the samples from an int array in the specified band for 
+     * the specified rectangle of pixels.
+     * 
+     * @param x the X coordinate of the rectangle.
+     * @param y the Y coordinate of the rectangle.
+     * @param w the width of the rectangle.
+     * @param h the height of the rectangle.
+     * @param b the specified band.
+     * @param iArray the int array.
+     * @param data the image data.
+     */
+    public void setSamples(int x, int y, int w, int h, int b, int iArray[],
+            DataBuffer data) {
+        int idx = 0;
+        for (int i = y; i < y + h; i++) {
+            for (int j = x; j < x + w; j++) {
+                setSample(j, i, b, iArray[idx++], data);
+            }
+        }
+    }
+
+    /**
+     * Gets the samples of a specified band for a specified rectangular
+     * area of pixels as a float array.
+     * 
+     * @param x the X coordinate of the rectangle.
+     * @param y the Y coordinate of the rectangle.
+     * @param w the width of the rectangle.
+     * @param h the height of the rectangle.
+     * @param b the specified band.
+     * @param fArray the float array where result will be stored.
+     * @param data the image data.
+     * 
+     * @return the samples of a specified band for a specified rectangular
+     * area of pixels.
+     */
+    public float[] getSamples(int x, int y, int w, int h, int b,
+            float fArray[], DataBuffer data) {
+        float samples[];
+        int idx = 0;
+
+        if (fArray == null) {
+            samples = new float[w * h];
+        } else {
+            samples = fArray;
+        }
+
+        for (int i = y; i < y + h; i++) {
+            for (int j = x; j < x + w; j++) {
+                samples[idx++] = getSampleFloat(j, i, b, data);
+            }
+        }
+
+        return samples;
+    }
+
+    /**
+     * Sets the samples from an float array in the specified band for 
+     * the specified rectangle of pixels.
+     * 
+     * @param x the X coordinate of the rectangle.
+     * @param y the Y coordinate of the rectangle.
+     * @param w the width of the rectangle.
+     * @param h the height of the rectangle.
+     * @param b the specified band.
+     * @param fArray the float array
+     * @param data the image data.
+     */
+    public void setSamples(int x, int y, int w, int h, int b, float fArray[],
+            DataBuffer data) {
+        int idx = 0;
+        for (int i = y; i < y + h; i++) {
+            for (int j = x; j < x + w; j++) {
+                setSample(j, i, b, fArray[idx++], data);
+            }
+        }
+    }
+
+    /**
+     * Gets the samples of a specified band for a specified rectangular
+     * area of pixels as a double array.
+     * 
+     * @param x the X coordinate of the rectangle.
+     * @param y the Y coordinate of the rectangle.
+     * @param w the width of the rectangle.
+     * @param h the height of the rectangle.
+     * @param b the specified band.
+     * @param dArray the double array where result will be stored.
+     * @param data the image data.
+     * 
+     * @return the samples of a specified band for a specified rectangular
+     * area of pixels.
+     */
+    public double[] getSamples(int x, int y, int w, int h, int b,
+            double dArray[], DataBuffer data) {
+        double samples[];
+        int idx = 0;
+
+        if (dArray == null) {
+            samples = new double[w * h];
+        } else {
+            samples = dArray;
+        }
+
+        for (int i = y; i < y + h; i++) {
+            for (int j = x; j < x + w; j++) {
+                samples[idx++] = getSampleDouble(j, i, b, data);
+            }
+        }
+
+        return samples;
+    }
+
+    /**
+     * Sets the samples from an double array in the specified band for 
+     * the specified rectangle of pixels.
+     * 
+     * @param x the X coordinate of the rectangle.
+     * @param y the Y coordinate of the rectangle.
+     * @param w the width of the rectangle.
+     * @param h the height of the rectangle.
+     * @param b the specified band.
+     * @param dArray the double array
+     * @param data the image data.
+     */
+    public void setSamples(int x, int y, int w, int h, int b, double dArray[],
+            DataBuffer data) {
+        int idx = 0;
+        for (int i = y; i < y + h; i++) {
+            for (int j = x; j < x + w; j++) {
+                setSample(j, i, b, dArray[idx++], data);
+            }
+        }
+    }
+
+    /**
+     * Sets a sample of the specified band for the specified pixel
+     * in the DataBuffer as float value.
+     * 
+     * @param x the X coordinate of the pixel.
+     * @param y the Y coordinate of the pixel.
+     * @param b the specified band.
+     * @param s the sample as float value.
+     * @param data the image data.
+     */
+    public void setSample(int x, int y, int b, float s, DataBuffer data) {
+        setSample(x, y, b, (int) s, data);
+    }
+
+    /**
+     * Sets a sample of the specified band for the specified pixel
+     * in the DataBuffer as double value.
+     * 
+     * @param x the X coordinate of the pixel.
+     * @param y the Y coordinate of the pixel.
+     * @param b the specified band.
+     * @param s the sample as double value.
+     * @param data the image data.
+     */
+    public void setSample(int x, int y, int b, double s, DataBuffer data) {
+        setSample(x, y, b, (int) s, data);
+    }
+
+    /**
+     * Creates a DataBuffer object which corresponds to the SampleModel. 
+     *  
+     * @return the DataBuffer object which corresponds to 
+     * the SampleModel.
+     */
+    public abstract DataBuffer createDataBuffer();
+
+    /**
+     * Gets the sample size in bits for the specified band.
+     * 
+     * @param band the specified band.
+     * 
+     * @return the sample size in bits for the specified band.
+     */
+    public abstract int getSampleSize(int band);
+
+    /**
+     * Gets an array of the sample size in bits for all bands.
+     *  
+     * @return an array of the sample size in bits for all bands.
+     */
+    public abstract int[] getSampleSize();
+
+    /**
+     * Gets the width of the image data of this SampleModel object.
+     * 
+     * @return the width of the image data of this SampleModel object.
+     */
+    public final int getWidth() {
+        return width;
+    }
+
+    /**
+     * Gets the transfer type used to transfer pixels via 
+     * the getDataElements and setDataElements methods.
+     * Transfer type value can be one of the predefined type 
+     * from DataBuffer class or not.
+     * 
+     * @return the transfer type.
+     */
+    public int getTransferType() {
+        return dataType;
+    }
+
+    /**
+     * Returns the number of data elements for pixel transfering
+     * via the getDataElements and setDataElements methods. 
+     * 
+     * @return the number of data elements for pixel transfering
+     * via the getDataElements and setDataElements methods.
+     */
+    public abstract int getNumDataElements();
+
+    /**
+     * Gets the number of bands in the image data of this 
+     * SampleModel object.
+     * 
+     * @return the number of bands in the image data of this 
+     * SampleModel object.
+     */
+    public final int getNumBands() {
+        return numBands;
+    }
+
+    /**
+     * Gets the height of the image data of this SampleModel object.
+     * 
+     * @return the height of the image data of this SampleModel object.
+     */
+    public final int getHeight() {
+        return height;
+    }
+
+    /**
+     * Gets the data type of image data of this SampleModel object.
+     * 
+     * @return the data type of image data of this SampleModel object.
+     */
+    public final int getDataType() {
+        return dataType;
+    }
+
+}
+
diff --git a/awt/java/awt/image/ShortLookupTable.java b/awt/java/awt/image/ShortLookupTable.java
new file mode 100644
index 0000000..77c9c45
--- /dev/null
+++ b/awt/java/awt/image/ShortLookupTable.java
@@ -0,0 +1,132 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Oleg V. Khaschansky
+ * @version $Revision$
+ *
+ * @date: Oct 14, 2005
+ */
+
+package java.awt.image;
+
+
+/**
+ * The ShortLookupTable class provides provides functionality for 
+ * lookup operations, and is defined by an input short array for 
+ * bands or components of image and an offset value.
+ * The offset value will be subtracted from the input values before 
+ * indexing the input arrays. The output of a lookup operation is 
+ * represented as an unsigned short array.
+ */
+public class ShortLookupTable extends LookupTable {
+    
+    /** The data. */
+    private short data[][];
+
+    /**
+     * Instantiates a new ShortLookupTable with the specified offset value
+     * and the specified short array which represents lookup table for
+     * all bands.
+     * 
+     * @param offset the offset value.
+     * @param data the data array.
+     */
+    public ShortLookupTable(int offset, short[] data) {
+        super(offset, 1);
+        this.data = new short[1][data.length];
+        // The data array stored as a reference
+        this.data[0] = data;
+    }
+
+    /**
+     * Instantiates a new ShortLookupTable with the specified offset value
+     * and the specified short array of arrays which represents lookup table
+     * for each band.
+     * 
+     * @param offset the offset value.
+     * @param data the data array of arrays for each band.
+     */
+    public ShortLookupTable(int offset, short[][] data) {
+        super(offset, data.length);
+        this.data = new short[data.length][data[0].length];
+        for (int i = 0; i < data.length; i++) {
+            // The data array for each band stored as a reference
+            this.data[i] = data[i];
+        }
+    }
+
+    /**
+     * Gets the lookup table of this ShortLookupTable object. If 
+     * this ShortLookupTable object has one short array for all bands, 
+     * the returned array length is one.
+     * 
+     * @return the lookup table of this ShortLookupTable object.
+     */
+    public final short[][] getTable() {
+        return data;
+    }
+
+    /**
+     * Returns a short array which contains samples of the specified
+     * pixel which is translated with the lookup table of this 
+     * ShortLookupTable object. The resulted array is stored to
+     * the dst array.
+     * 
+     * @param src the source array.
+     * @param dst the destination array where the result can be stored.
+     * 
+     * @return the short array of translated samples of a pixel.
+     */
+    public short[] lookupPixel(short[] src, short[] dst) {
+        if (dst == null) {
+            dst = new short[src.length];
+        }
+
+        int offset = getOffset();
+        if (getNumComponents() == 1) {
+            for (int i = 0; i < src.length; i++) {
+                dst[i] = data[0][src[i]-offset];
+            }
+        } else {
+            for (int i = 0; i < getNumComponents(); i++) {
+                dst[i] = data[i][src[i]-offset];
+            }
+        }
+
+        return dst;
+    }
+
+    @Override
+    public int[] lookupPixel(int[] src, int[] dst) {
+        if (dst == null) {
+            dst = new int[src.length];
+        }
+
+        int offset = getOffset();
+        if (getNumComponents() == 1) {
+            for (int i = 0; i < src.length; i++) {
+                dst[i] = data[0][src[i]-offset];
+            }
+        } else {
+            for (int i = 0; i < getNumComponents(); i++) {
+                dst[i] = data[i][src[i]-offset];
+            }
+        }
+
+        return dst;
+    }
+}
diff --git a/awt/java/awt/image/SinglePixelPackedSampleModel.java b/awt/java/awt/image/SinglePixelPackedSampleModel.java
new file mode 100644
index 0000000..311395a
--- /dev/null
+++ b/awt/java/awt/image/SinglePixelPackedSampleModel.java
@@ -0,0 +1,508 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import java.util.Arrays;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The SinglePixelPackedSampleModel class represents pixel data 
+ * where several samples combine to create a single pixel and 
+ * are stored in a single data array element. This class 
+ * supports TYPE_BYTE, TYPE_USHORT, TYPE_INT data types. 
+ */
+public class SinglePixelPackedSampleModel extends SampleModel {
+
+    /** The bit masks. */
+    private int bitMasks[];
+
+    /** The bit offsets. */
+    private int bitOffsets[];
+
+    /** The bit sizes. */
+    private int bitSizes[];
+
+    /** The scanline stride. */
+    private int scanlineStride;
+
+    /** The max bit size. */
+    private int maxBitSize;
+
+    /**
+     * Instantiates a new SinglePixelPackedSampleModel with the specified
+     * parameters.
+     * 
+     * @param dataType the data type of samples.
+     * @param w the width of the image data.
+     * @param h the height of the image data.
+     * @param bitMasks the bit masks for all the bands.
+     */
+    public SinglePixelPackedSampleModel(int dataType, int w, int h,
+            int bitMasks[]) {
+        this(dataType, w, h, w, bitMasks);
+    }
+
+    /**
+     * Instantiates a new SinglePixelPackedSampleModel with the specified
+     * parameters.
+     * 
+     * @param dataType the data type of the samples.
+     * @param w the width of the image data.
+     * @param h the height of the image data.
+     * @param scanlineStride The scanline stride of the image data.
+     * @param bitMasks the bit masks for all the bands.
+     */
+    public SinglePixelPackedSampleModel(int dataType, int w, int h,
+            int scanlineStride, int bitMasks[]) {
+
+        super(dataType, w, h, bitMasks.length);
+
+        if (dataType != DataBuffer.TYPE_BYTE &&
+                dataType != DataBuffer.TYPE_USHORT &&
+                dataType != DataBuffer.TYPE_INT) {
+            // awt.61=Unsupported data type: {0}
+            throw new IllegalArgumentException(Messages.getString("awt.61", //$NON-NLS-1$
+                    dataType));
+        }
+
+        this.scanlineStride = scanlineStride;
+        this.bitMasks = bitMasks.clone();
+        this.bitOffsets = new int[this.numBands];
+        this.bitSizes = new int[this.numBands];
+
+        this.maxBitSize = 0;
+
+        for (int i = 0; i < this.numBands; i++) {
+            int offset = 0;
+            int size = 0;
+            int mask = bitMasks[i];
+
+            if (mask != 0) {
+                while ((mask & 1) == 0) {
+                    mask >>>= 1;
+                    offset++;
+                }
+
+                while ((mask & 1) == 1) {
+                    mask >>>= 1;
+                    size++;
+                }
+
+                if (mask != 0) {
+                    // awt.62=Wrong mask : {0}
+                    throw new IllegalArgumentException(Messages.getString(
+                            "awt.62", bitMasks[i])); //$NON-NLS-1$
+                }
+            }
+
+            this.bitOffsets[i] = offset;
+            this.bitSizes[i] = size;
+
+            if (this.maxBitSize < size) {
+                this.maxBitSize = size;
+            }
+
+        }
+
+    }
+
+    @Override
+    public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
+        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+        switch (getTransferType()) {
+        case DataBuffer.TYPE_BYTE:
+            byte bdata[];
+            if (obj == null) {
+                bdata = new byte[1];
+            } else {
+                bdata = (byte[]) obj;
+            }
+
+            bdata[0] = (byte) data.getElem(y * scanlineStride + x);
+            obj = bdata;
+            break;
+        case DataBuffer.TYPE_USHORT:
+            short sdata[];
+            if (obj == null) {
+                sdata = new short[1];
+            } else {
+                sdata = (short[]) obj;
+            }
+
+            sdata[0] = (short) data.getElem(y * scanlineStride + x);
+            obj = sdata;
+            break;
+        case DataBuffer.TYPE_INT:
+            int idata[];
+            if (obj == null) {
+                idata = new int[1];
+            } else {
+                idata = (int[]) obj;
+            }
+
+            idata[0] = data.getElem(y * scanlineStride + x);
+            obj = idata;
+            break;
+        }
+        return obj;
+    }
+
+    @Override
+    public void setDataElements(int x, int y, Object obj, DataBuffer data) {
+        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+        switch (getTransferType()) {
+        case DataBuffer.TYPE_BYTE:
+            data.setElem(y * scanlineStride + x, ((byte[]) obj)[0] & 0xff);
+            break;
+        case DataBuffer.TYPE_USHORT:
+            data.setElem(y * scanlineStride + x, ((short[]) obj)[0] & 0xffff);
+            break;
+        case DataBuffer.TYPE_INT:
+            data.setElem(y * scanlineStride + x, ((int[]) obj)[0]);
+            break;
+        }
+    }
+
+    /**
+     * Compares this SinglePixelPackedSampleModel object with 
+     * the specified object.
+     * 
+     * @param o the Object to be compared.
+     * 
+     * @return true, if this SinglePixelPackedSampleModel object is 
+     * equal to the specified object, false otherwise.
+     */
+    @Override
+    public boolean equals(Object o) {
+        if ((o == null) || !(o instanceof SinglePixelPackedSampleModel)) {
+            return false;
+        }
+
+        SinglePixelPackedSampleModel model = (SinglePixelPackedSampleModel) o;
+        return this.width == model.width &&
+                this.height == model.height &&
+                this.numBands == model.numBands &&
+                this.dataType == model.dataType &&
+                Arrays.equals(this.bitMasks, model.bitMasks) &&
+                Arrays.equals(this.bitOffsets, model.bitOffsets) &&
+                Arrays.equals(this.bitSizes, model.bitSizes) &&
+                this.scanlineStride == model.scanlineStride;
+    }
+
+    @Override
+    public SampleModel createSubsetSampleModel(int bands[]) {
+        if (bands.length > this.numBands) {
+            // awt.64=The number of the bands in the subset is greater than the number of bands in the sample model
+            throw new RasterFormatException(Messages.getString("awt.64")); //$NON-NLS-1$
+        }
+
+        int masks[] = new int[bands.length];
+        for (int i = 0; i < bands.length; i++) {
+            masks[i] = this.bitMasks[bands[i]];
+        }
+        return new SinglePixelPackedSampleModel(this.dataType, this.width,
+                this.height, this.scanlineStride, masks);
+    }
+
+    @Override
+    public SampleModel createCompatibleSampleModel(int w, int h) {
+        return new SinglePixelPackedSampleModel(this.dataType, w, h,
+                this.bitMasks);
+    }
+
+    @Override
+    public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
+        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+        int pixel[];
+        if (iArray == null) {
+            pixel = new int[this.numBands];
+        } else {
+            pixel = iArray;
+        }
+
+        for (int i = 0; i < this.numBands; i++) {
+            pixel[i] = getSample(x, y, i, data);
+        }
+
+        return pixel;
+    }
+
+    @Override
+    public void setPixel(int x, int y, int iArray[], DataBuffer data) {
+        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+        for (int i = 0; i < this.numBands; i++) {
+            setSample(x, y, i, iArray[i], data);
+        }
+    }
+
+    @Override
+    public int getSample(int x, int y, int b, DataBuffer data) {
+        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+        int sample = data.getElem(y * scanlineStride + x);
+        return ((sample & this.bitMasks[b]) >>> this.bitOffsets[b]);
+    }
+
+    @Override
+    public int[] getPixels(int x, int y, int w, int h, int iArray[],
+            DataBuffer data) {
+        if ((x < 0) || (y < 0) || ((long) x + (long) w > this.width)
+                || ((long) y + (long) h > this.height)) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+
+        int pixels[];
+
+        if (iArray == null) {
+            pixels = new int[w * h * this.numBands];
+        } else {
+            pixels = iArray;
+        }
+
+        int idx = 0;
+
+        for (int i = y; i < y + h; i++) {
+            for (int j = x; j < x + w; j++) {
+                for (int n = 0; n < this.numBands; n++) {
+                    pixels[idx++] = getSample(j, i, n, data);
+                }
+            }
+        }
+        return pixels;
+    }
+
+    @Override
+    public void setPixels(int x, int y, int w, int h, int iArray[],
+            DataBuffer data) {
+        if ((x < 0) || (y < 0) || ((long) x + (long) w > this.width)
+                || ((long) y + (long) h > this.height)) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages
+                    .getString("awt.63")); //$NON-NLS-1$
+        }
+
+        int idx = 0;
+
+        for (int i = y; i < y + h; i++) {
+            for (int j = x; j < x + w; j++) {
+                for (int n = 0; n < this.numBands; n++) {
+                    setSample(j, i, n, iArray[idx++], data);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void setSample(int x, int y, int b, int s, DataBuffer data) {
+        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+        int tmp = data.getElem(y * scanlineStride + x);
+        tmp &= ~this.bitMasks[b];
+        tmp |= (s << this.bitOffsets[b]) & this.bitMasks[b];
+        data.setElem(y * scanlineStride + x, tmp);
+    }
+
+    @Override
+    public int[] getSamples(int x, int y, int w, int h, int b, int iArray[],
+            DataBuffer data) {
+        if ((x < 0) || (y < 0) || ((long) x + (long) w > this.width)
+                || ((long) y + (long) h > this.height)) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages
+                    .getString("awt.63")); //$NON-NLS-1$
+        }
+
+        int samples[];
+        int idx = 0;
+
+        if (iArray == null) {
+            samples = new int[w * h];
+        } else {
+            samples = iArray;
+        }
+
+        for (int i = y; i < y + h; i++) {
+            for (int j = x; j < x + w; j++) {
+                samples[idx++] = getSample(j, i, b, data);
+            }
+        }
+
+        return samples;
+    }
+
+    @Override
+    public void setSamples(int x, int y, int w, int h, int b, int iArray[],
+            DataBuffer data) {
+        if ((x < 0) || (y < 0) || ((long) x + (long) w > this.width)
+                || ((long) y + (long) h > this.height)) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+
+        int idx = 0;
+        for (int i = y; i < y + h; i++) {
+            for (int j = x; j < x + w; j++) {
+                setSample(x + j, y + i, b, iArray[idx++], data);
+            }
+        }
+    }
+
+    @Override
+    public DataBuffer createDataBuffer() {
+        DataBuffer data = null;
+        int size = (this.height - 1) * scanlineStride + width;
+
+        switch (this.dataType) {
+        case DataBuffer.TYPE_BYTE:
+            data = new DataBufferByte(size);
+            break;
+        case DataBuffer.TYPE_USHORT:
+            data = new DataBufferUShort(size);
+            break;
+        case DataBuffer.TYPE_INT:
+            data = new DataBufferInt(size);
+            break;
+        }
+        return data;
+    }
+
+    /**
+     * Gets the offset of the specified pixel in the data array.
+     * 
+     * @param x the X coordinate of the specified pixel.
+     * @param y the Y coordinate of the specified pixel.
+     * 
+     * @return the offset of the specified pixel.
+     */
+    public int getOffset(int x, int y) {
+        return (y * scanlineStride + x);
+    }
+
+    @Override
+    public int getSampleSize(int band) {
+        return bitSizes[band];
+    }
+
+    @Override
+    public int[] getSampleSize() {
+        return bitSizes.clone();
+    }
+
+    /**
+     * Gets an array of the bit offsets of the data array elements. 
+     * 
+     * @return an array of the bit offsets.
+     */
+    public int[] getBitOffsets() {
+        return bitOffsets.clone();
+    }
+
+    /**
+     * Gets an array of the bit masks for all bands.
+     * 
+     * @return an array of the bit masks for all bands.
+     */
+    public int[] getBitMasks() {
+        return bitMasks.clone();
+    }
+
+    /**
+     * Returns a hash code of this MultiPixelPackedSampleModel class.
+     * 
+     * @return the hash code of this MultiPixelPackedSampleModel class.
+     */
+    @Override
+    public int hashCode() {
+        int hash = 0;
+        int tmp = 0;
+
+        hash = width;
+        tmp = hash >>> 24;
+        hash <<= 8;
+        hash |= tmp;
+        hash ^= height;
+        tmp = hash >>> 24;
+        hash <<= 8;
+        hash |= tmp;
+        hash ^= numBands;
+        tmp = hash >>> 24;
+        hash <<= 8;
+        hash |= tmp;
+        hash ^= dataType;
+        tmp = hash >>> 24;
+        hash <<= 8;
+        hash |= tmp;
+        for (int element : bitMasks) {
+            hash ^= element;
+            tmp = hash >>> 24;
+            hash <<= 8;
+            hash |= tmp;
+        }
+        for (int element : bitOffsets) {
+            hash ^= element;
+            tmp = hash >>> 24;
+            hash <<= 8;
+            hash |= tmp;
+        }
+        for (int element : bitSizes) {
+            hash ^= element;
+            tmp = hash >>> 24;
+            hash <<= 8;
+            hash |= tmp;
+        }
+        hash ^= scanlineStride;
+        return hash;
+    }
+
+    /**
+     * Gets the scanline stride.
+     * 
+     * @return the scanline stride
+     */
+    public int getScanlineStride() {
+        return this.scanlineStride;
+    }
+
+    @Override
+    public int getNumDataElements() {
+        return 1;
+    }
+
+}
+
diff --git a/awt/java/awt/image/TileObserver.java b/awt/java/awt/image/TileObserver.java
new file mode 100644
index 0000000..39ded02
--- /dev/null
+++ b/awt/java/awt/image/TileObserver.java
@@ -0,0 +1,44 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+
+/**
+ * An asynchronous update interface for receiving notifications
+ * about tile information when tiles of a WritableRenderedImage 
+ * become modifiable or unmodifiable.
+ */
+public interface TileObserver {
+
+    /**
+     * This method is called when information about a tile
+     * update is available.
+     * 
+     * @param source the source image.
+     * @param tileX the X index of the tile.
+     * @param tileY the Y index of the tile.
+     * @param willBeWritable parameter which indicates whether
+     * the tile will be grabbed for writing or be released.
+     */
+    public void tileUpdate(WritableRenderedImage source, int tileX, int tileY, boolean willBeWritable);
+
+}
+
diff --git a/awt/java/awt/image/VolatileImage.java b/awt/java/awt/image/VolatileImage.java
new file mode 100644
index 0000000..3b0cfb2
--- /dev/null
+++ b/awt/java/awt/image/VolatileImage.java
@@ -0,0 +1,144 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Alexey A. Petrenko
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.Image;
+import java.awt.ImageCapabilities;
+import java.awt.Transparency;
+
+/**
+ * The VolatileImage abstract class represents an image which can lose 
+ * its contents at any point. VolatileImage objects are device specific.
+ * This class provies methods for checking if operation of this image
+ * are compatible for the GraphicsConfiguration. 
+ */
+public abstract class VolatileImage extends Image
+    // Volatile image implements Transparency since 1.5
+    implements Transparency {
+    
+    /** 
+     * The Constant IMAGE_INCOMPATIBLE indicates that this VolatileImage 
+     * is not applicable for the GraphicsConfiguration object. 
+     */
+    public static final int IMAGE_INCOMPATIBLE = 2;
+
+    /** 
+     * The Constant IMAGE_OK indicates that VolatileImage is ready 
+     * for using.
+     */
+    public static final int IMAGE_OK = 0;
+
+    /** 
+     * The Constant IMAGE_RESTORED indicates that VolatileImage
+     * will be ready to use after restoring. 
+     */
+    public static final int IMAGE_RESTORED = 1;
+
+    /** 
+     * The transparency value of this image. 
+     */
+    protected int transparency = OPAQUE;
+
+    /**
+     * Instantiates a new VolatileImage object.
+     */
+    public VolatileImage() {
+        super();
+    }
+
+    /**
+     * Returns true if rendering data is lost during validating.
+     * This method should be called after rendering operation of image.
+     * 
+     * @return true, if contents lost during validating, false otherwise.
+     */
+
+    public abstract boolean contentsLost();
+
+    /**
+     * Creates a Graphics2D used to draw in this VolatileImage.
+     * 
+     * @return the Graphics2D object.
+     */
+    public abstract Graphics2D createGraphics();
+
+    /**
+     * Gets the ImageCapabilities of this VolatileImage.
+     * 
+     * @return the ImageCapabilities of this VolatileImage.
+     */
+    public abstract ImageCapabilities getCapabilities();
+
+    /**
+     * Gets the height of this VolatileImage.
+     * 
+     * @return the height of this VolatileImage.
+     */
+    public abstract int getHeight();
+
+    /**
+     * Gets a BufferedImage representation of current VolatileImage that
+     * won't be affected by any changes to this VolatileImage.
+     * 
+     * @return a BufferedImage representation of current VolatileImage.
+     */
+    public abstract BufferedImage getSnapshot();
+
+    /**
+     * Gets the width of this VolatileImage.
+     * 
+     * @return the width of this VolatileImage.
+     */
+    public abstract int getWidth();
+
+    /**
+     * Validates the drawing surface of the image if the surface had been 
+     * lost and if the spacified GraphicsConfiguration object is  
+     * applicable to this image. 
+     * 
+     * @param gc GraphicsConfiguration object.
+     * 
+     * @return one of the image status constants: IMAGE_OK, IMAGE_RESTORED or
+     * IMAGE_INCOMPATIBLE.
+     */
+    public abstract int validate(GraphicsConfiguration gc);
+
+    @Override
+    public void flush() {
+    }
+
+    @Override
+    public Graphics getGraphics() {
+        return createGraphics();
+    }
+
+    @Override
+    public ImageProducer getSource() {
+        return getSnapshot().getSource();
+    }
+
+    public int getTransparency() {
+        return transparency;
+    }
+}
diff --git a/awt/java/awt/image/WritableRaster.java b/awt/java/awt/image/WritableRaster.java
new file mode 100644
index 0000000..0893915
--- /dev/null
+++ b/awt/java/awt/image/WritableRaster.java
@@ -0,0 +1,516 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import java.awt.Point;
+import java.awt.Rectangle;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The WritableRaster class provides functionality for 
+ * writing samples and pixel capabilities to the Raster.
+ */
+public class WritableRaster extends Raster {
+
+    /**
+     * Instantiates a new WritableRaster object with the specified 
+     * SampleModel, DataBuffer, rectangular region and parent 
+     * WritableRaster. 
+     * 
+     * @param sampleModel the specified SampleModel.
+     * @param dataBuffer the specified DataBuffer.
+     * @param aRegion the rectangular region which defines the new image bounds. 
+     * @param sampleModelTranslate this point defines the translation point
+     * from the SampleModel to the new WritableRaster coordinates.
+     * @param parent the parent of this WritableRaster.
+     */
+    protected WritableRaster(SampleModel sampleModel, DataBuffer dataBuffer,
+            Rectangle aRegion, Point sampleModelTranslate,
+            WritableRaster parent) {
+        super(sampleModel, dataBuffer, aRegion, sampleModelTranslate, parent);
+    }
+
+    /**
+     * Instantiates a new WritableRaster object with the specified
+     * SampleModel which defines a layout of this WritableRaster and 
+     * DataBuffer objects which defines the image data.
+     * 
+     * @param sampleModel the specified SampleModel.
+     * @param dataBuffer the specified DataBuffer.
+     * @param origin the point of origin.
+     */
+    protected WritableRaster(SampleModel sampleModel, DataBuffer dataBuffer,
+            Point origin) {
+        this(sampleModel, dataBuffer, new Rectangle(origin.x, origin.y,
+                sampleModel.width, sampleModel.height), origin, null);
+    }
+
+    /**
+     * Instantiates a new WritableRaster with the specified SampleModel.
+     * 
+     * @param sampleModel the specified SampleModel.
+     * @param origin the origin.
+     */
+    protected WritableRaster(SampleModel sampleModel, Point origin) {
+        this(sampleModel, sampleModel.createDataBuffer(), new Rectangle(
+                origin.x, origin.y, sampleModel.width, sampleModel.height),
+                origin, null);
+    }
+
+    /**
+     * Sets the data for a single pixel from an input Object which 
+     * represents an array of primitive types: DataBuffer.TYPE_BYTE, 
+     * DataBuffer.TYPE_USHORT, DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT, 
+     * DataBuffer.TYPE_FLOAT, or DataBuffer.TYPE_DOUBLE.
+     * 
+     * @param x the X coordinate of the pixel.
+     * @param y the Y coordinate of the pixel.
+     * @param inData the input data.
+     */
+    public void setDataElements(int x, int y, Object inData) {
+        sampleModel.setDataElements(x - sampleModelTranslateX,
+                y - sampleModelTranslateY, inData, dataBuffer);
+    }
+
+    /**
+     * Sets the data elements which represent pixel data to the specified 
+     * rectangle area as a primitive array. The following image data types
+     * are supported: DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, 
+     * DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT, DataBuffer.TYPE_FLOAT, 
+     * or DataBuffer.TYPE_DOUBLE.
+     * 
+     * @param x the X coordinate of the rectangle of pixels.
+     * @param y the Y coordinate of the rectangle of pixels.
+     * @param w the width of the rectangle of pixels.
+     * @param h the height of the rectangle of pixels.
+     * @param inData the array of primitive type data to be set to the
+     * specified area.
+     */
+    public void setDataElements(int x, int y, int w, int h, Object inData) {
+        sampleModel.setDataElements(x - sampleModelTranslateX,
+                y - sampleModelTranslateY, w, h, inData, dataBuffer);
+    }
+
+    /**
+     * Creates the child of this WritableRaster by sharing the specified 
+     * rectangular area in this WritableRaster. 
+     * The parentX, parentY, width and height parameters specify rectangular
+     * area to be shared.
+     * 
+     * @param parentX the X coordinate of the upper left corner of 
+     * the shared rectangle with respect to this WritableRaster' coordinates. 
+     * @param parentY the Y coordinate of the upper left corner of 
+     * the shared rectangle with respect to this WritableRaster' coordinates. 
+     * @param w the width of the child area.
+     * @param h the height of the child area.
+     * @param childMinX the X coordinate of child area mapped to the parentX
+     * coordinate.
+     * @param childMinY the Y coordinate of child area mapped to the parentY
+     * coordinate.
+     * @param bandList the array of band indicies.
+     * 
+     * @return the child WritableRaster.
+     */
+    public WritableRaster createWritableChild(int parentX, int parentY, int w,
+            int h, int childMinX, int childMinY, int bandList[]) {
+        if (w <= 0 || h <= 0) {
+            // awt.244=Width or Height of child Raster is less than or equal to zero
+            throw new RasterFormatException(Messages.getString("awt.244")); //$NON-NLS-1$
+        }
+
+        if (parentX < this.minX || parentX + w > this.minX + this.width) {
+            // awt.245=parentX disposes outside Raster
+            throw new RasterFormatException(Messages.getString("awt.245")); //$NON-NLS-1$
+        }
+
+        if (parentY < this.minY || parentY + h > this.minY + this.height) {
+            // awt.246=parentY disposes outside Raster
+            throw new RasterFormatException(Messages.getString("awt.246")); //$NON-NLS-1$
+        }
+
+        if ((long) parentX + w > Integer.MAX_VALUE) {
+            // awt.247=parentX + w results in integer overflow
+            throw new RasterFormatException(Messages.getString("awt.247")); //$NON-NLS-1$
+        }
+
+        if ((long) parentY + h > Integer.MAX_VALUE) {
+            // awt.248=parentY + h results in integer overflow
+            throw new RasterFormatException(Messages.getString("awt.248")); //$NON-NLS-1$
+        }
+
+        if ((long) childMinX + w > Integer.MAX_VALUE) {
+            // awt.249=childMinX + w results in integer overflow
+            throw new RasterFormatException(Messages.getString("awt.249")); //$NON-NLS-1$
+        }
+
+        if ((long) childMinY + h > Integer.MAX_VALUE) {
+            // awt.24A=childMinY + h results in integer overflow
+            throw new RasterFormatException(Messages.getString("awt.24A")); //$NON-NLS-1$
+        }
+
+        SampleModel childModel;
+
+        if (bandList == null) {
+            childModel = sampleModel;
+        } else {
+            childModel = sampleModel.createSubsetSampleModel(bandList);
+        }
+
+        int childTranslateX = childMinX - parentX;
+        int childTranslateY = childMinY - parentY;
+
+        return new WritableRaster(childModel, dataBuffer,
+                new Rectangle(childMinX, childMinY, w, h),
+                new Point(childTranslateX + sampleModelTranslateX,
+                        childTranslateY + sampleModelTranslateY),
+                this);
+    }
+
+    /**
+     * Creates the translated child of this WritableRaster. 
+     * New WritableRaster object is a reference to the this 
+     * WritableRaster and with different location. 
+     *  
+     * @param childMinX the X coordinate of the new WritableRaster.
+     * @param childMinY the Y coordinate of the new WritableRaster.
+     * 
+     * @return the WritableRaster.
+     */
+    public WritableRaster createWritableTranslatedChild(int childMinX,
+            int childMinY) {
+        return createWritableChild(minX, minY, width, height, childMinX,
+                childMinY, null);
+    }
+
+    /**
+     * Gets the parent WritableRaster for this WritableRaster object. 
+     * 
+     * @return the parent WritableRaster for this WritableRaster object.
+     */
+    public WritableRaster getWritableParent() {
+        return (WritableRaster) parent;
+    }
+
+    /**
+     * Sets pixels from the specified source Raster srcRaster to this 
+     * WritableRaster.
+     * 
+     * @param srcRaster the source Raster.
+     */
+    public void setRect(Raster srcRaster) {
+        setRect(0, 0, srcRaster);
+    }
+
+    /**
+     * Sets pixels from the specified source Raster srcRaster to this 
+     * WritableRaster. Each pixel with (x, y) coordinates from the source 
+     * Raster is copied to pixel with (x+dx, y+dy) coordinates in this
+     * WritableRaster. The pixels with (x+dx, y+dy) coordinates which
+     * are out the bounds of this raster are ignored. 
+     *  
+     * @param dx the distance the pixel's X coordinate in the source
+     * Raster is translated when writtien to this WritableRaster. 
+     * @param dy the distance the pixel's Y coordinate in the source
+     * Raster is translated when writtien to this WritableRaster.
+     * @param srcRaster the source Raster.
+     */
+    public void setRect(int dx, int dy, Raster srcRaster) {
+        int w = srcRaster.getWidth();
+        int h = srcRaster.getHeight();
+
+        int srcX = srcRaster.getMinX();
+        int srcY = srcRaster.getMinY();
+
+        int dstX = srcX + dx;
+        int dstY = srcY + dy;
+
+        if (dstX < this.minX) {
+            int minOffX = this.minX - dstX;
+            w -= minOffX;
+            dstX = this.minX;
+            srcX += minOffX;
+        }
+
+        if (dstY < this.minY) {
+            int minOffY = this.minY - dstY;
+            h -= minOffY;
+            dstY = this.minY;
+            srcY += minOffY;
+        }
+
+        if (dstX + w > this.minX + this.width) {
+            int maxOffX = (dstX + w) - (this.minX + this.width);
+            w -= maxOffX;
+        }
+
+        if (dstY + h > this.minY + this.height) {
+            int maxOffY = (dstY + h) - (this.minY + this.height);
+            h -= maxOffY;
+        }
+
+        if (w <= 0 || h <= 0) {
+            return;
+        }
+
+        switch (sampleModel.getDataType()) {
+        case DataBuffer.TYPE_BYTE:
+        case DataBuffer.TYPE_SHORT:
+        case DataBuffer.TYPE_USHORT:
+        case DataBuffer.TYPE_INT:
+            int iPixelsLine[] = null;
+            for (int i = 0; i < h; i++) {
+                iPixelsLine = srcRaster.getPixels(srcX, srcY + i, w, 1,
+                        iPixelsLine);
+                setPixels(dstX, dstY + i, w, 1, iPixelsLine);
+            }
+            break;
+
+        case DataBuffer.TYPE_FLOAT:
+            float fPixelsLine[] = null;
+            for (int i = 0; i < h; i++) {
+                fPixelsLine = srcRaster.getPixels(srcX, srcY + i, w, 1,
+                        fPixelsLine);
+                setPixels(dstX, dstY + i, w, 1, fPixelsLine);
+            }
+            break;
+
+        case DataBuffer.TYPE_DOUBLE:
+            double dPixelsLine[] = null;
+            for (int i = 0; i < h; i++) {
+                dPixelsLine = srcRaster.getPixels(srcX, srcY + i, w, 1,
+                        dPixelsLine);
+                setPixels(dstX, dstY + i, w, 1, dPixelsLine);
+            }
+            break;
+        }
+    }
+
+    /**
+     * Sets the data for a rectangle of pixels from an input Raster to
+     * this WritableRaster.
+     * 
+     * @param x the X coordinate of the point where the data of 
+     * the input Raster is to be written.
+     * @param y the Y coordinate of the point where the data of 
+     * the input Raster is to be written.
+     * @param inRaster the input Raster.
+     */
+    public void setDataElements(int x, int y, Raster inRaster) {
+        int dstX = x + inRaster.getMinX();
+        int dstY = y + inRaster.getMinY();
+
+        int w = inRaster.getWidth();
+        int h = inRaster.getHeight();
+
+        if (dstX < this.minX || dstX + w > this.minX + this.width ||
+                dstY < this.minY || dstY + h > this.minY + this.height) {
+            // awt.63=Coordinates are not in bounds
+            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
+        }
+
+        int srcX = inRaster.getMinX();
+        int srcY = inRaster.getMinY();
+        Object line = null;
+
+        for (int i = 0; i < h; i++) {
+            line = inRaster.getDataElements(srcX, srcY + i, w, 1, line);
+            setDataElements(dstX, dstY + i, w, 1, line);
+        }
+    }
+
+    /**
+     * Sets a int array of samples for the specified pixel 
+     * in this WritableRaster. 
+     * 
+     * @param x the pixel's X coordinate.
+     * @param y the pixel's Y coordinate.
+     * @param iArray the int array of samples.
+     */
+    public void setPixel(int x, int y, int iArray[]) {
+        sampleModel.setPixel(x - sampleModelTranslateX,
+                y - sampleModelTranslateY, iArray, dataBuffer);
+    }
+
+    /**
+     * Sets a float array of samples for the specified pixel 
+     * in this WritableRaster. 
+     * 
+     * @param x the pixel's X coordinate.
+     * @param y the pixel's Y coordinate.
+     * @param fArray the float array of samples.
+     */
+    public void setPixel(int x, int y, float fArray[]) {
+        sampleModel.setPixel(x - sampleModelTranslateX,
+                y - sampleModelTranslateY, fArray, dataBuffer);
+    }
+
+    /**
+     * Sets a double array of samples for the specified pixel 
+     * in this WritableRaster. 
+     * 
+     * @param x the pixel's X coordinate.
+     * @param y the pixel's Y coordinate.
+     * @param dArray the double array of samples.
+     */
+    public void setPixel(int x, int y, double dArray[]) {
+        sampleModel.setPixel(x - sampleModelTranslateX,
+                y - sampleModelTranslateY, dArray, dataBuffer);
+    }
+
+    /**
+     * Sets a int array of samples for the specified rectangular area
+     * of pixels in this WritableRaster. 
+     * 
+     * @param x the X coordinate of rectangular area.
+     * @param y the Y coordinate of rectangular area.
+     * @param w the width of rectangular area.
+     * @param h the height of rectangular area.
+     * @param iArray the int array of samples.
+     */
+    public void setPixels(int x, int y, int w, int h, int iArray[]) {
+        sampleModel.setPixels(x - sampleModelTranslateX,
+                y - sampleModelTranslateY, w, h, iArray, dataBuffer);
+    }
+
+    /**
+     * Sets a float array of samples for the specified rectangular area
+     * of pixels in this WritableRaster. 
+     * 
+     * @param x the X coordinate of rectangular area.
+     * @param y the Y coordinate of rectangular area.
+     * @param w the width of rectangular area.
+     * @param h the height of rectangular area.
+     * @param fArray the float array of samples.
+     */
+    public void setPixels(int x, int y, int w, int h, float fArray[]) {
+        sampleModel.setPixels(x - sampleModelTranslateX,
+                y - sampleModelTranslateY, w, h, fArray, dataBuffer);
+    }
+
+    /**
+     * Sets a double array of samples for the specified rectangular area
+     * of pixels in this WritableRaster. 
+     * 
+     * @param x the X coordinate of rectangular area.
+     * @param y the Y coordinate of rectangular area.
+     * @param w the width of rectangular area.
+     * @param h the height of rectangular area.
+     * @param dArray the double array of samples.
+     */
+    public void setPixels(int x, int y, int w, int h, double dArray[]) {
+        sampleModel.setPixels(x - sampleModelTranslateX,
+                y - sampleModelTranslateY, w, h, dArray, dataBuffer);
+    }
+
+    /**
+     * Sets the samples for the specified band and the specified
+     * rectangular area of pixels with an int array of samples.
+     * 
+     * @param x the X coordinate of the area of pixels.
+     * @param y the Y coordinate of the area of pixels.
+     * @param w the width of the area of pixels.
+     * @param h the height of the area of pixels.
+     * @param b the specified band.
+     * @param iArray the int array of samples.
+
+     */
+    public void setSamples(int x, int y, int w, int h, int b, int iArray[]) {
+        sampleModel.setSamples(x - sampleModelTranslateX,
+                y - sampleModelTranslateY, w, h, b, iArray, dataBuffer);
+    }
+
+    /**
+     * Sets the samples for the specified band and the specified
+     * rectangular area of pixels with a float array of samples.
+     * 
+     * @param x the X coordinate of the area of pixels.
+     * @param y the Y coordinate of the area of pixels.
+     * @param w the width of the area of pixels.
+     * @param h the height of the area of pixels.
+     * @param b the specified band.
+     * @param fArray the float array of samples.
+     */
+    public void setSamples(int x, int y, int w, int h, int b, float fArray[]) {
+        sampleModel.setSamples(x - sampleModelTranslateX,
+                y - sampleModelTranslateY, w, h, b, fArray, dataBuffer);
+    }
+
+    /**
+     * Sets the samples for the specified band and the specified
+     * rectangular area of pixels with a double array of samples.
+     * 
+     * @param x the X coordinate of the area of pixels.
+     * @param y the Y coordinate of the area of pixels.
+     * @param w the width of the area of pixels.
+     * @param h the height of the area of pixels.
+     * @param b the specified band.
+     * @param dArray the double array of samples.
+     */
+    public void setSamples(int x, int y, int w, int h, int b, double dArray[]) {
+        sampleModel.setSamples(x - sampleModelTranslateX,
+                y - sampleModelTranslateY, w, h, b, dArray, dataBuffer);
+    }
+
+    /**
+     * Sets the sample for the specified band and the specified
+     * pixel with an int sample.
+     * 
+     * @param x the X coordinate of the pixel.
+     * @param y the Y coordinate of the pixel.
+     * @param b the specified band.
+     * @param s the sample to be set.
+     */
+    public void setSample(int x, int y, int b, int s) {
+        sampleModel.setSample(x - sampleModelTranslateX,
+                y - sampleModelTranslateY, b, s, dataBuffer);
+    }
+
+    /**
+     * Sets the sample for the specified band and the specified
+     * pixel with a float sample.
+     * 
+     * @param x the X coordinate of the pixel.
+     * @param y the Y coordinate of the pixel.
+     * @param b the specified band.
+     * @param s the sample to be set.
+     */
+    public void setSample(int x, int y, int b, float s) {
+        sampleModel.setSample(x - sampleModelTranslateX,
+                y - sampleModelTranslateY, b, s, dataBuffer);
+    }
+
+    /**
+     * Sets the sample for the specified band and the specified
+     * pixel with a int sample.
+     * 
+     * @param x the X coordinate of the pixel.
+     * @param y the Y coordinate of the pixel.
+     * @param b the specified band.
+     * @param s the sample to be set.
+     */
+    public void setSample(int x, int y, int b, double s) {
+        sampleModel.setSample(x - sampleModelTranslateX,
+                y - sampleModelTranslateY, b, s, dataBuffer);
+    }
+
+}
+
diff --git a/awt/java/awt/image/WritableRenderedImage.java b/awt/java/awt/image/WritableRenderedImage.java
new file mode 100644
index 0000000..ee1cb9e
--- /dev/null
+++ b/awt/java/awt/image/WritableRenderedImage.java
@@ -0,0 +1,101 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image;
+
+import java.awt.Point;
+
+/**
+ * The WriteableRenderedImage interface is interface for objects which
+ * contains Raster data of one or several tiles. This interface provides
+ * notification mehanism for obtaining tile's writing status.    
+ */
+public interface WritableRenderedImage extends RenderedImage {
+
+    /**
+     * Gets and checks out the writable tile for writing. 
+     * 
+     * @param tileX the X index of the tile. 
+     * @param tileY the Y index of the tile.
+     * 
+     * @return the WritableRaster.
+     */
+    public WritableRaster getWritableTile(int tileX, int tileY);
+
+    /**
+     * Removes the registered TileObserver.
+     * 
+     * @param to the TileObserver which is registered for this
+     * WritableRenderedImage.
+     */
+    public void removeTileObserver(TileObserver to);
+
+    /**
+     * Adds the specified TileObserver to this WritableRenderedImage.
+     * 
+     * @param to the TileObserver object to be added.
+     */
+    public void addTileObserver(TileObserver to);
+
+    /**
+     * Sets this image to the contents of the specified Raster.  
+     * 
+     * @param r the specified Raster.
+     */
+    public void setData(Raster r);
+
+    /**
+     * Gets the array of points wich represent indices of tiles which
+     * are check out for writing.
+     * 
+     * @return the array of Points.
+     */
+    public Point[] getWritableTileIndices();
+
+    /**
+     * Checks if the specified tile is writable or not.
+     * 
+     * @param tileX the X index of tile. 
+     * @param tileY the Y index of tile.
+     * 
+     * @return true, if the specified tile is writable,
+     * false otherwise.
+     */
+    public boolean isTileWritable(int tileX, int tileY);
+
+    /**
+     * Release the specified writable tile. This method removes the writer 
+     * from the tile.
+     * 
+     * @param tileX the X index of the tile. 
+     * @param tileY the Y index of the tile.
+     */
+    public void releaseWritableTile(int tileX, int tileY);
+
+    /**
+     * Checks if there is a tile which is checked out for writing.
+     * 
+     * @return true, if any tile is checked out for writing, false if there
+     * is no such tile.
+     */
+    public boolean hasTileWriters();
+
+}
+
diff --git a/awt/java/awt/image/renderable/ContextualRenderedImageFactory.java b/awt/java/awt/image/renderable/ContextualRenderedImageFactory.java
new file mode 100644
index 0000000..3e96637
--- /dev/null
+++ b/awt/java/awt/image/renderable/ContextualRenderedImageFactory.java
@@ -0,0 +1,89 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image.renderable;
+
+import java.awt.geom.Rectangle2D;
+import java.awt.image.RenderedImage;
+
+/**
+ * A factory for creating ContextualRenderedImage objects with utilities 
+ * for manipulating the properties in the parameter block.
+ */
+public interface ContextualRenderedImageFactory extends RenderedImageFactory {
+
+    /**
+     * Maps a render context to a parameter block and a renderable image.
+     * 
+     * @param a0 the index
+     * @param a1 the RenderContext
+     * @param a2 the ParameterBlock
+     * @param a3 the RenderableImage
+     * 
+     * @return the render context
+     */
+    public RenderContext mapRenderContext(int a0, RenderContext a1, ParameterBlock a2, RenderableImage a3);
+
+    /**
+     * Gets the value of the property from the parameter block.
+     * 
+     * @param a0 the parameter block to examine to find the property
+     * @param a1 the name of the property
+     * 
+     * @return the value of the property
+     */
+    public Object getProperty(ParameterBlock a0, String a1);
+
+    /**
+     * Creates the rendered image determined by the render context and
+     * parameter block.
+     * 
+     * @param a0 the RenderContext
+     * @param a1 the ParameterBlock
+     * 
+     * @return the rendered image
+     */
+    public RenderedImage create(RenderContext a0, ParameterBlock a1);
+
+    /**
+     * Gets the bounding rectangle from the parameter block.
+     * 
+     * @param a0 the parameter block to read the bounds from
+     * 
+     * @return the bounding rectangle
+     */
+    public Rectangle2D getBounds2D(ParameterBlock a0);
+
+    /**
+     * Gets the names of all of the supported properties.
+     * 
+     * @return the property names
+     */
+    public String[] getPropertyNames();
+
+    /**
+     * Checks if this image factory is dynamic.
+     * 
+     * @return true, if this image factory is dynamic
+     */
+    public boolean isDynamic();
+
+}
+
diff --git a/awt/java/awt/image/renderable/ParameterBlock.java b/awt/java/awt/image/renderable/ParameterBlock.java
new file mode 100644
index 0000000..1555f45
--- /dev/null
+++ b/awt/java/awt/image/renderable/ParameterBlock.java
@@ -0,0 +1,548 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image.renderable;
+
+import java.awt.image.RenderedImage;
+import java.io.Serializable;
+import java.util.Vector;
+
+/**
+ * The Class ParameterBlock groups an indexed set of parameter data 
+ * with a set of renderable (source) images.  The mapping between
+ * the indexed parameters and their property names is provided 
+ * by a {@link ContextualRenderedImageFactory}
+ */
+public class ParameterBlock implements Cloneable, Serializable {
+
+
+    /** The Constant serialVersionUID. */
+    private static final long serialVersionUID = -7577115551785240750L;
+
+    /** The sources (renderable images). */
+    protected Vector<Object> sources = new Vector<Object>();
+
+    /** The parameters. */
+    protected Vector<Object> parameters = new Vector<Object>();
+
+    /**
+     * Instantiates a new parameter block.
+     * 
+     * @param sources the vector of source images
+     * @param parameters the vector of parameters
+     */
+    public ParameterBlock(Vector<Object> sources, Vector<Object> parameters) {
+        setSources(sources);
+        setParameters(parameters);
+    }
+
+    /**
+     * Instantiates a new parameter block with no parameters.
+     * 
+     * @param sources the vector of source images
+     */
+    public ParameterBlock(Vector<Object> sources) {
+        setSources(sources);
+    }
+
+    /**
+     * Instantiates a new parameter block with no image or parameter vectors.
+     */
+    public ParameterBlock() {}
+
+    /**
+     * Sets the source image at the specified index.
+     * 
+     * @param source the source image
+     * @param index the index where the source will be placed
+     * 
+     * @return this parameter block
+     */
+    public ParameterBlock setSource(Object source, int index) {
+        if(sources.size() < index + 1){
+            sources.setSize(index + 1);
+        }
+        sources.setElementAt(source, index);
+        return this;
+    }
+
+    /**
+     * Sets the parameter value object at the specified index.
+     * 
+     * @param obj the parameter value to place at the desired index
+     * @param index the index where the object is to be placed in the 
+     * vector of parameters
+     * 
+     * @return this parameter block
+     */
+    public ParameterBlock set(Object obj, int index) {
+        if(parameters.size() < index + 1){
+            parameters.setSize(index + 1);
+        }
+        parameters.setElementAt(obj, index);
+        return this;
+    }
+
+    /**
+     * Adds a source to the vector of sources.
+     * 
+     * @param source the source to add
+     * 
+     * @return this parameter block
+     */
+    public ParameterBlock addSource(Object source) {
+        sources.addElement(source);
+        return this;
+    }
+
+    /**
+     * Adds the object to the vector of parameter values
+     * 
+     * @param obj the obj to add
+     * 
+     * @return this parameter block
+     */
+    public ParameterBlock add(Object obj) {
+        parameters.addElement(obj);
+        return this;
+    }
+
+    /**
+     * Sets the vector of sources, replacing the existing
+     * vector of sources, if any.
+     * 
+     * @param sources the new sources
+     */
+    public void setSources(Vector<Object> sources) {
+        this.sources = sources;
+    }
+
+    /**
+     * Sets the vector of parameters, replacing the existing
+     * vector of parameters, if any.
+     * 
+     * @param parameters the new parameters
+     */
+    public void setParameters(Vector<Object> parameters) {
+        this.parameters = parameters;
+    }
+
+    /**
+     * Gets the vector of sources.
+     * 
+     * @return the sources
+     */
+    public Vector<Object> getSources() {
+        return sources;
+    }
+
+    /**
+     * Gets the vector of parameters.
+     * 
+     * @return the parameters
+     */
+    public Vector<Object> getParameters() {
+        return parameters;
+    }
+
+    /**
+     * Gets the source at the specified index.
+     * 
+     * @param index the index
+     * 
+     * @return the source object found at the specified index
+     */
+    public Object getSource(int index) {
+        return sources.elementAt(index);
+    }
+
+    /**
+     * Gets the object parameter found at the specified index.
+     * 
+     * @param index the index
+     * 
+     * @return the parameter object found at the specified index
+     */
+    public Object getObjectParameter(int index) {
+        return parameters.elementAt(index);
+    }
+
+    /**
+     * Shallow clone (clones using the superclass clone method).
+     * 
+     * @return the clone of this object
+     */
+    public Object shallowClone() {
+        try{
+            return super.clone();
+        }catch(Exception e){
+            return null;
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Object clone() {
+        ParameterBlock replica;
+        try{
+            replica = (ParameterBlock)super.clone();
+        }catch(Exception e){
+            return null;
+        }
+        if(sources != null){
+            replica.setSources((Vector<Object>)(sources.clone()));
+        }
+        if(parameters != null){
+            replica.setParameters((Vector<Object>)(parameters.clone()));
+        }
+        return replica;
+    }
+
+    /**
+     * Gets an array of classes corresponding to all of the parameter
+     * values found in the array of parameters, in order.
+     * 
+     * @return the parameter classes
+     */
+    public Class[] getParamClasses() {
+        int count = parameters.size();
+        Class paramClasses[] = new Class[count];
+
+        for(int i = 0; i < count; i++){
+            paramClasses[i] = parameters.elementAt(i).getClass();
+        }
+        return paramClasses;
+    }
+
+    /**
+     * Gets the renderable source image found at the specified index
+     * in the source array.
+     * 
+     * @param index the index
+     * 
+     * @return the renderable source image
+     */
+    public RenderableImage getRenderableSource(int index) {
+        return (RenderableImage)sources.elementAt(index);
+    }
+
+    /**
+     * Wraps the short value in a Short and places it in the 
+     * parameter block at the specified index.
+     * 
+     * @param s the short value of the parameter
+     * @param index the index
+     * 
+     * @return this parameter block
+     */
+    public ParameterBlock set(short s, int index) {
+        return set(new Short(s), index);
+    }
+
+    /**
+     * Wraps the short value in a Short and adds it to the 
+     * parameter block.
+     * 
+     * @param s the short value of the parameter
+     * 
+     * @return this parameter block
+     */
+    public ParameterBlock add(short s) {
+        return add(new Short(s));
+    }
+
+    /**
+     * Wraps the long value in a Long and places it in the 
+     * parameter block at the specified index.
+     * 
+     * @param l the long value of the parameter
+     * @param index the index
+     * 
+     * @return this parameter block
+     */
+    public ParameterBlock set(long l, int index) {
+        return set(new Long(l), index);
+    }
+
+    /**
+     * Wraps the long value in a Long and adds it to the 
+     * parameter block.
+     * 
+     * @param l the long value of the parameter
+     * 
+     * @return this parameter block
+     */
+    public ParameterBlock add(long l) {
+        return add(new Long(l));
+    }
+
+    /**
+     * Wraps the int value in an Integer and places it in the 
+     * parameter block at the specified index.
+     * 
+     * @param i the int value of the parameter
+     * @param index the index
+     * 
+     * @return this parameter block
+     */
+    public ParameterBlock set(int i, int index) {
+        return set(new Integer(i), index);
+    }
+
+    /**
+     * Wraps the int value in an Integer and adds it to the 
+     * parameter block.
+     * 
+     * @param i the int value of the parameter
+     * 
+     * @return this parameter block
+     */
+    public ParameterBlock add(int i) {
+        return add(new Integer(i));
+    }
+
+    /**
+     * Wraps the float value in a Float and places it in the 
+     * parameter block at the specified index.
+     * 
+     * @param f the float value of the parameter
+     * @param index the index
+     * 
+     * @return this parameter block
+     */
+    public ParameterBlock set(float f, int index) {
+        return set(new Float(f), index);
+    }
+
+    /**
+     * Wraps the float value in a Float and adds it to the 
+     * parameter block.
+     * 
+     * @param f the float value of the parameter
+     * 
+     * @return this parameter block
+     */
+    public ParameterBlock add(float f) {
+        return add(new Float(f));
+    }
+
+    /**
+     * Wraps the double value in a Double and places it in the 
+     * parameter block at the specified index.
+     * 
+     * @param d the double value of the parameter
+     * @param index the index
+     * 
+     * @return this parameter block
+     */
+    public ParameterBlock set(double d, int index) {
+        return set(new Double(d), index);
+    }
+
+    /**
+     * Wraps the double value in a Double and adds it to the 
+     * parameter block.
+     * 
+     * @param d the double value of the parameter
+     * 
+     * @return this parameter block
+     */
+    public ParameterBlock add(double d) {
+        return add(new Double(d));
+    }
+
+    /**
+     * Wraps the char value in a Character and places it in the 
+     * parameter block at the specified index.
+     * 
+     * @param c the char value of the parameter
+     * @param index the index
+     * 
+     * @return this parameter block
+     */
+    public ParameterBlock set(char c, int index) {
+        return set(new Character(c), index);
+    }
+
+    /**
+     * Wraps the char value in a Character and adds it to the 
+     * parameter block.
+     * 
+     * @param c the char value of the parameter
+     * 
+     * @return this parameter block
+     */
+    public ParameterBlock add(char c) {
+        return add(new Character(c));
+    }
+
+    /**
+     * Wraps the byte value in a Byte and places it in the 
+     * parameter block at the specified index.
+     * 
+     * @param b the byte value of the parameter
+     * @param index the index
+     * 
+     * @return this parameter block
+     */
+    public ParameterBlock set(byte b, int index) {
+        return set(new Byte(b), index);
+    }
+
+    /**
+     * Wraps the byte value in a Byte and adds it to the 
+     * parameter block.
+     * 
+     * @param b the byte value of the parameter
+     * 
+     * @return the parameter block
+     */
+    public ParameterBlock add(byte b) {
+        return add(new Byte(b));
+    }
+
+    /**
+     * Gets the RenderedImage at the specified index from the 
+     * vector of source images.
+     * 
+     * @param index the index
+     * 
+     * @return the rendered image
+     */
+    public RenderedImage getRenderedSource(int index) {
+        return (RenderedImage)sources.elementAt(index);
+    }
+
+    /**
+     * Gets the short-valued parameter found at the desired index
+     * in the vector of parameter values.
+     * 
+     * @param index the index
+     * 
+     * @return the short parameter
+     */
+    public short getShortParameter(int index) {
+        return ((Short)parameters.elementAt(index)).shortValue();
+    }
+
+    /**
+     * Gets the long-valued parameter found at the desired index
+     * in the vector of parameter values.
+     * 
+     * @param index the index
+     * 
+     * @return the long parameter
+     */
+    public long getLongParameter(int index) {
+        return ((Long)parameters.elementAt(index)).longValue();
+    }
+
+    /**
+     * Gets the int-valued parameter found at the desired index
+     * in the vector of parameter values.
+     * 
+     * @param index the index
+     * 
+     * @return the int parameter
+     */
+    public int getIntParameter(int index) {
+        return ((Integer)parameters.elementAt(index)).intValue();
+    }
+
+    /**
+     * Gets the float-valued parameter found at the desired index
+     * in the vector of parameter values.
+     * 
+     * @param index the index
+     * 
+     * @return the float parameter
+     */
+    public float getFloatParameter(int index) {
+        return ((Float)parameters.elementAt(index)).floatValue();
+    }
+
+    /**
+     * Gets the double-valued parameter found at the desired index
+     * in the vector of parameter values.
+     * 
+     * @param index the index
+     * 
+     * @return the double parameter
+     */
+    public double getDoubleParameter(int index) {
+        return ((Double)parameters.elementAt(index)).doubleValue();
+    }
+
+    /**
+     * Gets the char-valued parameter found at the desired index
+     * in the vector of parameter values.
+     * 
+     * @param index the index
+     * 
+     * @return the char parameter
+     */
+    public char getCharParameter(int index) {
+        return ((Character)parameters.elementAt(index)).charValue();
+    }
+
+    /**
+     * Gets the byte-valued parameter found at the desired index
+     * in the vector of parameter values.
+     * 
+     * @param index the index
+     * 
+     * @return the byte parameter
+     */
+    public byte getByteParameter(int index) {
+        return ((Byte)parameters.elementAt(index)).byteValue();
+    }
+
+    /**
+     * Clears the vector of sources.
+     */
+    public void removeSources() {
+        sources.removeAllElements();
+    }
+
+    /**
+     * Clears the vector of parameters.
+     */
+    public void removeParameters() {
+        parameters.removeAllElements();
+    }
+
+    /**
+     * Gets the number of elements in the vector of sources.
+     * 
+     * @return the number of elements in the vector of sources
+     */
+    public int getNumSources() {
+        return sources.size();
+    }
+
+    /**
+     * Gets the number of elements in the vector of parameters.
+     * 
+     * @return the number of elements in the vector of parameters
+     */
+    public int getNumParameters() {
+        return parameters.size();
+    }
+}
diff --git a/awt/java/awt/image/renderable/RenderContext.java b/awt/java/awt/image/renderable/RenderContext.java
new file mode 100644
index 0000000..3a3b93c
--- /dev/null
+++ b/awt/java/awt/image/renderable/RenderContext.java
@@ -0,0 +1,196 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image.renderable;
+
+import java.awt.RenderingHints;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+
+/**
+ * The Class RenderContext stores data on how an image is to be 
+ * rendered: the affine transform, the area of interest, and 
+ * the rendering hints.
+ */
+public class RenderContext implements Cloneable {
+
+    /** The affine transform. */
+    AffineTransform transform;
+    
+    /** The area of interest. */
+    Shape aoi;
+    
+    /** The rendering hints. */
+    RenderingHints hints;
+
+    /**
+     * Instantiates a new render context.
+     * 
+     * @param usr2dev the affine transform
+     * @param aoi the area of interest
+     * @param hints the rendering hints
+     */
+    public RenderContext(AffineTransform usr2dev, Shape aoi, RenderingHints hints) {
+        this.transform = (AffineTransform)usr2dev.clone();
+        this.aoi = aoi;
+        this.hints = hints;
+    }
+
+    /**
+     * Instantiates a new render context with no specified hints.
+     * 
+     * @param usr2dev the affine transform
+     * @param aoi the area of interest
+     */
+    public RenderContext(AffineTransform usr2dev, Shape aoi) {
+        this(usr2dev, aoi, null);
+    }
+
+    /**
+     * Instantiates a new render context with no specified area of interest.
+     * 
+     * @param usr2dev the affine transform
+     * @param hints the rendering hints
+     */
+    public RenderContext(AffineTransform usr2dev, RenderingHints hints) {
+        this(usr2dev, null, hints);
+    }
+
+    /**
+     * Instantiates a new render context with no rendering hints or 
+     * area of interest.
+     * 
+     * @param usr2dev the affine transform
+     */
+    public RenderContext(AffineTransform usr2dev) {
+        this(usr2dev, null, null);
+    }
+
+    @Override
+    public Object clone() {
+        return new RenderContext(transform, aoi, hints);
+    }
+
+    /**
+     * Sets the affine transform for this render context.
+     * 
+     * @param newTransform the new affine transform
+     */
+    public void setTransform(AffineTransform newTransform) {
+        transform = (AffineTransform)newTransform.clone();
+    }
+
+    /**
+     * Concatenates the current transform with the specified transform
+     * (so they are applied with the specified transform acting first)
+     * and sets the resulting transform as the affine transform of 
+     * this rendering context.
+     * 
+     * @param modTransform the new transform which modifies the 
+     * current transform
+     * 
+     * @deprecated use {@link RenderContext#preConcatenateTransform(AffineTransform)}
+     */
+    @Deprecated    
+    public void preConcetenateTransform(AffineTransform modTransform) {
+        preConcatenateTransform(modTransform);
+    }
+
+    /**
+     * Concatenates the current transform with the specified transform
+     * (so they are applied with the specified transform acting first)
+     * and sets the resulting transform as the affine transform of 
+     * this rendering context.
+     * 
+     * @param modTransform the new transform which modifies the 
+     * current transform
+     */
+    public void preConcatenateTransform(AffineTransform modTransform) {
+        transform.preConcatenate(modTransform);
+    }
+
+    /**
+     * Concatenate the specified transform with the current transform.
+     * 
+     * @param modTransform the new transform which modifies the 
+     * current transform
+     * 
+     * @deprecated use {@link RenderContext#concatenateTransform(AffineTransform)}
+     */
+    @Deprecated
+    public void concetenateTransform(AffineTransform modTransform) {
+        concatenateTransform(modTransform);
+    }
+
+    /**
+     * Concatenate the specified transform with the current transform.
+     * 
+     * @param modTransform the new transform which modifies the 
+     * current transform
+     */
+    public void concatenateTransform(AffineTransform modTransform) {
+        transform.concatenate(modTransform);
+    }
+
+    /**
+     * Gets the transform.
+     * 
+     * @return the transform
+     */
+    public AffineTransform getTransform() {
+        return (AffineTransform)transform.clone();
+    }
+
+    /**
+     * Sets the area of interest.
+     * 
+     * @param newAoi the new area of interest
+     */
+    public void setAreaOfInterest(Shape newAoi) {
+        aoi = newAoi;
+    }
+
+    /**
+     * Gets the area of interest.
+     * 
+     * @return the area of interest
+     */
+    public Shape getAreaOfInterest() {
+        return aoi;
+    }
+
+    /**
+     * Sets the rendering hints.
+     * 
+     * @param hints the new rendering hints
+     */
+    public void setRenderingHints(RenderingHints hints) {
+        this.hints = hints;
+    }
+
+    /**
+     * Gets the rendering hints.
+     * 
+     * @return the rendering hints
+     */
+    public RenderingHints getRenderingHints() {
+        return hints;
+    }
+}
diff --git a/awt/java/awt/image/renderable/RenderableImage.java b/awt/java/awt/image/renderable/RenderableImage.java
new file mode 100644
index 0000000..885dc06
--- /dev/null
+++ b/awt/java/awt/image/renderable/RenderableImage.java
@@ -0,0 +1,132 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image.renderable;
+
+import java.awt.RenderingHints;
+import java.awt.image.RenderedImage;
+import java.util.Vector;
+
+/**
+ * The Interface RenderableImage is implemented by an object that
+ * collects all of the image-specific data that defines a single image 
+ * that could be rendered to different rendering targets.
+ */
+public interface RenderableImage {
+
+    /** The Constant HINTS_OBSERVED indicates that the rendering
+     * hints are applied rather than ignored. */
+    public static final String HINTS_OBSERVED = "HINTS_OBSERVED"; //$NON-NLS-1$
+
+    /**
+     * Gets the property from the RenderableImage's parameter block.
+     * 
+     * @param name the name of the property to get.
+     * 
+     * @return the value of the property
+     */
+    public Object getProperty(String name);
+
+    /**
+     * Creates the rendered image based on the information contained 
+     * in the parameters and the render context.
+     * 
+     * @param renderContext the render context giving rendering specifications
+     * such as transformations
+     * 
+     * @return the rendered image
+     */
+    public RenderedImage createRendering(RenderContext renderContext);
+
+    /**
+     * Creates the scaled rendered image based on the information contained 
+     * in the parameters and the render context.
+     * 
+     * @param w the desired width after scaling or zero if the scaling 
+     * should be proportional, based on the height
+     * @param h the desired height after scaling or zero if the scaling 
+     * should be proportional, based on the width
+     * @param hints the rendering hints to use
+     * 
+     * @return the rendered image
+     * 
+     * @throws IllegalArgumentException if both the height and width are zero
+     */
+    public RenderedImage createScaledRendering(int w, int h, RenderingHints hints);
+
+    /**
+     * Gets the vector of sources from the parameter block.
+     * 
+     * @return the sources
+     */
+    public Vector<RenderableImage> getSources();
+
+    /**
+     * Gets the names of all of the supported properties in the current context.
+     * 
+     * @return the property names
+     */
+    public String[] getPropertyNames();
+
+    /**
+     * Creates the default rendering (using the identity transform
+     * and default render context).
+     * 
+     * @return the rendered image
+     */
+    public RenderedImage createDefaultRendering();
+
+    /**
+     * Checks if this context supports dynamic rendering.
+     * 
+     * @return true, if this context supports dynamic rendering
+     */
+    public boolean isDynamic();
+
+    /**
+     * Gets the width of the image.
+     * 
+     * @return the width of the image
+     */
+    public float getWidth();
+
+    /**
+     * Gets the y coordinate of the upper left corner.
+     * 
+     * @return the y coordinate of the upper left corner
+     */
+    public float getMinY();
+
+    /**
+     * Gets the x coordinate of the upper left corner.
+     * 
+     * @return the x coordinate of the upper left corner
+     */
+    public float getMinX();
+
+    /**
+     * Gets the height of the image.
+     * 
+     * @return the height of the image
+     */
+    public float getHeight();
+
+}
+
diff --git a/awt/java/awt/image/renderable/RenderableImageOp.java b/awt/java/awt/image/renderable/RenderableImageOp.java
new file mode 100644
index 0000000..993ba5f
--- /dev/null
+++ b/awt/java/awt/image/renderable/RenderableImageOp.java
@@ -0,0 +1,182 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image.renderable;
+
+import java.awt.RenderingHints;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.RenderedImage;
+import java.util.Vector;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Class RenderableImageOp is a basic implementation of RenderableImage, 
+ * with methods to access the parameter data and perform rendering
+ * operations.
+ */
+public class RenderableImageOp implements RenderableImage {
+
+    /** The CRIF. */
+    ContextualRenderedImageFactory CRIF;
+    
+    /** The param block. */
+    ParameterBlock paramBlock;
+    
+    /** The height. */
+    float minX, minY, width, height;
+
+    /**
+     * Instantiates a new renderable image op.
+     * 
+     * @param CRIF the cRIF
+     * @param paramBlock the param block
+     */
+    public RenderableImageOp(ContextualRenderedImageFactory CRIF, ParameterBlock paramBlock) {
+        this.CRIF = CRIF;
+        this.paramBlock = (ParameterBlock) paramBlock.clone();
+        Rectangle2D r = CRIF.getBounds2D(paramBlock);
+        minX = (float) r.getMinX();
+        minY = (float) r.getMinY();
+        width = (float) r.getWidth();
+        height = (float) r.getHeight();
+    }
+
+    public Object getProperty(String name) {
+        return CRIF.getProperty(paramBlock, name);
+    }
+
+    /**
+     * Sets the parameter block.
+     * 
+     * @param paramBlock the param block
+     * 
+     * @return the parameter block
+     */
+    public ParameterBlock setParameterBlock(ParameterBlock paramBlock) {
+        ParameterBlock oldParam = this.paramBlock;
+        this.paramBlock = (ParameterBlock) paramBlock.clone();
+        return oldParam;
+    }
+
+    public RenderedImage createRendering(RenderContext renderContext) {
+
+        Vector<RenderableImage> sources = getSources();
+        ParameterBlock rdParam = (ParameterBlock) paramBlock.clone();
+
+        if (sources != null) {
+            Vector<Object> rdSources = new Vector<Object>();
+            int i = 0;
+            while (i < sources.size()) {
+                RenderContext newContext = CRIF.mapRenderContext(i, renderContext, paramBlock,
+                        this);
+                RenderedImage rdim = sources.elementAt(i).createRendering(newContext);
+
+                if (rdim != null) {
+                    rdSources.addElement(rdim);
+                }
+                i++;
+            }
+            if (rdSources.size() > 0) {
+                rdParam.setSources(rdSources);
+            }
+        }
+        return CRIF.create(renderContext, rdParam);
+    }
+
+    public RenderedImage createScaledRendering(int w, int h, RenderingHints hints) {
+        if(w == 0 && h == 0) {
+            // awt.60=Width and Height mustn't be equal zero both
+            throw new IllegalArgumentException(Messages.getString("awt.60")); //$NON-NLS-1$
+        }
+        if(w == 0){
+            w = Math.round(h*(getWidth()/getHeight()));
+        }
+
+        if(h == 0){
+            h = Math.round(w*(getHeight()/getWidth()));
+        }
+
+        double sx = (double)w/getWidth();
+        double sy = (double)h/getHeight();
+
+        AffineTransform at = AffineTransform.getScaleInstance(sx, sy);
+        RenderContext context = new RenderContext(at, hints);
+        return createRendering(context);
+    }
+
+    public Vector<RenderableImage> getSources() {
+        if(paramBlock.getNumSources() == 0) {
+            return null;
+        }
+        Vector<RenderableImage> v = new Vector<RenderableImage>();
+        int  i = 0;
+        while(i < paramBlock.getNumSources()){
+            Object o = paramBlock.getSource(i);
+            if(o instanceof RenderableImage){
+                v.addElement((RenderableImage) o);
+            }
+            i++;
+        }
+        return v;
+    }
+
+    public String[] getPropertyNames() {
+        return CRIF.getPropertyNames();
+    }
+
+    /**
+     * Gets the parameter block.
+     * 
+     * @return the parameter block
+     */
+    public ParameterBlock getParameterBlock() {
+        return paramBlock;
+    }
+
+    public RenderedImage createDefaultRendering() {
+        AffineTransform at = new AffineTransform();
+        RenderContext context = new RenderContext(at);
+        return createRendering(context);
+    }
+
+    public boolean isDynamic() {
+        return CRIF.isDynamic();
+    }
+
+    public float getWidth() {
+        return width;
+    }
+
+    public float getMinY() {
+        return minY;
+    }
+
+    public float getMinX() {
+        return minX;
+    }
+
+    public float getHeight() {
+        return height;
+    }
+
+}
+
diff --git a/awt/java/awt/image/renderable/RenderableImageProducer.java b/awt/java/awt/image/renderable/RenderableImageProducer.java
new file mode 100644
index 0000000..7fda98c
--- /dev/null
+++ b/awt/java/awt/image/renderable/RenderableImageProducer.java
@@ -0,0 +1,141 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image.renderable;
+
+import java.awt.image.ColorModel;
+import java.awt.image.ImageConsumer;
+import java.awt.image.ImageProducer;
+import java.awt.image.Raster;
+import java.awt.image.RenderedImage;
+import java.util.Vector;
+
+/**
+ * The Class RenderableImageProducer provides the implementation for 
+ * the image rendering.
+ */
+public class RenderableImageProducer implements ImageProducer, Runnable {
+
+    /** The rbl. */
+    RenderableImage rbl;
+    
+    /** The rc. */
+    RenderContext rc;
+    
+    /** The consumers. */
+    Vector<ImageConsumer> consumers = new Vector<ImageConsumer>();
+
+    /**
+     * Instantiates a new renderable image producer.
+     * 
+     * @param rdblImage the rdbl image
+     * @param rc the rc
+     */
+    public RenderableImageProducer(RenderableImage rdblImage, RenderContext rc) {
+        this.rbl = rdblImage;
+        this.rc = rc;
+    }
+
+    /**
+     * Sets the render context.
+     * 
+     * @param rc the new render context
+     */
+    public synchronized void setRenderContext(RenderContext rc) {
+        this.rc = rc;
+    }
+
+    public synchronized boolean isConsumer(ImageConsumer ic) {
+        return consumers.contains(ic);
+    }
+
+    public synchronized void startProduction(ImageConsumer ic) {
+        addConsumer(ic);
+        Thread t = new Thread(this, "RenderableImageProducer thread"); //$NON-NLS-1$
+        t.start();
+    }
+
+    public void requestTopDownLeftRightResend(ImageConsumer ic) {}
+
+    public synchronized void removeConsumer(ImageConsumer ic) {
+        if(ic != null) {
+            consumers.removeElement(ic);
+        }
+    }
+
+    public synchronized void addConsumer(ImageConsumer ic) {
+        if(ic != null && !consumers.contains(ic)){
+            consumers.addElement(ic);
+        }
+    }
+
+    /**
+     * Creates the rendered image in a new thread.
+     */
+    public void run() {
+        if(rbl == null) {
+            return;
+        }
+
+        RenderedImage rd;
+        if(rc != null) {
+            rd = rbl.createRendering(rc);
+        } else {
+            rd = rbl.createDefaultRendering();
+        }
+
+        ColorModel cm = rd.getColorModel();
+        if(cm == null) {
+            cm = ColorModel.getRGBdefault();
+        }
+
+        Raster r = rd.getData();
+        int w = r.getWidth();
+        int h = r.getHeight();
+
+        for (ImageConsumer c : consumers) {
+            c.setDimensions(w, h);
+            c.setHints(ImageConsumer.TOPDOWNLEFTRIGHT |
+                    ImageConsumer.COMPLETESCANLINES |
+                    ImageConsumer.SINGLEFRAME |
+                    ImageConsumer.SINGLEPASS);
+        }
+
+        int scanLine[] = new int[w];
+        int pixel[] = null;
+
+        for(int y = 0; y < h; y++){
+            for(int x = 0; x < w; x++){
+                pixel = r.getPixel(x, y, pixel);
+                scanLine[x] = cm.getDataElement(pixel, 0);
+            }
+
+            for (ImageConsumer c : consumers) {
+                c.setPixels(0, y, w, 1, cm, scanLine, 0, w);
+            }
+        }
+
+        for (ImageConsumer c : consumers) {
+            c.imageComplete(ImageConsumer.STATICIMAGEDONE);
+        }
+    }
+
+}
+
diff --git a/awt/java/awt/image/renderable/RenderedImageFactory.java b/awt/java/awt/image/renderable/RenderedImageFactory.java
new file mode 100644
index 0000000..345d82c
--- /dev/null
+++ b/awt/java/awt/image/renderable/RenderedImageFactory.java
@@ -0,0 +1,43 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+package java.awt.image.renderable;
+
+import java.awt.RenderingHints;
+import java.awt.image.RenderedImage;
+
+/**
+ * A factory for creating RenderedImage objects based on parameters
+ * and rendering hints.
+ */
+public interface RenderedImageFactory {
+
+    /**
+     * Creates the rendered image.
+     * 
+     * @param a0 the ParameterBlock
+     * @param a1 the RenderingHints
+     * 
+     * @return the rendered image
+     */
+    public RenderedImage create(ParameterBlock a0, RenderingHints a1);
+
+}
+
diff --git a/awt/java/awt/peer/ButtonPeer.java b/awt/java/awt/peer/ButtonPeer.java
new file mode 100644
index 0000000..cc45b49
--- /dev/null
+++ b/awt/java/awt/peer/ButtonPeer.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.peer;
+
+public interface ButtonPeer {
+
+}
diff --git a/awt/java/awt/peer/CanvasPeer.java b/awt/java/awt/peer/CanvasPeer.java
new file mode 100644
index 0000000..e276366
--- /dev/null
+++ b/awt/java/awt/peer/CanvasPeer.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.peer;
+
+public interface CanvasPeer {
+
+}
diff --git a/awt/java/awt/peer/CheckboxMenuItemPeer.java b/awt/java/awt/peer/CheckboxMenuItemPeer.java
new file mode 100644
index 0000000..296f422
--- /dev/null
+++ b/awt/java/awt/peer/CheckboxMenuItemPeer.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.peer;
+
+public interface CheckboxMenuItemPeer {
+
+}
diff --git a/awt/java/awt/peer/CheckboxPeer.java b/awt/java/awt/peer/CheckboxPeer.java
new file mode 100644
index 0000000..e9f8dd1
--- /dev/null
+++ b/awt/java/awt/peer/CheckboxPeer.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.peer;
+
+public interface CheckboxPeer {
+
+}
diff --git a/awt/java/awt/peer/ChoicePeer.java b/awt/java/awt/peer/ChoicePeer.java
new file mode 100644
index 0000000..57b7629
--- /dev/null
+++ b/awt/java/awt/peer/ChoicePeer.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.peer;
+
+public interface ChoicePeer {
+
+}
diff --git a/awt/java/awt/peer/ComponentPeer.java b/awt/java/awt/peer/ComponentPeer.java
new file mode 100644
index 0000000..bc26791
--- /dev/null
+++ b/awt/java/awt/peer/ComponentPeer.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.peer;
+
+public interface ComponentPeer {
+
+}
diff --git a/awt/java/awt/peer/DialogPeer.java b/awt/java/awt/peer/DialogPeer.java
new file mode 100644
index 0000000..8ae3049
--- /dev/null
+++ b/awt/java/awt/peer/DialogPeer.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.peer;
+
+public interface DialogPeer {
+
+}
diff --git a/awt/java/awt/peer/FileDialogPeer.java b/awt/java/awt/peer/FileDialogPeer.java
new file mode 100644
index 0000000..0d15e48
--- /dev/null
+++ b/awt/java/awt/peer/FileDialogPeer.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.peer;
+
+public interface FileDialogPeer {
+
+}
diff --git a/awt/java/awt/peer/FontPeer.java b/awt/java/awt/peer/FontPeer.java
new file mode 100644
index 0000000..fd9815f
--- /dev/null
+++ b/awt/java/awt/peer/FontPeer.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.peer;
+
+public interface FontPeer {
+
+}
diff --git a/awt/java/awt/peer/FramePeer.java b/awt/java/awt/peer/FramePeer.java
new file mode 100644
index 0000000..9cfc40b
--- /dev/null
+++ b/awt/java/awt/peer/FramePeer.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.peer;
+
+public interface FramePeer {
+
+}
diff --git a/awt/java/awt/peer/LabelPeer.java b/awt/java/awt/peer/LabelPeer.java
new file mode 100644
index 0000000..052ca9d
--- /dev/null
+++ b/awt/java/awt/peer/LabelPeer.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.peer;
+
+public interface LabelPeer {
+
+}
diff --git a/awt/java/awt/peer/LightweightPeer.java b/awt/java/awt/peer/LightweightPeer.java
new file mode 100644
index 0000000..1dee905
--- /dev/null
+++ b/awt/java/awt/peer/LightweightPeer.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.peer;
+
+public interface LightweightPeer {
+
+}
diff --git a/awt/java/awt/peer/ListPeer.java b/awt/java/awt/peer/ListPeer.java
new file mode 100644
index 0000000..0a27885
--- /dev/null
+++ b/awt/java/awt/peer/ListPeer.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.peer;
+
+public interface ListPeer {
+
+}
diff --git a/awt/java/awt/peer/MenuBarPeer.java b/awt/java/awt/peer/MenuBarPeer.java
new file mode 100644
index 0000000..3ad2c16
--- /dev/null
+++ b/awt/java/awt/peer/MenuBarPeer.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.peer;
+
+public interface MenuBarPeer {
+
+}
diff --git a/awt/java/awt/peer/MenuComponentPeer.java b/awt/java/awt/peer/MenuComponentPeer.java
new file mode 100644
index 0000000..3ac3b34
--- /dev/null
+++ b/awt/java/awt/peer/MenuComponentPeer.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.peer;
+
+public interface MenuComponentPeer {
+
+}
diff --git a/awt/java/awt/peer/MenuItemPeer.java b/awt/java/awt/peer/MenuItemPeer.java
new file mode 100644
index 0000000..b133897
--- /dev/null
+++ b/awt/java/awt/peer/MenuItemPeer.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.peer;
+
+public interface MenuItemPeer {
+
+}
diff --git a/awt/java/awt/peer/MenuPeer.java b/awt/java/awt/peer/MenuPeer.java
new file mode 100644
index 0000000..d643ce7
--- /dev/null
+++ b/awt/java/awt/peer/MenuPeer.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.peer;
+
+public interface MenuPeer {
+
+}
diff --git a/awt/java/awt/peer/MouseInfoPeer.java b/awt/java/awt/peer/MouseInfoPeer.java
new file mode 100644
index 0000000..9173a62
--- /dev/null
+++ b/awt/java/awt/peer/MouseInfoPeer.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.peer;
+
+public interface MouseInfoPeer {
+
+}
diff --git a/awt/java/awt/peer/PanelPeer.java b/awt/java/awt/peer/PanelPeer.java
new file mode 100644
index 0000000..1faa1fe
--- /dev/null
+++ b/awt/java/awt/peer/PanelPeer.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.peer;
+
+public interface PanelPeer {
+
+}
diff --git a/awt/java/awt/peer/PopupMenuPeer.java b/awt/java/awt/peer/PopupMenuPeer.java
new file mode 100644
index 0000000..cf1ef61
--- /dev/null
+++ b/awt/java/awt/peer/PopupMenuPeer.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.peer;
+
+public interface PopupMenuPeer {
+
+}
diff --git a/awt/java/awt/peer/ScrollPanePeer.java b/awt/java/awt/peer/ScrollPanePeer.java
new file mode 100644
index 0000000..df3de83
--- /dev/null
+++ b/awt/java/awt/peer/ScrollPanePeer.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.peer;
+
+public interface ScrollPanePeer {
+
+}
diff --git a/awt/java/awt/peer/ScrollbarPeer.java b/awt/java/awt/peer/ScrollbarPeer.java
new file mode 100644
index 0000000..eec8961
--- /dev/null
+++ b/awt/java/awt/peer/ScrollbarPeer.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.peer;
+
+public interface ScrollbarPeer {
+
+}
diff --git a/awt/java/awt/peer/TextAreaPeer.java b/awt/java/awt/peer/TextAreaPeer.java
new file mode 100644
index 0000000..636707f
--- /dev/null
+++ b/awt/java/awt/peer/TextAreaPeer.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.peer;
+
+public interface TextAreaPeer {
+
+}
diff --git a/awt/java/awt/peer/TextFieldPeer.java b/awt/java/awt/peer/TextFieldPeer.java
new file mode 100644
index 0000000..2b8232a
--- /dev/null
+++ b/awt/java/awt/peer/TextFieldPeer.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.peer;
+
+public interface TextFieldPeer {
+
+}
diff --git a/awt/java/awt/peer/WindowPeer.java b/awt/java/awt/peer/WindowPeer.java
new file mode 100644
index 0000000..384646f
--- /dev/null
+++ b/awt/java/awt/peer/WindowPeer.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Pavel Dolgov
+ * @version $Revision$
+ */
+package java.awt.peer;
+
+public interface WindowPeer {
+
+}
diff --git a/awt/java/beans/FeatureDescriptor.java b/awt/java/beans/FeatureDescriptor.java
new file mode 100644
index 0000000..2945c65
--- /dev/null
+++ b/awt/java/beans/FeatureDescriptor.java
@@ -0,0 +1,234 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package java.beans;
+
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+
+/**
+ * Common base class for Descriptors.
+ */
+public class FeatureDescriptor {
+
+    private Map<String, Object> values;
+
+    boolean preferred, hidden, expert;
+
+    String shortDescription;
+
+    String name;
+
+    String displayName;
+
+    /**
+     * <p>
+     * Constructs an instance.
+     * </p>
+     */
+    public FeatureDescriptor() {
+        this.values = new HashMap<String, Object>();
+    }
+
+    /**
+     * <p>
+     * Sets the value for the named attribute.
+     * </p>
+     * 
+     * @param attributeName
+     *            The name of the attribute to set a value with.
+     * @param value
+     *            The value to set.
+     */
+    public void setValue(String attributeName, Object value) {
+        if (attributeName == null || value == null) {
+            throw new NullPointerException();
+        }
+        values.put(attributeName, value);
+    }
+
+    /**
+     * <p>
+     * Gets the value associated with the named attribute.
+     * </p>
+     * 
+     * @param attributeName
+     *            The name of the attribute to get a value for.
+     * @return The attribute's value.
+     */
+    public Object getValue(String attributeName) {
+        Object result = null;
+        if (attributeName != null) {
+            result = values.get(attributeName);
+        }
+        return result;
+    }
+
+    /**
+     * <p>
+     * Enumerates the attribute names.
+     * </p>
+     * 
+     * @return An instance of {@link Enumeration}.
+     */
+    public Enumeration<String> attributeNames() {
+        // Create a new list, so that the references are copied
+        return Collections.enumeration(new LinkedList<String>(values.keySet()));
+    }
+
+    /**
+     * <p>
+     * Sets the short description.
+     * </p>
+     * 
+     * @param text
+     *            The description to set.
+     */
+    public void setShortDescription(String text) {
+        this.shortDescription = text;
+    }
+
+    /**
+     * <p>
+     * Sets the name.
+     * </p>
+     * 
+     * @param name
+     *            The name to set.
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    /**
+     * <p>
+     * Sets the display name.
+     * </p>
+     * 
+     * @param displayName
+     *            The display name to set.
+     */
+    public void setDisplayName(String displayName) {
+        this.displayName = displayName;
+    }
+
+    /**
+     * <p>
+     * Gets the short description or {@link #getDisplayName()} if not set.
+     * </p>
+     * 
+     * @return The description.
+     */
+    public String getShortDescription() {
+        return shortDescription == null ? getDisplayName() : shortDescription;
+    }
+
+    /**
+     * <p>
+     * Gets the name.
+     * </p>
+     * 
+     * @return The name.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * <p>
+     * Gets the display name or {@link #getName()} if not set.
+     * </p>
+     * 
+     * @return The display name.
+     */
+    public String getDisplayName() {
+        return displayName == null ? getName() : displayName;
+    }
+
+    /**
+     * <p>
+     * Sets the preferred indicator.
+     * </p>
+     * 
+     * @param preferred
+     *            <code>true</code> if preferred, <code>false</code>
+     *            otherwise.
+     */
+    public void setPreferred(boolean preferred) {
+        this.preferred = preferred;
+    }
+
+    /**
+     * <p>
+     * Sets the hidden indicator.
+     * </p>
+     * 
+     * @param hidden
+     *            <code>true</code> if hidden, <code>false</code> otherwise.
+     */
+    public void setHidden(boolean hidden) {
+        this.hidden = hidden;
+    }
+
+    /**
+     * <p>
+     * Sets the expert indicator.
+     * </p>
+     * 
+     * @param expert
+     *            <code>true</code> if expert, <code>false</code> otherwise.
+     */
+    public void setExpert(boolean expert) {
+        this.expert = expert;
+    }
+
+    /**
+     * <p>
+     * Indicates if this feature is preferred.
+     * </p>
+     * 
+     * @return <code>true</code> if preferred, <code>false</code> otherwise.
+     */
+    public boolean isPreferred() {
+        return preferred;
+    }
+
+    /**
+     * <p>
+     * Indicates if this feature is hidden.
+     * </p>
+     * 
+     * @return <code>true</code> if hidden, <code>false</code> otherwise.
+     */
+    public boolean isHidden() {
+        return hidden;
+    }
+
+    /**
+     * <p>
+     * Indicates if this feature is an expert feature.
+     * </p>
+     * 
+     * @return <code>true</code> if hidden, <code>false</code> otherwise.
+     */
+    public boolean isExpert() {
+        return expert;
+    }
+}
diff --git a/awt/java/beans/IndexedPropertyChangeEvent.java b/awt/java/beans/IndexedPropertyChangeEvent.java
new file mode 100644
index 0000000..c9084c6
--- /dev/null
+++ b/awt/java/beans/IndexedPropertyChangeEvent.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package java.beans;
+
+/**
+ * A type of {@link PropertyChangeEvent} that indicates that an indexed property
+ * has changed.
+ * 
+ * @since 1.5
+ */
+public class IndexedPropertyChangeEvent extends PropertyChangeEvent {
+
+    private static final long serialVersionUID = -320227448495806870L;
+
+    private final int index;
+
+    /**
+     * Creates a new property changed event with an indication of the property
+     * index.
+     * 
+     * @param source
+     *            the changed bean.
+     * @param propertyName
+     *            the changed property, or <code>null</code> to indicate an
+     *            unspecified set of the properties have changed.
+     * @param oldValue
+     *            the previous value of the property, or <code>null</code> if
+     *            the <code>propertyName</code> is <code>null</code> or the
+     *            previous value is unknown.
+     * @param newValue
+     *            the new value of the property, or <code>null</code> if the
+     *            <code>propertyName</code> is <code>null</code> or the new
+     *            value is unknown..
+     * @param index
+     *            the index of the property.
+     */
+    public IndexedPropertyChangeEvent(Object source, String propertyName,
+            Object oldValue, Object newValue, int index) {
+        super(source, propertyName, oldValue, newValue);
+        this.index = index;
+    }
+
+    /**
+     * Answer the index of the property that was changed in this event.
+     * 
+     * @return The property element index.
+     */
+    public int getIndex() {
+        return index;
+    }
+}
diff --git a/awt/java/beans/IndexedPropertyDescriptor.java b/awt/java/beans/IndexedPropertyDescriptor.java
new file mode 100644
index 0000000..25667d9
--- /dev/null
+++ b/awt/java/beans/IndexedPropertyDescriptor.java
@@ -0,0 +1,227 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package java.beans;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import org.apache.harmony.beans.internal.nls.Messages;
+
+public class IndexedPropertyDescriptor extends PropertyDescriptor {
+    private Method indexedGetter;
+
+    private Method indexedSetter;
+
+    public IndexedPropertyDescriptor(String propertyName, Class<?> beanClass,
+            String getterName, String setterName, String indexedGetterName,
+            String indexedSetterName) throws IntrospectionException {
+        super(propertyName, beanClass, getterName, setterName);
+
+        // RI behaves like this
+        if (indexedGetterName == null && indexedSetterName == null &&
+                (getterName != null || setterName != null)) {
+            throw new IntrospectionException(Messages.getString("beans.50"));
+        }
+        setIndexedReadMethod(beanClass, indexedGetterName);
+        setIndexedWriteMethod(beanClass, indexedSetterName);
+    }
+
+    public IndexedPropertyDescriptor(String propertyName, Method getter, Method setter,
+            Method indexedGetter, Method indexedSetter) throws IntrospectionException {
+        super(propertyName, getter, setter);
+        
+        // we need this in order to be compatible with RI
+        if (indexedGetter == null && indexedSetter == null &&
+                (getter != null || setter != null)) {
+            throw new IntrospectionException(Messages.getString("beans.50"));
+        }
+        setIndexedReadMethod(indexedGetter);
+        setIndexedWriteMethod(indexedSetter);
+    }
+
+    public IndexedPropertyDescriptor(String propertyName, Class<?> beanClass)
+            throws IntrospectionException {
+        super(propertyName, beanClass, null, null);
+        String getterName;
+        String setterName;
+        String indexedGetterName;
+        String indexedSetterName;
+
+        // array getter
+        getterName = createDefaultMethodName(propertyName, "get"); //$NON-NLS-1$
+        if (hasMethod(beanClass, getterName)) {
+            setReadMethod(beanClass, getterName);
+        }
+        // array setter
+        setterName = createDefaultMethodName(propertyName, "set"); //$NON-NLS-1$
+        if (hasMethod(beanClass, setterName)) {
+            setWriteMethod(beanClass, setterName);
+        }
+        // indexed getter
+        indexedGetterName = createDefaultMethodName(propertyName, "get"); //$NON-NLS-1$
+        if (hasMethod(beanClass, indexedGetterName)) {
+            setIndexedReadMethod(beanClass, indexedGetterName);
+        }
+        // indexed setter
+        indexedSetterName = createDefaultMethodName(propertyName, "set"); //$NON-NLS-1$
+        if (hasMethod(beanClass, indexedSetterName)) {
+            setIndexedWriteMethod(beanClass, indexedSetterName);
+        }
+        // RI seems to behave a bit differently
+        if (indexedGetter == null && indexedSetter == null &&
+                getReadMethod() == null && getWriteMethod() == null) {
+            throw new IntrospectionException(
+                    Messages.getString("beans.01", propertyName)); //$NON-NLS-1$
+        }
+        if (indexedGetter == null && indexedSetter == null) {
+            // not an indexed property indeed
+            throw new IntrospectionException(Messages.getString("beans.50"));
+        }
+    }
+
+    public void setIndexedReadMethod(Method indexedGetter) throws IntrospectionException {
+        if (indexedGetter != null) {
+            int modifiers = indexedGetter.getModifiers();
+            Class<?>[] parameterTypes;
+            Class<?> returnType;
+            Class<?> indexedPropertyType;
+
+            if (!Modifier.isPublic(modifiers)) {
+                throw new IntrospectionException(Messages.getString("beans.21")); //$NON-NLS-1$
+            }
+            parameterTypes = indexedGetter.getParameterTypes();
+            if (parameterTypes.length != 1) {
+                throw new IntrospectionException(Messages.getString("beans.22")); //$NON-NLS-1$
+            }
+            if (!parameterTypes[0].equals(int.class)) {
+                throw new IntrospectionException(Messages.getString("beans.23")); //$NON-NLS-1$
+            }
+            returnType = indexedGetter.getReturnType();
+            indexedPropertyType = getIndexedPropertyType();
+            if ((indexedPropertyType != null) && !returnType.equals(indexedPropertyType)) {
+                throw new IntrospectionException(Messages.getString("beans.24")); //$NON-NLS-1$
+            }
+        }
+        this.indexedGetter = indexedGetter;
+    }
+
+    public void setIndexedWriteMethod(Method indexedSetter) throws IntrospectionException {
+        if (indexedSetter != null) {
+            int modifiers = indexedSetter.getModifiers();
+            Class<?>[] parameterTypes;
+            Class<?> firstParameterType;
+            Class<?> secondParameterType;
+            Class<?> propType;
+
+            if (!Modifier.isPublic(modifiers)) {
+                throw new IntrospectionException(Messages.getString("beans.25")); //$NON-NLS-1$
+            }
+            parameterTypes = indexedSetter.getParameterTypes();
+            if (parameterTypes.length != 2) {
+                throw new IntrospectionException(Messages.getString("beans.26")); //$NON-NLS-1$
+            }
+            firstParameterType = parameterTypes[0];
+            if (!firstParameterType.equals(int.class)) {
+                throw new IntrospectionException(Messages.getString("beans.27")); //$NON-NLS-1$
+            }
+            secondParameterType = parameterTypes[1];
+            propType = getIndexedPropertyType();
+            if (propType != null && !secondParameterType.equals(propType)) {
+                throw new IntrospectionException(Messages.getString("beans.28")); //$NON-NLS-1$
+            }
+        }
+        this.indexedSetter = indexedSetter;
+    }
+
+    public Method getIndexedWriteMethod() {
+        return indexedSetter;
+    }
+
+    public Method getIndexedReadMethod() {
+        return indexedGetter;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        boolean result = super.equals(obj);
+        
+        if (result) {
+            IndexedPropertyDescriptor pd = (IndexedPropertyDescriptor) obj;
+    
+            if (indexedGetter != null) {
+                result = indexedGetter.equals(pd.getIndexedReadMethod());
+            } else if (result && indexedGetter == null) {
+                result = pd.getIndexedReadMethod() == null;
+            }
+                
+            if (result) {
+                if (indexedSetter != null) {
+                    result = indexedSetter.equals(pd.getIndexedWriteMethod());
+                } else if (indexedSetter == null) {
+                    result = pd.getIndexedWriteMethod() == null;
+                }
+            }
+        }
+            
+        return result;
+    }
+
+    public Class<?> getIndexedPropertyType() {
+        Class<?> result = null;
+
+        if (indexedGetter != null) {
+            result = indexedGetter.getReturnType();
+        } else if (indexedSetter != null) {
+            Class<?>[] parameterTypes = indexedSetter.getParameterTypes();
+
+            result = parameterTypes[1];
+        }
+        return result;
+    }
+
+    private void setIndexedReadMethod(Class<?> beanClass, String indexedGetterName) {
+        Method[] getters = findMethods(beanClass, indexedGetterName);
+        boolean result = false;
+
+        for (Method element : getters) {
+            try {
+                setIndexedReadMethod(element);
+                result = true;
+            } catch (IntrospectionException ie) {}
+
+            if (result) {
+                break;
+            }
+        }
+    }
+
+    private void setIndexedWriteMethod(Class<?> beanClass, String indexedSetterName) {
+        Method[] setters = findMethods(beanClass, indexedSetterName);
+        boolean result = false;
+
+        for (Method element : setters) {
+            try {
+                setIndexedWriteMethod(element);
+                result = true;
+            } catch (IntrospectionException ie) {}
+
+            if (result) {
+                break;
+            }
+        }
+    }
+}
diff --git a/awt/java/beans/IntrospectionException.java b/awt/java/beans/IntrospectionException.java
new file mode 100644
index 0000000..c895afe
--- /dev/null
+++ b/awt/java/beans/IntrospectionException.java
@@ -0,0 +1,27 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package java.beans;
+
+public class IntrospectionException extends Exception {
+
+    static final long serialVersionUID = -3728150539969542619L;
+
+    public IntrospectionException(String message) {
+        super(message);
+    }
+}
diff --git a/awt/java/beans/PropertyChangeEvent.java b/awt/java/beans/PropertyChangeEvent.java
new file mode 100644
index 0000000..97c703a
--- /dev/null
+++ b/awt/java/beans/PropertyChangeEvent.java
@@ -0,0 +1,62 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package java.beans;
+
+import java.util.EventObject;
+
+public class PropertyChangeEvent extends EventObject {
+
+    private static final long serialVersionUID = 7042693688939648123L;
+
+    String propertyName;
+
+    Object oldValue;
+
+    Object newValue;
+
+    Object propagationId;
+
+    public PropertyChangeEvent(Object source, String propertyName,
+            Object oldValue, Object newValue) {
+        super(source);
+
+        this.propertyName = propertyName;
+        this.oldValue = oldValue;
+        this.newValue = newValue;
+    }
+
+    public String getPropertyName() {
+        return propertyName;
+    }
+
+    public void setPropagationId(Object propagationId) {
+        this.propagationId = propagationId;
+    }
+
+    public Object getPropagationId() {
+        return propagationId;
+    }
+
+    public Object getOldValue() {
+        return oldValue;
+    }
+
+    public Object getNewValue() {
+        return newValue;
+    }
+}
diff --git a/awt/java/beans/PropertyChangeListener.java b/awt/java/beans/PropertyChangeListener.java
new file mode 100644
index 0000000..94422c0
--- /dev/null
+++ b/awt/java/beans/PropertyChangeListener.java
@@ -0,0 +1,25 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package java.beans;
+
+import java.util.EventListener;
+
+public interface PropertyChangeListener extends EventListener {
+
+    public void propertyChange(PropertyChangeEvent event);
+}
diff --git a/awt/java/beans/PropertyChangeListenerProxy.java b/awt/java/beans/PropertyChangeListenerProxy.java
new file mode 100644
index 0000000..f4f3aec
--- /dev/null
+++ b/awt/java/beans/PropertyChangeListenerProxy.java
@@ -0,0 +1,41 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package java.beans;
+
+import java.util.EventListenerProxy;
+
+public class PropertyChangeListenerProxy extends EventListenerProxy implements
+        PropertyChangeListener {
+
+    String propertyName;
+
+    public PropertyChangeListenerProxy(String propertyName,
+            PropertyChangeListener listener) {
+        super(listener);
+        this.propertyName = propertyName;
+    }
+
+    public String getPropertyName() {
+        return propertyName;
+    }
+
+    public void propertyChange(PropertyChangeEvent event) {
+        PropertyChangeListener listener = (PropertyChangeListener) getListener();
+        listener.propertyChange(event);
+    }
+}
diff --git a/awt/java/beans/PropertyChangeSupport.java b/awt/java/beans/PropertyChangeSupport.java
new file mode 100644
index 0000000..d56e63a
--- /dev/null
+++ b/awt/java/beans/PropertyChangeSupport.java
@@ -0,0 +1,351 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package java.beans;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+public class PropertyChangeSupport implements Serializable {
+
+    private static final long serialVersionUID = 6401253773779951803l;
+
+    private transient Object sourceBean;
+
+    private transient List<PropertyChangeListener> allPropertiesChangeListeners =
+            new ArrayList<PropertyChangeListener>();
+
+    private transient Map<String, List<PropertyChangeListener>>
+            selectedPropertiesChangeListeners =
+            new HashMap<String, List<PropertyChangeListener>>();
+
+    // fields for serialization compatibility
+    private Hashtable<String, List<PropertyChangeListener>> children;
+
+    private Object source;
+
+    private int propertyChangeSupportSerializedDataVersion = 1;
+
+    public PropertyChangeSupport(Object sourceBean) {
+        if (sourceBean == null) {
+            throw new NullPointerException();
+        }
+        this.sourceBean = sourceBean;
+    }
+
+    public void firePropertyChange(String propertyName, Object oldValue,
+            Object newValue) {
+        PropertyChangeEvent event = createPropertyChangeEvent(propertyName,
+                oldValue, newValue);
+        doFirePropertyChange(event);
+    }
+
+    public void fireIndexedPropertyChange(String propertyName, int index,
+            Object oldValue, Object newValue) {
+
+        // nulls and equals check done in doFire...
+        doFirePropertyChange(new IndexedPropertyChangeEvent(sourceBean,
+                propertyName, oldValue, newValue, index));
+    }
+
+    public synchronized void removePropertyChangeListener(String propertyName,
+            PropertyChangeListener listener) {
+        if ((propertyName != null) && (listener != null)) {
+            List<PropertyChangeListener> listeners =
+                    selectedPropertiesChangeListeners.get(propertyName);
+
+            if (listeners != null) {
+                listeners.remove(listener);
+            }
+        }
+    }
+
+    public synchronized void addPropertyChangeListener(String propertyName,
+            PropertyChangeListener listener) {
+        if ((listener != null) && (propertyName != null)) {
+            List<PropertyChangeListener> listeners =
+                    selectedPropertiesChangeListeners.get(propertyName);
+
+            if (listeners == null) {
+                listeners = new ArrayList<PropertyChangeListener>();
+                selectedPropertiesChangeListeners.put(propertyName, listeners);
+            }
+
+            // RI compatibility
+            if (listener instanceof PropertyChangeListenerProxy) {
+                PropertyChangeListenerProxy proxy =
+                        (PropertyChangeListenerProxy) listener;
+
+                listeners.add(new PropertyChangeListenerProxy(
+                        proxy.getPropertyName(),
+                        (PropertyChangeListener) proxy.getListener()));
+            } else {
+                listeners.add(listener);
+            }
+        }
+    }
+
+    public synchronized PropertyChangeListener[] getPropertyChangeListeners(
+            String propertyName) {
+        List<PropertyChangeListener> listeners = null;
+
+        if (propertyName != null) {
+            listeners = selectedPropertiesChangeListeners.get(propertyName);
+        }
+
+        return (listeners == null) ? new PropertyChangeListener[] {}
+                : listeners.toArray(
+                        new PropertyChangeListener[listeners.size()]);
+    }
+
+    public void firePropertyChange(String propertyName, boolean oldValue,
+            boolean newValue) {
+        PropertyChangeEvent event = createPropertyChangeEvent(propertyName,
+                oldValue, newValue);
+        doFirePropertyChange(event);
+    }
+
+    public void fireIndexedPropertyChange(String propertyName, int index,
+            boolean oldValue, boolean newValue) {
+
+        if (oldValue != newValue) {
+            fireIndexedPropertyChange(propertyName, index, Boolean
+                    .valueOf(oldValue), Boolean.valueOf(newValue));
+        }
+    }
+
+    public void firePropertyChange(String propertyName, int oldValue,
+            int newValue) {
+        PropertyChangeEvent event = createPropertyChangeEvent(propertyName,
+                oldValue, newValue);
+        doFirePropertyChange(event);
+    }
+
+    public void fireIndexedPropertyChange(String propertyName, int index,
+            int oldValue, int newValue) {
+
+        if (oldValue != newValue) {
+            fireIndexedPropertyChange(propertyName, index,
+                    new Integer(oldValue), new Integer(newValue));
+        }
+    }
+
+    public synchronized boolean hasListeners(String propertyName) {
+        boolean result = allPropertiesChangeListeners.size() > 0;
+        if (!result && (propertyName != null)) {
+            List<PropertyChangeListener> listeners =
+                    selectedPropertiesChangeListeners.get(propertyName);
+            if (listeners != null) {
+                result = listeners.size() > 0;
+            }
+        }
+        return result;
+    }
+
+    public synchronized void removePropertyChangeListener(
+            PropertyChangeListener listener) {
+        if (listener != null) {
+            if (listener instanceof PropertyChangeListenerProxy) {
+                String name = ((PropertyChangeListenerProxy) listener)
+                        .getPropertyName();
+                PropertyChangeListener lst = (PropertyChangeListener)
+                        ((PropertyChangeListenerProxy) listener).getListener();
+
+                removePropertyChangeListener(name, lst);
+            } else {
+                allPropertiesChangeListeners.remove(listener);
+            }
+        }
+    }
+
+    public synchronized void addPropertyChangeListener(
+            PropertyChangeListener listener) {
+        if (listener != null) {
+            if (listener instanceof PropertyChangeListenerProxy) {
+                String name = ((PropertyChangeListenerProxy) listener)
+                        .getPropertyName();
+                PropertyChangeListener lst = (PropertyChangeListener)
+                        ((PropertyChangeListenerProxy) listener).getListener();
+                addPropertyChangeListener(name, lst);
+            } else {
+                allPropertiesChangeListeners.add(listener);
+            }
+        }
+    }
+
+    public synchronized PropertyChangeListener[] getPropertyChangeListeners() {
+        ArrayList<PropertyChangeListener> result =
+                new ArrayList<PropertyChangeListener>(
+                        allPropertiesChangeListeners);
+
+        for (String propertyName : selectedPropertiesChangeListeners.keySet()) {
+            List<PropertyChangeListener> selectedListeners =
+                    selectedPropertiesChangeListeners.get(propertyName);
+
+            if (selectedListeners != null) {
+
+                for (PropertyChangeListener listener : selectedListeners) {
+                    result.add(new PropertyChangeListenerProxy(propertyName,
+                            listener));
+                }
+            }
+        }
+
+        return result.toArray(new PropertyChangeListener[result.size()]);
+    }
+
+    private void writeObject(ObjectOutputStream oos) throws IOException {
+        List<PropertyChangeListener> allSerializedPropertiesChangeListeners =
+                new ArrayList<PropertyChangeListener>();
+
+        for (PropertyChangeListener pcl : allPropertiesChangeListeners) {
+            if (pcl instanceof Serializable) {
+                allSerializedPropertiesChangeListeners.add(pcl);
+            }
+        }
+
+        Map<String, List<PropertyChangeListener>>
+                selectedSerializedPropertiesChangeListeners =
+                        new HashMap<String, List<PropertyChangeListener>>();
+
+        for (String propertyName : selectedPropertiesChangeListeners.keySet()) {
+            List<PropertyChangeListener> keyValues =
+                    selectedPropertiesChangeListeners.get(propertyName);
+
+            if (keyValues != null) {
+                List<PropertyChangeListener> serializedPropertiesChangeListeners
+                        = new ArrayList<PropertyChangeListener>();
+
+                for (PropertyChangeListener pcl : keyValues) {
+                    if (pcl instanceof Serializable) {
+                        serializedPropertiesChangeListeners.add(pcl);
+                    }
+                }
+
+                if (!serializedPropertiesChangeListeners.isEmpty()) {
+                    selectedSerializedPropertiesChangeListeners.put(
+                            propertyName, serializedPropertiesChangeListeners);
+                }
+            }
+        }
+
+        children = new Hashtable<String, List<PropertyChangeListener>>(
+                selectedSerializedPropertiesChangeListeners);
+        children.put("", allSerializedPropertiesChangeListeners); //$NON-NLS-1$
+        oos.writeObject(children);
+
+        Object source = null;
+        if (sourceBean instanceof Serializable) {
+            source = sourceBean;
+        }
+        oos.writeObject(source);
+
+        oos.writeInt(propertyChangeSupportSerializedDataVersion);
+    }
+
+    @SuppressWarnings("unchecked")
+    private void readObject(ObjectInputStream ois) throws IOException,
+            ClassNotFoundException {
+        children = (Hashtable<String, List<PropertyChangeListener>>) ois
+                .readObject();
+
+        selectedPropertiesChangeListeners = new HashMap<String, List<PropertyChangeListener>>(
+                children);
+        allPropertiesChangeListeners = selectedPropertiesChangeListeners
+                .remove(""); //$NON-NLS-1$
+        if (allPropertiesChangeListeners == null) {
+            allPropertiesChangeListeners = new ArrayList<PropertyChangeListener>();
+        }
+
+        sourceBean = ois.readObject();
+        propertyChangeSupportSerializedDataVersion = ois.readInt();
+    }
+
+    public void firePropertyChange(PropertyChangeEvent event) {
+        doFirePropertyChange(event);
+    }
+
+    private PropertyChangeEvent createPropertyChangeEvent(String propertyName,
+            Object oldValue, Object newValue) {
+        return new PropertyChangeEvent(sourceBean, propertyName, oldValue,
+                newValue);
+    }
+
+    private PropertyChangeEvent createPropertyChangeEvent(String propertyName,
+            boolean oldValue, boolean newValue) {
+        return new PropertyChangeEvent(sourceBean, propertyName, oldValue,
+                newValue);
+    }
+
+    private PropertyChangeEvent createPropertyChangeEvent(String propertyName,
+            int oldValue, int newValue) {
+        return new PropertyChangeEvent(sourceBean, propertyName, oldValue,
+                newValue);
+    }
+
+    private void doFirePropertyChange(PropertyChangeEvent event) {
+        String propertyName = event.getPropertyName();
+        Object oldValue = event.getOldValue();
+        Object newValue = event.getNewValue();
+
+        if ((newValue != null) && (oldValue != null)
+                && newValue.equals(oldValue)) {
+            return;
+        }
+
+        /*
+         * Copy the listeners collections so they can be modified while we fire
+         * events.
+         */
+
+        // Listeners to all property change events
+        PropertyChangeListener[] listensToAll;
+        // Listens to a given property change
+        PropertyChangeListener[] listensToOne = null;
+        synchronized (this) {
+            listensToAll = allPropertiesChangeListeners
+                    .toArray(new PropertyChangeListener[allPropertiesChangeListeners
+                            .size()]);
+
+            List<PropertyChangeListener> listeners = selectedPropertiesChangeListeners
+                    .get(propertyName);
+            if (listeners != null) {
+                listensToOne = listeners
+                        .toArray(new PropertyChangeListener[listeners.size()]);
+            }
+        }
+
+        // Fire the listeners
+        for (PropertyChangeListener listener : listensToAll) {
+            listener.propertyChange(event);
+        }
+        if (listensToOne != null) {
+            for (PropertyChangeListener listener : listensToOne) {
+                listener.propertyChange(event);
+            }
+        }
+    }
+
+}
diff --git a/awt/java/beans/PropertyDescriptor.java b/awt/java/beans/PropertyDescriptor.java
new file mode 100644
index 0000000..9389152
--- /dev/null
+++ b/awt/java/beans/PropertyDescriptor.java
@@ -0,0 +1,300 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package java.beans;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Vector;
+import org.apache.harmony.beans.internal.nls.Messages;
+
+public class PropertyDescriptor extends FeatureDescriptor {
+    private Method getter;
+
+    private Method setter;
+
+    private Class<?> propertyEditorClass;
+
+    private boolean constrained;
+
+    private boolean bound;
+
+    public PropertyDescriptor(String propertyName, Class<?> beanClass, String getterName,
+            String setterName) throws IntrospectionException {
+        super();
+        if (beanClass == null) {
+            throw new IntrospectionException(Messages.getString("beans.03")); //$NON-NLS-1$
+        }
+        if (propertyName == null || propertyName.length() == 0) {
+            throw new IntrospectionException(Messages.getString("beans.04")); //$NON-NLS-1$
+        }
+        this.setName(propertyName);
+        this.setDisplayName(propertyName);
+        if (setterName != null) {
+            if (hasMethod(beanClass, setterName)) {
+                setWriteMethod(beanClass, setterName);
+            } else {
+                throw new IntrospectionException(Messages.getString("beans.20")); //$NON-NLS-1$
+            }
+        }
+        if (getterName != null) {
+            if (hasMethod(beanClass, getterName)) {
+                setReadMethod(beanClass, getterName);
+            } else {
+                throw new IntrospectionException(Messages.getString("beans.1F")); //$NON-NLS-1$
+            }
+        }
+    }
+
+    public PropertyDescriptor(String propertyName, Method getter, Method setter)
+            throws IntrospectionException {
+        super();
+        if (propertyName == null || propertyName.length() == 0) {
+            throw new IntrospectionException(Messages.getString("beans.04")); //$NON-NLS-1$
+        }
+        this.setName(propertyName);
+        this.setDisplayName(propertyName);
+        setWriteMethod(setter);
+        setReadMethod(getter);
+    }
+
+    public PropertyDescriptor(String propertyName, Class<?> beanClass)
+            throws IntrospectionException {
+        String getterName;
+        String setterName;
+        if (beanClass == null) {
+            throw new IntrospectionException(Messages.getString("beans.03")); //$NON-NLS-1$
+        }
+        if (propertyName == null || propertyName.length() == 0) {
+            throw new IntrospectionException(Messages.getString("beans.04")); //$NON-NLS-1$
+        }
+        this.setName(propertyName);
+        this.setDisplayName(propertyName);
+        getterName = createDefaultMethodName(propertyName, "is"); //$NON-NLS-1$
+        if (hasMethod(beanClass, getterName)) {
+            setReadMethod(beanClass, getterName);
+        } else {
+            getterName = createDefaultMethodName(propertyName, "get"); //$NON-NLS-1$
+            if (hasMethod(beanClass, getterName)) {
+                setReadMethod(beanClass, getterName);
+            }
+        }
+        setterName = createDefaultMethodName(propertyName, "set"); //$NON-NLS-1$
+        if (hasMethod(beanClass, setterName)) {
+            setWriteMethod(beanClass, setterName);
+        }
+        if (getter == null && setter == null) {
+            throw new IntrospectionException(Messages.getString("beans.01", propertyName)); //$NON-NLS-1$
+        }
+    }
+
+    public void setWriteMethod(Method setter) throws IntrospectionException {
+        if (setter != null) {
+            int modifiers = setter.getModifiers();
+            if (!Modifier.isPublic(modifiers)) {
+                throw new IntrospectionException(Messages.getString("beans.05")); //$NON-NLS-1$
+            }
+            Class<?>[] parameterTypes = setter.getParameterTypes();
+            if (parameterTypes.length != 1) {
+                throw new IntrospectionException(Messages.getString("beans.06")); //$NON-NLS-1$
+            }
+            Class<?> parameterType = parameterTypes[0];
+            Class<?> propertyType = getPropertyType();
+            if (propertyType != null && !propertyType.equals(parameterType)) {
+                throw new IntrospectionException(Messages.getString("beans.07")); //$NON-NLS-1$
+            }
+        }
+        this.setter = setter;
+    }
+
+    public void setReadMethod(Method getter) throws IntrospectionException {
+        if (getter != null) {
+            int modifiers = getter.getModifiers();
+            if (!Modifier.isPublic(modifiers)) {
+                throw new IntrospectionException(Messages.getString("beans.0A")); //$NON-NLS-1$
+            }
+            Class<?>[] parameterTypes = getter.getParameterTypes();
+            if (parameterTypes.length != 0) {
+                throw new IntrospectionException(Messages.getString("beans.08")); //$NON-NLS-1$
+            }
+            Class<?> returnType = getter.getReturnType();
+            if (returnType.equals(Void.TYPE)) {
+                throw new IntrospectionException(Messages.getString("beans.33")); //$NON-NLS-1$
+            }
+            Class<?> propertyType = getPropertyType();
+            if ((propertyType != null) && !returnType.equals(propertyType)) {
+                throw new IntrospectionException(Messages.getString("beans.09")); //$NON-NLS-1$
+            }
+        }
+        this.getter = getter;
+    }
+
+    public Method getWriteMethod() {
+        return setter;
+    }
+
+    public Method getReadMethod() {
+        return getter;
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        boolean result = (object != null && object instanceof PropertyDescriptor);
+        if (result) {
+            PropertyDescriptor pd = (PropertyDescriptor) object;
+            boolean gettersAreEqual = (this.getter == null) && (pd.getReadMethod() == null)
+                    || (this.getter != null) && (this.getter.equals(pd.getReadMethod()));
+            boolean settersAreEqual = (this.setter == null) && (pd.getWriteMethod() == null)
+                    || (this.setter != null) && (this.setter.equals(pd.getWriteMethod()));
+            boolean propertyTypesAreEqual = this.getPropertyType() == pd.getPropertyType();
+            boolean propertyEditorClassesAreEqual = this.getPropertyEditorClass() == pd
+                    .getPropertyEditorClass();
+            boolean boundPropertyAreEqual = this.isBound() == pd.isBound();
+            boolean constrainedPropertyAreEqual = this.isConstrained() == pd.isConstrained();
+            result = gettersAreEqual && settersAreEqual && propertyTypesAreEqual
+                    && propertyEditorClassesAreEqual && boundPropertyAreEqual
+                    && constrainedPropertyAreEqual;
+        }
+        return result;
+    }
+
+    public void setPropertyEditorClass(Class<?> propertyEditorClass) {
+        this.propertyEditorClass = propertyEditorClass;
+    }
+
+    public Class<?> getPropertyType() {
+        Class<?> result = null;
+        if (getter != null) {
+            result = getter.getReturnType();
+        } else if (setter != null) {
+            Class<?>[] parameterTypes = setter.getParameterTypes();
+            result = parameterTypes[0];
+        }
+        return result;
+    }
+
+    public Class<?> getPropertyEditorClass() {
+        return propertyEditorClass;
+    }
+
+    public void setConstrained(boolean constrained) {
+        this.constrained = constrained;
+    }
+
+    public void setBound(boolean bound) {
+        this.bound = bound;
+    }
+
+    public boolean isConstrained() {
+        return constrained;
+    }
+
+    public boolean isBound() {
+        return bound;
+    }
+
+    boolean hasMethod(Class<?> beanClass, String methodName) {
+        Method[] methods = findMethods(beanClass, methodName);
+        return (methods.length > 0);
+    }
+
+    String createDefaultMethodName(String propertyName, String prefix) {
+        String result = null;
+        if (propertyName != null) {
+            String bos = propertyName.substring(0, 1).toUpperCase();
+            String eos = propertyName.substring(1, propertyName.length());
+            result = prefix + bos + eos;
+        }
+        return result;
+    }
+
+    Method[] findMethods(Class<?> aClass, String methodName) {
+        Method[] allMethods = aClass.getMethods();
+        Vector<Method> matchedMethods = new Vector<Method>();
+        Method[] result;
+        for (Method method : allMethods) {
+            if (method.getName().equals(methodName)) {
+                matchedMethods.add(method);
+            }
+        }
+        result = new Method[matchedMethods.size()];
+        for (int j = 0; j < matchedMethods.size(); ++j) {
+            result[j] = matchedMethods.elementAt(j);
+        }
+        return result;
+    }
+
+    void setReadMethod(Class<?> beanClass, String getterName) {
+        boolean result = false;
+        Method[] getters = findMethods(beanClass, getterName);
+        for (Method element : getters) {
+            try {
+                setReadMethod(element);
+                result = true;
+            } catch (IntrospectionException ie) {
+            }
+            if (result) {
+                break;
+            }
+        }
+    }
+
+    void setWriteMethod(Class<?> beanClass, String setterName) throws IntrospectionException {
+        boolean result = false;
+        Method[] setters = findMethods(beanClass, setterName);
+        for (Method element : setters) {
+            try {
+                setWriteMethod(element);
+                result = true;
+            } catch (IntrospectionException ie) {
+            }
+            if (result) {
+                break;
+            }
+        }
+    }
+
+    public PropertyEditor createPropertyEditor(Object bean) {
+        PropertyEditor editor;
+        if (propertyEditorClass == null) {
+            return null;
+        }
+        if (!PropertyEditor.class.isAssignableFrom(propertyEditorClass)) {
+            // beans.48=Property editor is not assignable from the
+            // PropertyEditor interface
+            throw new ClassCastException(Messages.getString("beans.48")); //$NON-NLS-1$
+        }
+        try {
+            Constructor<?> constr;
+            try {
+                // try to look for the constructor with single Object argument
+                constr = propertyEditorClass.getConstructor(Object.class);
+                editor = (PropertyEditor) constr.newInstance(bean);
+            } catch (NoSuchMethodException e) {
+                // try no-argument constructor
+                constr = propertyEditorClass.getConstructor();
+                editor = (PropertyEditor) constr.newInstance();
+            }
+        } catch (Exception e) {
+            // beans.47=Unable to instantiate property editor
+            RuntimeException re = new RuntimeException(Messages.getString("beans.47"), e); //$NON-NLS-1$
+            throw re;
+        }
+        return editor;
+    }
+}
diff --git a/awt/java/beans/PropertyEditor.java b/awt/java/beans/PropertyEditor.java
new file mode 100644
index 0000000..65bedea
--- /dev/null
+++ b/awt/java/beans/PropertyEditor.java
@@ -0,0 +1,49 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package java.beans;
+
+import java.awt.Component;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+
+public interface PropertyEditor {
+
+    public void paintValue(Graphics gfx, Rectangle box);
+
+    public void setAsText(String text) throws IllegalArgumentException;
+
+    public String[] getTags();
+
+    public String getJavaInitializationString();
+
+    public String getAsText();
+
+    public void setValue(Object value);
+
+    public Object getValue();
+
+    public void removePropertyChangeListener(PropertyChangeListener listener);
+
+    public void addPropertyChangeListener(PropertyChangeListener listener);
+
+    public Component getCustomEditor();
+
+    public boolean supportsCustomEditor();
+
+    public boolean isPaintable();
+}
diff --git a/awt/java/beans/PropertyEditorManager.java b/awt/java/beans/PropertyEditorManager.java
new file mode 100644
index 0000000..ed55829
--- /dev/null
+++ b/awt/java/beans/PropertyEditorManager.java
@@ -0,0 +1,114 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package java.beans;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class PropertyEditorManager {
+
+    private static String[] path = { "org.apache.harmony.beans.editors" }; //$NON-NLS-1$
+
+    private static final Map<Class<?>, Class<?>> registeredEditors = new HashMap<Class<?>, Class<?>>();
+
+    public PropertyEditorManager() {
+    }
+
+    public static void registerEditor(Class<?> targetType, Class<?> editorClass) {
+        if (targetType == null) {
+            throw new NullPointerException();
+        }
+
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPropertiesAccess();
+        }
+        if (editorClass != null) {
+            registeredEditors.put(targetType, editorClass);
+        } else {
+            registeredEditors.remove(targetType);
+        }
+    }
+
+    public static synchronized PropertyEditor findEditor(Class<?> targetType) {
+        if (targetType == null) {
+            throw new NullPointerException();
+        }
+
+        Class<?> editorClass = null;
+        PropertyEditor editor = null;
+
+        editorClass = registeredEditors.get(targetType);
+
+        if (editorClass == null) {
+            String editorClassName = targetType.getName() + "Editor"; //$NON-NLS-1$
+            ClassLoader loader = targetType.getClassLoader();
+
+            if (loader == null) {
+                loader = Thread.currentThread().getContextClassLoader();
+            }
+
+            try {
+                editorClass = Class.forName(editorClassName, true, loader);
+            } catch (ClassNotFoundException cnfe) {
+                String shortEditorClassName = editorClassName
+                        .substring(editorClassName.lastIndexOf(".") + 1); //$NON-NLS-1$
+
+                if (targetType.isPrimitive()) {
+                    shortEditorClassName = shortEditorClassName.substring(0, 1)
+                            .toUpperCase()
+                            + shortEditorClassName.substring(1);
+                }
+
+                for (String element : path) {
+                    editorClassName = element + "." + shortEditorClassName; //$NON-NLS-1$
+
+                    try {
+                        editorClass = Class.forName(editorClassName, true,
+                                loader);
+                        break;
+                    } catch (Exception e) {
+                    }
+                }
+            } catch (Exception e) {
+            }
+        }
+
+        if (editorClass != null) {
+            try {
+                editor = (PropertyEditor) editorClass.newInstance();
+            } catch (Exception e) {
+            }
+        }
+
+        return editor;
+    }
+
+    public static synchronized void setEditorSearchPath(String[] apath) {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPropertiesAccess();
+        }
+
+        path = apath;
+    }
+
+    public static synchronized String[] getEditorSearchPath() {
+        return path;
+    }
+}
diff --git a/awt/java/beans/PropertyEditorSupport.java b/awt/java/beans/PropertyEditorSupport.java
new file mode 100644
index 0000000..c3929a1
--- /dev/null
+++ b/awt/java/beans/PropertyEditorSupport.java
@@ -0,0 +1,129 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package java.beans;
+
+import java.awt.Component;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.harmony.beans.internal.nls.Messages;
+
+public class PropertyEditorSupport implements PropertyEditor {
+
+    Object source = null;
+
+    List<PropertyChangeListener> listeners = new ArrayList<PropertyChangeListener>();
+
+    Object oldValue = null;
+
+    Object newValue = null;
+
+    public PropertyEditorSupport(Object source) {
+        if (source == null) {
+            throw new NullPointerException(Messages.getString("beans.0C")); //$NON-NLS-1$
+        }
+        this.source = source;
+    }
+
+    public PropertyEditorSupport() {
+        source = this;
+    }
+
+    public void paintValue(Graphics gfx, Rectangle box) {
+    }
+
+    public void setAsText(String text) throws IllegalArgumentException {
+        if (newValue instanceof String) {
+            setValue(text);
+        } else {
+            throw new IllegalArgumentException(text);
+        }
+    }
+
+    public String[] getTags() {
+        return null;
+    }
+
+    public String getJavaInitializationString() {
+        return "???"; //$NON-NLS-1$
+    }
+
+    public String getAsText() {
+        return newValue == null ? "null" : newValue.toString(); //$NON-NLS-1$
+    }
+
+    public void setValue(Object value) {
+        this.oldValue = this.newValue;
+        this.newValue = value;
+        firePropertyChange();
+    }
+
+    public Object getValue() {
+        return newValue;
+    }
+
+    public void setSource(Object source) {
+        if (source == null) {
+            throw new NullPointerException(Messages.getString("beans.0C")); //$NON-NLS-1$
+        }
+        this.source = source;
+    }
+
+    public Object getSource() {
+        return source;
+    }
+
+    public synchronized void removePropertyChangeListener(
+            PropertyChangeListener listener) {
+        if (listeners != null) {
+            listeners.remove(listener);
+        }
+    }
+
+    public synchronized void addPropertyChangeListener(
+            PropertyChangeListener listener) {
+        listeners.add(listener);
+    }
+
+    public Component getCustomEditor() {
+        return null;
+    }
+
+    public boolean supportsCustomEditor() {
+        return false;
+    }
+
+    public boolean isPaintable() {
+        return false;
+    }
+
+    public void firePropertyChange() {
+        if (listeners.size() > 0) {
+            PropertyChangeEvent event = new PropertyChangeEvent(source, null,
+                    oldValue, newValue);
+            Iterator<PropertyChangeListener> iterator = listeners.iterator();
+
+            while (iterator.hasNext()) {
+                PropertyChangeListener listener = iterator.next();
+                listener.propertyChange(event);
+            }
+        }
+    }
+}
diff --git a/awt/java/beans/PropertyVetoException.java b/awt/java/beans/PropertyVetoException.java
new file mode 100644
index 0000000..c7f092a
--- /dev/null
+++ b/awt/java/beans/PropertyVetoException.java
@@ -0,0 +1,54 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package java.beans;
+
+/**
+ * Indicates that a proposed property change is unacceptable.
+ */
+public class PropertyVetoException extends Exception {
+
+    private static final long serialVersionUID = 129596057694162164L;
+
+    private final PropertyChangeEvent evt;
+
+    /**
+     * <p>
+     * Constructs an instance with a message and the change event.
+     * </p>
+     * 
+     * @param message
+     *            A description of the veto.
+     * @param event
+     *            The event that was vetoed.
+     */
+    public PropertyVetoException(String message, PropertyChangeEvent event) {
+        super(message);
+        this.evt = event;
+    }
+
+    /**
+     * <p>
+     * Gets the property change event.
+     * </p>
+     * 
+     * @return An instance of {@link PropertyChangeEvent}
+     */
+    public PropertyChangeEvent getPropertyChangeEvent() {
+        return evt;
+    }
+}