javauis/lcdui_akn/javalcdui/javasrc/javax/microedition/lcdui/Graphics.java
branchRCL_3
changeset 14 04becd199f91
child 18 9ac0a0a7da70
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/lcdui_akn/javalcdui/javasrc/javax/microedition/lcdui/Graphics.java	Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,1639 @@
+/*
+* Copyright (c) 1999 - 2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+package javax.microedition.lcdui;
+
+import javax.microedition.lcdui.game.Sprite;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.lang.Math;
+
+import com.nokia.mj.impl.rt.legacy.NativeError;
+import com.nokia.mid.ui.DirectUtils;
+import com.nokia.mj.impl.rt.support.ApplicationInfo;
+import com.nokia.mj.impl.rt.support.Finalizer;
+
+/**
+ * MIDP LCDUI API class providing methods to draw graphics primitives
+ * on a Canvas, CustomItem or Image.
+ *
+ * Implementation writes commands into a (currently per-MIDlet) global
+ * buffer. Each command is of the following form:
+ *
+ * [header][data]
+ *
+ * The header is a 32 bit integer divided into two 16 bit fields, the most
+ * significant halfword contains the opcode. The opcode is further subdivided
+ * into three fields:
+ *
+ * 15-12  11-10 9-0
+ * [clear][mode][op]
+ *
+ * The top 4 bits are clear, although this may change in future, the top two bits
+ * must always remain clear as these bits are used by the buffer itself.
+ *
+ * Bits 10 and 11 contain a mode identifier which is used by the native layer
+ * to try to minimize the number of state changes to the native graphics context.
+ *
+ * Bits 0 to 9 contains an integer opcode. These must match the opcodes declared in
+ * MMIDGraphics in lcdgr.h, and must remain contiguous.
+ */
+public class Graphics
+{
+    private static final int TRANS_MIN = javax.microedition.lcdui.game.Sprite.TRANS_NONE;
+    private static final int TRANS_MAX = javax.microedition.lcdui.game.Sprite.TRANS_MIRROR_ROT90;
+
+    /**
+     * Pixel formats.
+     *
+     * These must be kept in sync with MMIDGraphics::TPixelType
+     *
+     * Only TYPE_INT_ARGB_8888 is currently used - in Graphics.drawRGB
+     * The others may be useful in the implementation of extension APIs but
+     * will require modifications to the MMIDGraphics implementation.
+     */
+    private static final int TYPE_INT_ARGB_8888       = 0;    // supported
+    private static final int TYPE_SHORT_ARGB_4444 = 1;    // not supported yet
+    private static final int TYPE_PACKED_ECOLOR_4K    = 2;    // not supported yet
+
+    //
+    // Anchor specs
+    //
+    public static final int HCENTER  = 1;
+    public static final int VCENTER  = 2;
+    public static final int LEFT     = 4;
+    public static final int RIGHT    = 8;
+    public static final int TOP      = 16;
+    public static final int BOTTOM   = 32;
+    public static final int BASELINE = 64;
+
+    //
+    // StrokeStyle consts
+    //
+    public static final int SOLID = 0;
+    public static final int DOTTED = 1;
+
+    //
+    // Anchor masks
+    //
+    private static final int STRING_ANCHOR_MASK = HCENTER|LEFT|RIGHT|TOP|BOTTOM|BASELINE;
+    private static final int IMAGE_ANCHOR_MASK  = HCENTER|VCENTER|LEFT|RIGHT|TOP|BOTTOM;
+    private static final int HMASK              = HCENTER|LEFT|RIGHT;
+    private static final int VMASK              = VCENTER|TOP|BOTTOM|BASELINE;
+
+    //
+    // These must be kept in sync with MMIDGraphics::TGraphicsOp
+    //
+    private static final int OP_SET_COLOR    = 0;
+    private static final int OP_SET_STROKE   = 1;
+    private static final int OP_SET_FONT     = 2;
+    private static final int OP_SET_CLIPRECT = 3;
+    private static final int OP_TRANSLATE    = 4;
+    private static final int OP_RESET      = 5;
+
+    private static final int OP_DRAW_LINE       = 6;
+    private static final int OP_DRAW_RECT       = 7;
+    private static final int OP_FILL_RECT       = 8;
+    private static final int OP_DRAW_ROUNDRECT  = 9;
+    private static final int OP_FILL_ROUNDRECT  = 10;
+    private static final int OP_DRAW_ARC        = 11;
+    private static final int OP_FILL_ARC      = 12;
+    private static final int OP_DRAW_STRING     = 13;
+    private static final int OP_DRAW_IMAGE      = 14;
+    private static final int OP_DRAW_REGION     = 15;
+    private static final int OP_COPY_AREA     = 16;
+    private static final int OP_FILL_TRIANGLE   = 17;
+    private static final int OP_DRAW_PIXELS       = 18;
+
+    /* special ops */
+    private static final int OP_FLUSH         = 19;
+
+    private static final int OP_DRAW_BACKGROUND = 20;
+    /* NGA specific change */
+    private static final int OP_COPY_GRAPHICS   = 21;
+
+    // Default color
+    private static final int BLACK = 0xff000000;
+
+    Font          iDefaultFont;
+
+    //
+    Toolkit        iToolkit;
+    Buffer         iBuffer;
+    Object         iTarget;
+    Image          iImage;        // target is image
+    int            iHandle;
+    int            iDirectGraphicsHandle;
+    int            iWidth;
+    int            iHeight;
+    private char[] iChar;     // Buffer for string/character drawing.
+
+    // State
+    private int       iTransX;
+    private int       iTransY;
+    private int       iClipX;
+    private int       iClipY;
+    private int       iClipWidth;
+    private int       iClipHeight;
+
+    private int     iColor;           // color value ARGB with 8 bits each
+    private int     iStrokeStyle; // one of (SOLID,DOTTED)
+    private Font    iFont;
+    private Font    iScalableFont;
+    private boolean iFontSet;
+    private boolean iScalableFontSet;
+
+    private int iOnScreenWidth;  // width of screen
+    private int iOnScreenHeight; // height of screen
+
+    //flag if is original size set in JAD file
+    private boolean iIsSetOriginalSize;
+    // flag if set target size in JAD file
+    private boolean iIsSetTargetSize;
+
+    // size from Nokia-MIDlet-Canvas-Scaling-Orientation-Switch JAD attribute
+    private int iTargetHeight;
+    private int iTargetWidth;
+
+    // NokiaUI DirectGraphics is stored here in order to allow a proper
+    // garbage collection.
+    DirectGraphicsImpl iDirectGraphics;
+
+    private Finalizer mFinalizer = new Finalizer()
+    {
+        public void finalizeImpl()
+        {
+            doFinalize();
+        }
+    };
+
+    /*
+     * Constructor
+     */
+    Graphics(Toolkit aToolkit,
+             Object aTarget,
+             int aDrawable,
+             int aWidth,
+             int aHeight)
+    {
+        // saving of given parameters
+        iToolkit = aToolkit;
+        iBuffer = aToolkit.iBuffer;
+        iTarget = aTarget;
+
+        iIsSetTargetSize = false;
+        // If a Graphics is drawing to image then a image is saved. Null otherwise
+        iImage = (aTarget instanceof Image) ? (Image)aTarget : null;
+
+        // creating of native side graphics
+        iHandle = NativeError.check(_create(aToolkit.getHandle(), aDrawable));
+
+        // default values
+        iChar = new char[1];
+        iIsSetOriginalSize = false;
+        iIsSetTargetSize = false;
+        iDefaultFont = Font.getDefaultFont();
+
+        // this get a correct iIsSetOriginalSize and iIsSetTargetSize values.
+        //
+        // getting JAD attributes
+        ApplicationInfo appInfo = ApplicationInfo.getInstance();
+        if (appInfo.getAttribute("Nokia-MIDlet-Original-Display-Size") != null)
+        {
+            iIsSetOriginalSize = true;
+        }
+        String targetSize = appInfo.getAttribute("Nokia-MIDlet-Target-Display-Size");
+        if (targetSize != null)
+        {
+            // setting of iTargetHeight and iTargetWidth
+            setTargetSize(targetSize);
+        }
+
+        // resenting of state of Graphics
+        resetState(aWidth, aHeight);
+    }
+
+    /**
+     * This method set iTargetHeight and iTargetWidth according to targetSize String.
+     * @param targetSize string with Nokia-MIDlet-Target-Display-Size param
+     */
+    private void setTargetSize(String targetSize)
+    {
+        iIsSetTargetSize = false;
+        String current = "";
+        int indexString = 0;
+        int indexArray = 0;
+
+        // deleting of leading spaces
+        targetSize = targetSize.trim();
+
+        // loading of help string for iTargetWidth
+        current += targetSize.charAt(indexString++);
+        while ((indexString < targetSize.length()) && (Character.isDigit(targetSize.charAt(indexString))))
+        {
+            current += (targetSize.charAt(indexString++));
+        }
+
+        // If first next non-space char is not ',', input string is wrong.
+        while (targetSize.charAt(indexString) == ' ')
+        {
+            indexString++;
+        }
+        if (targetSize.charAt(indexString++) != ',')
+        {
+            return;
+        }
+
+        // setting of iTargetWidth
+        iTargetWidth = Integer.parseInt(current);
+
+        // set to targetSize String for iTargetHeight without spaces
+        targetSize = targetSize.substring(indexString).trim();
+        indexString = 0;
+        indexArray = 0;
+        current = "";
+
+        // loading of help string for iTargetHeight
+        current += targetSize.charAt(indexString++);
+        while ((indexString < targetSize.length()) && (Character.isDigit(targetSize.charAt(indexString))))
+        {
+            current += (targetSize.charAt(indexString++));
+        }
+
+        // setting of iTargetHeight
+        iTargetHeight = Integer.parseInt(current);
+
+        // Set of flag iIsSetTargetSize.
+        iIsSetTargetSize = true;
+    }
+
+    void dispose()
+    {
+        final int handle;
+        synchronized (iBuffer)
+        {
+            handle = iHandle;
+            iHandle = 0;
+        }
+        if (0 != handle)
+        {
+            iToolkit.disposeObject(handle);
+        }
+    }
+
+    private void doFinalize()
+    {
+        if (mFinalizer != null)
+        {
+            registeredFinalize();
+            mFinalizer = null;
+        }
+    }
+
+    void registeredFinalize()
+    {
+        dispose();
+    }
+
+    private void resetState(int aWidth, int aHeight)
+    {
+        // set of size of iTarget.
+        iWidth       = aWidth;
+        iHeight      = aHeight;
+        // get of size of screen
+        iToolkit.getDevice().getDeviceSizeWithoutKeypad();
+        iOnScreenWidth = iToolkit.getDevice().iScreenWidth;
+        iOnScreenHeight = iToolkit.getDevice().iScreenHeight;
+        if (iOnScreenWidth == 0)
+        {
+            iOnScreenWidth = iWidth;
+        }
+        if (iOnScreenHeight == 0)
+        {
+            iOnScreenHeight = iHeight;
+        }
+
+        // reset of traslation, clip, color, stroke style and font
+        iTransX        = 0;
+        iTransY        = 0;
+        iClipX         = 0;
+        iClipY         = 0;
+        iClipWidth   = aWidth;
+        iClipHeight  = aHeight;
+        iColor         = BLACK;
+        iStrokeStyle = SOLID;
+        iFont        = iDefaultFont;
+        iFontSet   = false;
+        iScalableFontSet = false;
+
+        // If target is Canvas in fullscreen mode and
+        // MIDlet have set original size and have't set target size,
+        // then it is required set correct values of iOnScreenWidth and
+        // iOnScreenHeight.
+        if ((iTarget instanceof Canvas) &&
+                ((Canvas)iTarget).getFullScreenMode() &&
+                !iIsSetTargetSize && iIsSetOriginalSize)
+        {
+            // This code checks if some of measures is
+            // bigger of target Canvas is bigger than
+            // measure of screen.
+            float ratioX = (float)iWidth / iOnScreenWidth;
+            float ratioY = (float)iHeight / iOnScreenHeight;
+
+            if (Math.max(ratioX, ratioY) > 1)
+            {
+                // Canvas has smaller ratio for width to for height than screen.
+                if (ratioY > ratioX)
+                {
+                    // setting correct value of iOnScreenWidth
+                    iOnScreenWidth = (iOnScreenHeight * iWidth) / iHeight;
+                }
+                // Canvas has bigger ratio for width to for height than screen
+                // (or the same).
+                else
+                {
+                    // setting correct value of iOnScreenHeight
+                    iOnScreenHeight = (iOnScreenWidth * iHeight) / iWidth;
+                }
+            }
+        }
+        // setting of target size
+        if ((iTarget instanceof Canvas) &&
+                ((Canvas)iTarget).getFullScreenMode() &&
+                iIsSetTargetSize && iIsSetOriginalSize)
+        {
+            iOnScreenHeight = iTargetHeight;
+            iOnScreenWidth = iTargetWidth;
+        }
+    }
+
+    void reset(int aWidth, int aHeight)
+    {
+        synchronized (iBuffer)
+        {
+            if (iHandle != 0)
+            {
+                resetState(aWidth, aHeight);
+                iBuffer.write(iHandle, OP_RESET, aWidth, aHeight);
+            }
+        }
+    }
+
+    public void translate(int aDx,int aDy)
+    {
+        synchronized (iBuffer)
+        {
+            // If is downscaling on, then we change parameters.
+            if (isDownscaled())
+            {
+                aDx = (aDx * iOnScreenWidth) / iWidth;
+                aDy = (aDy * iOnScreenHeight) / iHeight;
+            }
+            // setting of translate in java class Graphics
+            iTransX += aDx;
+            iTransY += aDy;
+            iClipX  -= aDx;
+            iClipY  -= aDy;
+            // setting of translate in native graphics
+            iBuffer.write(iHandle, OP_TRANSLATE, iTransX, iTransY);
+        }
+    }
+
+    public int getTranslateX()
+    {
+        // If is downscaling on, then it return downscaled traslate of x.
+        if (isDownscaled())
+            return (iTransX * iWidth) / iOnScreenWidth;
+        // If is downscaling off, then it return non-scaled traslate of x.
+        else
+            return iTransX;
+    }
+
+    public int getTranslateY()
+    {
+        // If is downscaling on, then it return downscaled traslate of y.
+        if (isDownscaled())
+            return (iTransY * iHeight) / iOnScreenHeight;
+        // If is downscaling off, then it return non-scaled traslate of y.
+        else
+            return iTransY;
+    }
+
+    public int getColor()
+    {
+        return (iColor & 0x00ffffff);
+    }
+
+    public int getRedComponent()
+    {
+        return (iColor >>> 16) & 0xff;
+    }
+
+    public int getGreenComponent()
+    {
+        return (iColor >>> 8) & 0xff;
+    }
+
+    public int getBlueComponent()
+    {
+        return (iColor & 0xff);
+    }
+
+    public int getGrayScale()
+    {
+        final int color = iColor;
+        final int r = (color >>> 16) & 0xff;
+        final int g = (color >>> 8) & 0xff;
+        final int b = color & 0xff;
+        return Math.max(r, Math.max(g,b));
+    }
+
+    public void setColor(int aRed,int aGreen,int aBlue)
+    {
+        /*
+         * For all valid arguments, only the least significant
+         * byte can contain non-zero bits.
+         */
+        if (((aRed|aGreen|aBlue)>>>8)!=0)
+        {
+            throw new IllegalArgumentException();
+        }
+        setColor((aRed << 16) | (aGreen << 8) | aBlue);
+    }
+
+    public void setColor(int aRgb)
+    {
+        //
+        // Drawing colors are fully opaque.
+        //
+        final int color = (aRgb | 0xff000000);
+        synchronized (iBuffer)
+        {
+            if (iColor != color)
+            {
+                iColor = color;
+                iBuffer.write(iHandle, OP_SET_COLOR, color);
+            }
+        }
+    }
+
+    public void setGrayScale(int aValue)
+    {
+        setColor(aValue, aValue, aValue);
+    }
+
+    public Font getFont()
+    {
+        return iFont;
+    }
+
+    public void setFont(Font aFont)
+    {
+        if (aFont == null)
+        {
+            aFont = Font.getDefaultFont();
+        }
+        synchronized (iBuffer)
+        {
+            if (iFont != aFont)
+            {
+                iFont    = aFont;
+                iFontSet = false;
+                iScalableFontSet = false;
+            }
+        }
+    }
+    /**
+     * If the downscaling is on, it is created and used the new scaled font.
+     */
+    private void setScalableFont()
+    {
+        if (!iScalableFontSet && iFont != null)
+        {
+            int fontHeight = iFont.getHeight();
+            fontHeight = (fontHeight * iOnScreenHeight) / iHeight;
+            iScalableFont = DirectUtils.getFont(iFont.getFace(), iFont.getStyle(), fontHeight);
+            iFontSet = false;
+            iScalableFontSet = false;
+        }
+    }
+
+    /**
+     * set font with buffer locked.
+     */
+    private void UseFont()
+    {
+        if (!iFontSet)
+        {
+            if (!isDownscaled())
+            {
+                iBuffer.write(iHandle, OP_SET_FONT, iFont.iHandle);
+                iFontSet = true;
+            }
+            else if (!iScalableFontSet)
+            {
+                iBuffer.write(iHandle, OP_SET_FONT, iScalableFont.iHandle);
+                iFontSet = true;
+                iScalableFontSet = true;
+            }
+        }
+    }
+
+    public int getClipX()
+    {
+        return iClipX;
+    }
+
+    public int getClipY()
+    {
+        return iClipY;
+    }
+
+    public int getClipWidth()
+    {
+        return iClipWidth;
+    }
+
+    public int getClipHeight()
+    {
+        return iClipHeight;
+    }
+
+    public void clipRect(int aX, int aY, int aWidth,int aHeight)
+    {
+        // finding of correct clip
+        final int cx2 = Math.min(iClipX + iClipWidth, aX + aWidth);
+        final int cy2 = Math.min(iClipY + iClipHeight, aY + aHeight);
+        // setting of clip to Java Graphics
+        iClipX = Math.max(aX, iClipX);
+        iClipY = Math.max(aY, iClipY);
+        iClipWidth = cx2 - iClipX;
+        iClipHeight = cy2 - iClipY;
+        int clipX = iClipX;
+        int clipY = iClipY;
+        int clipWidth = iClipWidth;
+        int clipHeight = iClipHeight;
+        // If is downscaling on, then it downscales clip.
+        if (isDownscaled())
+        {
+            clipX = (clipX * iOnScreenWidth) / iWidth;
+            clipY = (clipY * iOnScreenHeight) / iHeight;
+            clipWidth = (clipWidth * iOnScreenWidth) / iWidth;
+            clipHeight = (clipHeight * iOnScreenHeight) / iHeight;
+        }
+        // Setting clip to native graphics
+        synchronized (iBuffer)
+        {
+            iBuffer.write(iHandle, OP_SET_CLIPRECT, clipX, clipY, clipWidth, clipHeight);
+            if (iDirectGraphicsHandle != 0)
+                iBuffer.write(iDirectGraphicsHandle, OP_SET_CLIPRECT, clipX, clipY, clipWidth, clipHeight);
+        }
+    }
+
+    public void setClip(int aX, int aY, int aWidth, int aHeight)
+    {
+        // setting of clip to Java Graphics
+        iClipX = aX;
+        iClipY = aY;
+        iClipWidth = aWidth;
+        iClipHeight = aHeight;
+        int clipX = iClipX;
+        int clipY = iClipY;
+        int clipWidth = iClipWidth;
+        int clipHeight = iClipHeight;
+        // If is downscaling on, then it downscales clip.
+        if (isDownscaled())
+        {
+            clipX = (clipX * iOnScreenWidth) / iWidth;
+            clipY = (clipY * iOnScreenHeight) / iHeight;
+            clipWidth = (clipWidth * iOnScreenWidth) / iWidth;
+            clipHeight = (clipHeight * iOnScreenHeight) / iHeight;
+        }
+        synchronized (iBuffer)
+        {
+            // Setting clip to native graphics
+            iBuffer.write(iHandle, OP_SET_CLIPRECT, clipX, clipY, clipWidth, clipHeight);
+            if (iDirectGraphicsHandle != 0)
+                iBuffer.write(iDirectGraphicsHandle, OP_SET_CLIPRECT, clipX, clipY, clipWidth, clipHeight);
+        }
+    }
+
+    public void drawLine(int aX1, int aY1, int aX2, int aY2)
+    {
+        // If is downscaling on, then it downscales line's ends.
+        if (isDownscaled())
+        {
+            aX1 = (aX1 * iOnScreenWidth) / iWidth;
+            aY1 = (aY1 * iOnScreenHeight) / iHeight;
+            aX2 = (aX2 * iOnScreenWidth) / iWidth;
+            aY2 = (aY2 * iOnScreenHeight) / iHeight;
+        }
+        synchronized (iBuffer)
+        {
+            // Send line to native graphics
+            iBuffer.write(iHandle, OP_DRAW_LINE, aX1, aY1, aX2, aY2);
+        }
+    }
+
+    public void fillRect(int aX, int aY, int aWidth, int aHeight)
+    {
+        // If is downscaling on, then it downscales rectagle.
+        if (isDownscaled())
+        {
+            aX = (aX * iOnScreenWidth) / iWidth;
+            aY = (aY * iOnScreenHeight) / iHeight;
+            /* Prevents bad drawing of thin rect.
+               Rounding up the final rect after downscaling.
+            */
+            if (aWidth > aHeight)
+            {
+                aWidth = (aWidth * iOnScreenWidth) / iWidth;
+                aHeight = (int)Math.ceil(((double)aHeight * iOnScreenHeight) / iHeight);
+            }
+            else if (aHeight > aWidth)
+            {
+                aWidth = (int)Math.ceil(((double)aWidth * iOnScreenWidth) / iWidth);
+                aHeight = (aHeight * iOnScreenHeight) / iHeight;
+            }
+            else
+            {
+                aWidth = (int)Math.ceil(((double)aWidth * iOnScreenWidth) / iWidth);
+                aHeight = (int)Math.ceil(((double)aHeight * iOnScreenHeight) / iHeight);
+            }
+        }
+        synchronized (iBuffer)
+        {
+            // Send rectagle to native graphics.
+            iBuffer.write(iHandle, OP_FILL_RECT, aX, aY, aWidth, aHeight);
+        }
+    }
+
+    public void drawRect(int aX, int aY, int aWidth, int aHeight)
+    {
+        // If is downscaling on, then it downscales rectagle.
+        if (isDownscaled())
+        {
+            aX = (aX * iOnScreenWidth) / iWidth;
+            aY = (aY * iOnScreenHeight) / iHeight;
+            aWidth = (aWidth * iOnScreenWidth) / iWidth;
+            aHeight = (aHeight * iOnScreenHeight) / iHeight;
+        }
+        synchronized (iBuffer)
+        {
+            // Send rectagle to native graphics.
+            iBuffer.write(iHandle, OP_DRAW_RECT, aX, aY, aWidth, aHeight);
+        }
+    }
+
+    public void drawRoundRect(int aX, int aY, int aWidth, int aHeight, int aArcWidth, int aArcHeight)
+    {
+        // If is downscaling on, then it downscales rectagle and arches.
+        if (isDownscaled())
+        {
+            aX = (aX * iOnScreenWidth) / iWidth;
+            aY = (aY * iOnScreenHeight) / iHeight;
+            aWidth = (aWidth * iOnScreenWidth) / iWidth;
+            aHeight = (aHeight * iOnScreenHeight) / iHeight;
+            aArcWidth = (aArcWidth * iOnScreenWidth) / iWidth;
+            aArcHeight = (aArcHeight * iOnScreenHeight) / iHeight;
+        }
+        synchronized (iBuffer)
+        {
+            // Send rectagle and arches to native graphics.
+            iBuffer.write(iHandle, OP_DRAW_ROUNDRECT, aX, aY, aWidth, aHeight, aArcWidth, aArcHeight);
+        }
+    }
+
+    public void fillRoundRect(int aX, int aY, int aWidth, int aHeight, int aArcWidth, int aArcHeight)
+    {
+        // If is downscaling on, then it downscales rectagle and arches.
+        if (isDownscaled())
+        {
+            aX = (aX * iOnScreenWidth) / iWidth;
+            aY = (aY * iOnScreenHeight) / iHeight;
+
+            /* Prevents bad drawing of thin rect.
+               Rounding up the final rect after downscaling.
+            */
+            if (aWidth > aHeight)
+            {
+                aWidth = (aWidth * iOnScreenWidth) / iWidth;
+                aHeight = (int)Math.ceil(((double)aHeight * iOnScreenHeight) / iHeight);
+            }
+            else if (aHeight > aWidth)
+            {
+                aWidth = (int)Math.ceil(((double)aWidth * iOnScreenWidth) / iWidth);
+                aHeight = (aHeight * iOnScreenHeight) / iHeight;
+            }
+            else
+            {
+                aWidth = (int)Math.ceil(((double)aWidth * iOnScreenWidth) / iWidth);
+                aHeight = (int)Math.ceil(((double)aHeight * iOnScreenHeight) / iHeight);
+            }
+            aArcWidth = (aArcWidth * iOnScreenWidth) / iWidth;
+            aArcHeight = (aArcHeight * iOnScreenHeight) / iHeight;
+        }
+        synchronized (iBuffer)
+        {
+            // Send rectagle and arches to native graphics.
+            iBuffer.write(iHandle, OP_FILL_ROUNDRECT, aX, aY, aWidth, aHeight, aArcWidth, aArcHeight);
+        }
+    }
+
+    public void fillArc(int aX, int aY, int aWidth, int aHeight, int aStartAngle, int aArcAngle)
+    {
+        // If is downscaling on, then it downscales centre and measures.
+        if (isDownscaled())
+        {
+            aX = (aX * iOnScreenWidth) / iWidth;
+            aY = (aY * iOnScreenHeight) / iHeight;
+            /* Prevents bad drawing of thin rect.
+               Rounding up the final rect after downscaling.
+            */
+            if (aWidth > aHeight)
+            {
+                aWidth = (aWidth * iOnScreenWidth) / iWidth;
+                aHeight = (int)Math.ceil(((double)aHeight * iOnScreenHeight) / iHeight);
+            }
+            else if (aHeight > aWidth)
+            {
+                aWidth = (int)Math.ceil(((double)aWidth * iOnScreenWidth) / iWidth);
+                aHeight = (aHeight * iOnScreenHeight) / iHeight;
+            }
+            else
+            {
+                aWidth = (int)Math.ceil(((double)aWidth * iOnScreenWidth) / iWidth);
+                aHeight = (int)Math.ceil(((double)aHeight * iOnScreenHeight) / iHeight);
+            }
+        }
+        synchronized (iBuffer)
+        {
+            // Send arch to native graphics.
+            iBuffer.write(iHandle, OP_FILL_ARC, aX, aY, aWidth, aHeight, aStartAngle, aArcAngle);
+        }
+    }
+
+    public void drawArc(int aX, int aY, int aWidth, int aHeight, int aStartAngle, int aArcAngle)
+    {
+        // If is downscaling on, then it downscales centre and measures.
+        if (isDownscaled())
+        {
+            aX = (aX * iOnScreenWidth) / iWidth;
+            aY = (aY * iOnScreenHeight) / iHeight;
+            aWidth = (aWidth * iOnScreenWidth) / iWidth;
+            aHeight = (aHeight * iOnScreenHeight) / iHeight;
+        }
+        synchronized (iBuffer)
+        {
+            // Send arch to native graphics.
+            iBuffer.write(iHandle, OP_DRAW_ARC, aX, aY, aWidth, aHeight, aStartAngle, aArcAngle);
+        }
+    }
+
+    public void drawString(String aString, int aX, int aY, int aAnchor)
+    {
+        // If is downscaling on, then it downscales drawing point.
+        if (isDownscaled())
+        {
+            aX = (aX * iOnScreenWidth) / iWidth;
+            aY = (aY * iOnScreenHeight) / iHeight;
+            setScalableFont();
+        }
+        final int length = aString.length();
+        synchronized (iBuffer)
+        {
+            // checking of anchor or setting default
+            aAnchor = checkAnchor(aAnchor, STRING_ANCHOR_MASK);
+            // set a current font for use
+            UseFont();
+            // Send text, drawing point and anchor to native graphics.
+            iBuffer.writeStr(iHandle, OP_DRAW_STRING, aString, 0, length, aX, aY, aAnchor);
+        }
+    }
+
+    public void drawSubstring(String aString, int aOffset, int aLength, int aX, int aY, int aAnchor)
+    {
+        // If is downscaling on, then it downscales drawing point.
+        if (isDownscaled())
+        {
+            aX = (aX * iOnScreenWidth) / iWidth;
+            aY = (aY * iOnScreenHeight) / iHeight;
+            setScalableFont();
+        }
+        synchronized (iBuffer)
+        {
+            // checking of anchor or setting default
+            aAnchor = checkAnchor(aAnchor, STRING_ANCHOR_MASK);
+
+            // Checking if offset and length are correct.
+            final int stringLength = aString.length();
+            final int beg = aOffset;
+            final int end = aOffset + aLength;
+            if ((beg < 0) || (end > stringLength) || (end < beg))
+            {
+                throw new StringIndexOutOfBoundsException();
+            }
+
+            // set a current font for use
+            UseFont();
+            // Send text, drawing point and anchor to native graphics.
+            iBuffer.writeStr(iHandle, OP_DRAW_STRING, aString, aOffset, aLength, aX, aY, aAnchor);
+        }
+    }
+
+    public void drawChar(char aChar, int aX, int aY, int aAnchor)
+    {
+        if (isDownscaled())
+        {
+            aX = (aX * iOnScreenWidth) / iWidth;
+            aY = (aY * iOnScreenHeight) / iHeight;
+        }
+        // Calling of drawChars with array with size 1.
+        iChar[0] = aChar;
+        DrawChars(iChar, 0, 1, aX, aY, aAnchor);
+    }
+
+    public void drawChars(char[] aChars,int aOffset,int aLength,int aX,int aY,int aAnchor)
+    {
+        // If is downscaling on, then it downscales drawing point.
+        if (isDownscaled())
+        {
+            aX = (aX * iOnScreenWidth) / iWidth;
+            aY = (aY * iOnScreenHeight) / iHeight;
+        }
+
+        synchronized (iBuffer)
+        {
+            // Checking if offset and length are correct.
+            final int charLength = aChars.length; // throws NullPointerException
+            final int beg = aOffset;
+            final int end = aOffset + aLength;
+            if ((beg < 0) || (end > charLength) || (end < beg))
+            {
+                throw new ArrayIndexOutOfBoundsException();
+            }
+            // Calling of DrawChars.
+            DrawChars(aChars, aOffset, aLength, aX, aY, aAnchor);
+        }
+    }
+
+    private void DrawChars(char[] aChars,int aOffset,int aLength,int aX,int aY,int aAnchor)
+    {
+        // checking of anchor or setting default
+        aAnchor = checkAnchor(aAnchor, STRING_ANCHOR_MASK);
+        if (isDownscaled())
+        {
+            setScalableFont();
+        }
+        // set a current font for use
+        UseFont();
+        // Send text, drawing point and anchor to native graphics.
+        iBuffer.writeChars(iHandle, OP_DRAW_STRING, aChars, aOffset, aLength, aX, aY, aAnchor);
+    }
+
+    public void drawImage(Image aImage, int aX, int aY, int aAnchor)
+    {
+        // check if iTarget is downscaled
+        if (isDownscaled())
+        {
+            // It is downscaled.
+            // downscaling drawing point
+            aX = (aX * iOnScreenWidth) / iWidth;
+            aY = (aY * iOnScreenHeight) / iHeight;
+
+            // getting size of aImage
+            int widthL = aImage.getWidth();
+            int heightL = aImage.getHeight();
+
+            // create RGB array for aImage.
+            int rgbL[] = new int[widthL * heightL];
+
+            // getting a RGB data from aImage
+            aImage.getRGB(rgbL, 0, widthL, 0, 0, widthL, heightL);
+
+            // downscaling size of aImage
+            int widthSL = (widthL * iOnScreenWidth) / iWidth;
+            int heightSL = (heightL * iOnScreenHeight) / iHeight;
+
+            // create RGB array for downscaled image
+            int rgbSL[] = new int[widthSL * heightSL];
+
+            // getting downscaled rgb data
+            getDownscaledRGB(rgbSL, rgbL, widthL, heightL);
+
+            // creating a image from downscaled RGB data
+            Image image = Image.createRGBImage(rgbSL, widthSL, heightSL, true);
+            synchronized (iBuffer)
+            {
+                // checking of anchor
+                aAnchor = checkAnchor(aAnchor, IMAGE_ANCHOR_MASK);
+                // send downscaled image with downscaled drawing point
+                // to native side
+                iBuffer.write(iHandle, OP_DRAW_IMAGE, image.iHandle, aX, aY, aAnchor);
+            }
+        }
+        else
+        {
+            // It is not downscaled.
+            synchronized (iBuffer)
+            {
+                // checking of anchor
+                aAnchor = checkAnchor(aAnchor, IMAGE_ANCHOR_MASK);
+                // send image with drawing point to native side
+                iBuffer.write(iHandle, OP_DRAW_IMAGE, aImage.iHandle, aX, aY, aAnchor);
+            }
+        }
+    }
+
+    /**
+     * Sets the copy-graphics command into the command buffer.
+     * @param aSrcGraphics The source graphics
+     * @since s60 9.2
+     */
+    void copyGraphics(Graphics aSrcGraphics)
+    {
+        synchronized (iBuffer)
+        {
+            iBuffer.write(iHandle, OP_COPY_GRAPHICS, aSrcGraphics.iHandle);
+        }
+    }
+
+    public void setStrokeStyle(int aStyle)
+    {
+        if ((aStyle != SOLID) && (aStyle != DOTTED))
+        {
+            throw new IllegalArgumentException();
+        }
+        synchronized (iBuffer)
+        {
+            iStrokeStyle = aStyle;
+            iBuffer.write(iHandle, OP_SET_STROKE, aStyle);
+        }
+    }
+
+    public int getStrokeStyle()
+    {
+        return iStrokeStyle;
+    }
+
+    /**
+     * Check that aAnchor contains a valid anchor spec.
+     * Using zero for the anchor point value gives results identical to using TOP | LEFT.
+     * The definition of the anchor point must be one of the horizontal constants
+     * (LEFT, HCENTER, RIGHT) combined with one of the vertical constants (TOP, BASELINE, BOTTOM)
+     */
+    private static int checkAnchor(int aAnchor, int aMask)
+    {
+        if (0 == aAnchor)
+        {
+            aAnchor = LEFT|TOP;
+            return aAnchor;
+        }
+
+        final boolean excess = (aAnchor & ~aMask) != 0;
+        final int horz = aAnchor & HMASK;
+        final int vert = aAnchor & VMASK;
+
+        if (excess || multipleBits(vert) || multipleBits(horz))
+        {
+            throw new IllegalArgumentException();
+        }
+        if (horz == 0 || vert == 0)
+        {
+            throw new IllegalArgumentException("anchor is not a legal value");
+        }
+
+        return aAnchor;
+    }
+
+    /**
+     *@return true if aAnchor contains more than one bit set.
+     */
+    private static boolean multipleBits(int aAnchor)
+    {
+        return (aAnchor & (aAnchor-1)) != 0;
+    }
+
+    // New in MIDP 2.0
+    public int getDisplayColor(int aColor)
+    {
+        int i = 0;
+        synchronized (iToolkit)
+        {
+            i = _getDisplayColor(iToolkit.getHandle(), iHandle, aColor);
+        }
+        return i;
+    }
+
+    //
+    // New in MIDP 2.0
+    //
+    // Semantics of negative width/height are not defined in the spec
+    // but could be used to implement reflections.
+    //
+    public void drawRGB(
+        int[]   aRgbData,
+        int     aOffset,
+        int     aScanLength,
+        int     aX,
+        int     aY,
+        int     aWidth,
+        int     aHeight,
+        boolean aProcessAlpha)
+    {
+        // setting of help variables
+        int len = aRgbData.length;
+        int width = aWidth >= 0 ? aWidth : -aWidth;
+        int height = aHeight >= 0 ? aHeight : -aHeight;
+
+        // get RGB array for drawing
+        int rgbSL[] = aRgbData;
+
+        // This checks if downscaling is on.
+        if (isDownscaled())
+        {
+            // dowscaling of drawing point and size of image
+            aX = (aX * iOnScreenWidth) / iWidth;
+            aY = (aY * iOnScreenHeight) / iHeight;
+            int widthSL = (width * iOnScreenWidth) / iWidth;
+            int heightSL = (height * iOnScreenHeight) / iHeight;
+
+            // set drawing array to new array with downscaled size
+            rgbSL = new int[widthSL * heightSL];
+
+            // preparing of aRgbData to use getDownscaledRGB method
+            aRgbData = cleanRGB(aRgbData, aOffset, aScanLength, width, height);
+
+            // downscaling of RGB data
+            getDownscaledRGB(rgbSL, aRgbData, width, height);
+
+            //setting parameters do downscaled values
+            aWidth = widthSL;
+            aHeight = heightSL;
+            aOffset = 0;
+            aScanLength = widthSL;
+        }
+        int scanLength;
+        int transform;
+
+        long end64       = (long)len - 1;
+        long offset64;
+        long scanLength64;
+
+
+        if (aScanLength >= 0)
+        {
+            // If aScanLength is positive, we can use RGB data forward.
+            scanLength = aScanLength;
+            transform  = Sprite.TRANS_NONE;
+            offset64   = (long)aOffset;
+        }
+        else
+        {
+            // If aScanlength is negative, we have to use RGB data backward.
+            scanLength = -aScanLength;
+            transform  = Sprite.TRANS_MIRROR_ROT180;  // relection in horizontal axis
+            offset64 = (long)aOffset - (long)scanLength * ((long)height - 1);
+        }
+
+        scanLength64 = (long)scanLength;
+        long min64 = offset64;
+        long max64 = offset64 + scanLength64 * ((long)height - 1) + (long)width - 1;
+
+        // They are given incorrect data.
+        if ((min64 < 0) || (max64 > end64))
+        {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+
+
+        //
+        // IMPROVEMENT: clip down the data to transfer.
+        //
+        int x1 = aX;
+        int y1 = aY;
+        int x2 = aX + aWidth;
+        int y2 = aY + aHeight;
+
+        int clipX2 = iClipX+iClipWidth;
+        int clipY2 = iClipY+iClipHeight;
+
+        x1 = iClipX > x1 ? iClipX : x1;
+        y1 = iClipY > y1 ? iClipY : y1;
+        x2 = clipX2 < x2 ? clipX2 : x2;
+        y2 = clipY2 < y2 ? clipY2 : y2;
+
+        width = x2 - x1;
+        height = y2 - y1;
+
+        //
+        // This will also clip out any attempt
+        // to draw with negative width/height.
+        //
+        if ((width<=0) || (height<=0))
+        {
+            return;
+        }
+
+        //
+        // move offset to start of clipped region, note we use top-left corner here
+        // because we have already regularized the scanlength : the tranform takes
+        // care of vertical flip for negative scan case.
+        //
+        offset64 += scanLength64 * (long)(y1 - aY) + (long)(x1 - aX);
+        //
+        // adjust length
+        //
+        long length64 = ((long)height - 1L) * scanLength64 + (long)width;
+        final int alpha = aProcessAlpha ? 1 : 0;
+
+        synchronized (iBuffer)
+        {
+            //
+            // ensure pending drawing commands are complete first
+            //
+            iBuffer.sync();
+
+            //
+            // Blocking server call to do Bitblt server side:
+            //
+            NativeError.check(_drawPixels(
+                                  iBuffer.getHandle(),
+                                  iHandle,
+                                  TYPE_INT_ARGB_8888,
+                                  rgbSL,
+                                  (int)offset64,
+                                  (int)length64,
+                                  (int)scanLength64,
+                                  aProcessAlpha,
+                                  x1,
+                                  y1,
+                                  width,
+                                  height,
+                                  transform
+                              ));
+        }
+    }
+
+    public void fillTriangle(int aX1, int aY1, int aX2, int aY2, int aX3, int aY3)
+    {
+        if (isDownscaled())
+        {
+            // If is downscaling on, then it downscales triangle.
+            aX1 = (aX1 * iOnScreenWidth) / iWidth;
+            aY1 = (aY1 * iOnScreenHeight) / iHeight;
+            aX2 = (aX2 * iOnScreenWidth) / iWidth;
+            aY2 = (aY2 * iOnScreenHeight) / iHeight;
+            aX3 = (aX3 * iOnScreenWidth) / iWidth;
+            aY3 = (aY3 * iOnScreenHeight) / iHeight;
+        }
+        synchronized (iBuffer)
+        {
+            // Send triangle to native graphics.
+            iBuffer.write(iHandle, OP_FILL_TRIANGLE, aX1, aY1, aX2, aY2, aX3, aY3);
+        }
+    }
+
+    // New in MIDP 2.0
+    public void copyArea(int aXsrc,int aYsrc,int aWidth,int aHeight,int aXdest,int aYdest,int aAnchor)
+    {
+        synchronized (iBuffer)
+        {
+            if (null == iImage)
+            {
+                throw new IllegalStateException("cannot copyArea on display");
+            }
+
+            /*
+             * Silently ignore - even if the source point is out of bounds.
+             */
+            if (aWidth <= 0 || aHeight <= 0)
+            {
+                return;
+            }
+
+            final int sx1 = aXsrc;
+            final int sy1 = aYsrc;
+            final int sx2 = aXsrc + aWidth;
+            final int sy2 = aYsrc + aHeight;
+
+            //
+            // (sx1,sy1,sx2,sy2) source rectangle is inclusive-exclusive
+            //
+            // Top left coordinate must be contained within drawing surface.
+            //
+            // Bottom right coordinate may extend one pixel to right or below
+            // drawing surface bottom right coordinate.
+            //
+            if ((sx1<0) || (sx1>=iWidth) || (sy1<0) || (sy1>=iHeight) ||
+                    (sx2<0) || (sx2>iWidth)  || (sy2<0) || (sy2>iHeight))
+            {
+                throw new IllegalArgumentException("copyArea source rect out of bounds");
+            }
+
+            checkAnchor(aAnchor, IMAGE_ANCHOR_MASK);
+
+
+            iBuffer.write(
+                iHandle,
+                OP_COPY_AREA,
+                aXsrc,
+                aYsrc,
+                aWidth,
+                aHeight,
+                aXdest,
+                aYdest,
+                aAnchor
+            );
+        }
+    }
+
+    public void drawRegion(
+        Image aImage,
+        int aXsrc,
+        int aYsrc,
+        int aWidth,
+        int aHeight,
+        int aTransform,
+        int aXdest,
+        int aYdest,
+        int aAnchor)
+    {
+        // giving a size of aImage
+        int srcWidth = aImage.getWidth();
+        int srcHeight = aImage.getHeight();
+
+        // If drawing area is empty, then return.
+        if ((aWidth <= 0) || (aHeight <= 0))
+        {
+            return;
+        }
+
+        // Drawing from image to the same image is not allowed.
+        if (iTarget == aImage)
+        {
+            throw new IllegalArgumentException("Cannot draw image onto itself");
+        }
+
+        // checking if drawing area is correct
+        int sx1 = aXsrc;
+        int sy1 = aYsrc;
+        int sx2 = aXsrc + aWidth;
+        int sy2 = aYsrc + aHeight;
+        if (sx1 < 0 || sy1 < 0 || sx2 > srcWidth || sy2 > srcHeight)
+        {
+            throw new IllegalArgumentException();
+        }
+
+        // checking of anchor
+        checkAnchor(aAnchor, IMAGE_ANCHOR_MASK);
+
+        // checking of legality of trasformation
+        if (aTransform < TRANS_MIN || aTransform > TRANS_MAX)
+        {
+            throw new IllegalArgumentException("Transform");
+        }
+
+        // checking if downscaling is on
+        if (isDownscaled())
+        {
+            // downscaling of drawing point and area
+            aXdest = (aXdest * iOnScreenWidth) / iWidth;
+            aYdest = (aYdest * iOnScreenHeight) / iHeight;
+            aWidth = (aWidth * iOnScreenWidth) / iWidth;
+            aHeight = (aHeight * iOnScreenHeight) / iHeight;
+
+            // getting of size of non-scaled image
+            int widthL = aImage.getWidth();
+            int heightL = aImage.getHeight();
+
+            // array for RGB data from non-scaled image
+            int rgbL[] = new int[widthL * heightL];
+
+            // getting RGB data
+            aImage.getRGB(rgbL, 0, widthL, 0, 0, widthL, heightL);
+
+            // downscaling of size of image
+            int widthSL = (widthL * iOnScreenWidth) / iWidth;
+            int heightSL = (heightL * iOnScreenHeight) / iHeight;
+
+            // array for RGB data for scaled image
+            int rgbSL[] = new int[widthSL * heightSL];
+
+            // downscaling RGB data
+            getDownscaledRGB(rgbSL, rgbL, widthL, heightL);
+
+            // creating image from scaled RGB data
+            Image image = Image.createRGBImage(rgbSL, widthSL, heightSL, true);
+
+            // scaling  of size of size of image
+            aXsrc = ((widthSL * aXsrc) / widthL);
+            aYsrc = ((heightSL * aYsrc) / heightL);
+
+            //
+            // finding of new drawing start point in source image
+            // This is the same algorithm like in getDownscaledRGB method.
+            //
+            int srcXL = widthSL;
+            int srcYL = heightSL;
+            int residueWidth = widthL;
+            int residueHeight = heightL;
+            for (int i = 0; i < widthSL; i++)
+            {
+                residueWidth -= (int)((double)((float)residueWidth /
+                                               (float)(widthSL - i)) + 0.5D);
+                if (widthL - residueWidth > aXsrc)
+                    break;
+            }
+
+            for (int j = 0; j < heightSL; j++)
+            {
+                residueHeight -= (int)((double)((float)residueHeight /
+                                                (float)(heightSL - j)) + 0.5D);
+                if (heightL - residueHeight > aYsrc)
+                    break;
+            }
+
+            synchronized (iBuffer)
+            {
+                // sending data to native side
+                iBuffer.write(iHandle,
+                              OP_DRAW_REGION,
+                              image.iHandle,
+                              widthL - residueWidth,
+                              heightL - residueHeight,
+                              aWidth, aHeight,
+                              aTransform,
+                              aXdest,
+                              aYdest,
+                              aAnchor);
+            }
+        }
+        else
+        {
+            synchronized (iBuffer)
+            {
+                // If downscaling off, then it only send data to native side
+                iBuffer.write(iHandle,
+                              OP_DRAW_REGION,
+                              aImage.iHandle,
+                              aXsrc,
+                              aYsrc,
+                              aWidth,
+                              aHeight,
+                              aTransform,
+                              aXdest,
+                              aYdest,
+                              aAnchor);
+            }
+        }
+    }
+
+    void flush(int aX, int aY, int aWidth, int aHeight)
+    {
+        if (isDownscaled())
+        {
+            // If downscaling on, then it downscales flushed area.
+            aX = (aX * iOnScreenWidth) / iWidth;
+            aY = (aY * iOnScreenHeight) / iHeight;
+            aWidth = (aWidth * iOnScreenWidth) / iWidth;
+            aHeight = (aHeight * iOnScreenHeight) / iHeight;
+        }
+        synchronized (iBuffer)
+        {
+            // sending data to native side
+            iBuffer.write(iHandle, OP_FLUSH, aX, aY, aWidth, aHeight);
+            iBuffer.sync();
+        }
+    }
+
+    /**
+     * Send draw background command to native side
+     * @param aDisplayable The target Displayable object
+     * @param aX X position
+     * @param aY Y position
+     * @param aWidth Width
+     * @param aHeight Height
+     * @since S60 5.0
+     */
+    void drawBackground(Displayable aDisplayable,
+                        int aX,
+                        int aY,
+                        int aWidth,
+                        int aHeight)
+    {
+        // If aDisplayable is not Canvas or a Displayable is null,
+        // then drawBackround do nothing.
+        if (aDisplayable == null || !(aDisplayable instanceof Canvas))
+            return;
+        if (isDownscaled())
+        {
+            // If downscaling on, then it downscales flushed area.
+            aX = (aX * iOnScreenWidth) / iWidth;
+            aY = (aY * iOnScreenHeight) / iHeight;
+            aWidth = (aWidth * iOnScreenWidth) / iWidth;
+            aHeight = (aHeight * iOnScreenHeight) / iHeight;
+        }
+        synchronized (iBuffer)
+        {
+            // sending data to native side
+            iBuffer.write(iHandle, 20, aDisplayable.getContentHandle(), aX, aY, aWidth, aHeight);
+        }
+    }
+
+    /**
+     * This function return flag if Graphics is downscaled.
+     * Graphics is downscaled on if we have set original size, this size is bigger then screen
+     * (at least on one measure) and iTarget is Canvas in full screen Canvas or a target size is
+     * smaller than original size.
+     * @return true if Graphics is downscaled, false otherwise
+     */
+    boolean isDownscaled()
+    {
+        if ((iTarget instanceof Canvas) && ((Canvas)iTarget).getFullScreenMode()
+                && iIsSetOriginalSize)
+        {
+            return iOnScreenHeight < iHeight || iOnScreenWidth < iWidth ;
+        }
+        return false;
+    }
+
+    /**
+     * This function returns downscaled GRB data from input RGB data. It scales
+     * according iOnScreenWidth, iOnScreenHeight, iWidth and iHeight.
+     * @param aRgbS array for output RGB data. This have to be defined with needed lenght.
+     * @param aRgb input data
+     * @param aWidth width of aRgb
+     * @param aHeight height of aRgb
+     */
+    private void getDownscaledRGB(int aRgbS[], int aRgb[], int aWidth, int aHeight)
+    {
+        // downscaling of size of aRgb
+        int widthS = (aWidth * iOnScreenWidth) / iWidth;
+        int heightS = (aHeight * iOnScreenHeight) / iHeight;
+
+        // help variables for remaining columns and rows
+        int residueWidth = aWidth;
+        int residueHeight = aHeight;
+
+        // help variables for count of columns and rows of non-scaled RGB data
+        // scaled to one pixel of downscaled image
+        int columnWidths[] = new int[widthS];
+        int rowHeights[] = new int[heightS];
+
+        // If aRgbS has lenght shorter then needed.
+        if (aRgbS.length < widthS * heightS)
+            throw new IllegalArgumentException();
+
+        // computing of count of columns of non-scaled RGB data
+        // scaled to one column of downscaled image
+        for (int i = 0; i < widthS; i++)
+        {
+            columnWidths[i] = (int)((double)((float)residueWidth /
+                                             (float)(widthS - i)) + 0.5D);
+            residueWidth -= columnWidths[i];
+        }
+
+        // computing of count of rows of non-scaled RGB data
+        // scaled to one row of downscaled image
+        for (int i = 0; i < heightS; i++)
+        {
+            rowHeights[i] = (int)((double)((float)residueHeight /
+                                           (float)(heightS - i)) + 0.5D);
+            residueHeight -= rowHeights[i];
+        }
+
+        // It goes through all columns of output image.
+        int posX = 0;
+        for (int i = 0; i < widthS; i++)
+        {
+            // getting of number of columns which will be scaled to one column
+            int w = columnWidths[i];
+            int posY = 0;
+            // It goes through all rows of output image.
+            for (int j = 0; j < heightS; j++)
+            {
+                // getting of number of rows which will be scaled to one row
+                int h = rowHeights[j];
+
+                if (w == 1 && h == 1)
+                {
+                    // The recalculating of this pixel is not needed.
+                    aRgbS[j * widthS + i] = aRgb[posY * aWidth + posX];
+                    posY++;
+                }
+                else
+                {
+                    // The recalculating of this pixel is needed.
+
+                    // We have to use char because char is only one
+                    // unsigned integer type in Java.
+                    char sumRed = '\0';
+                    char sumGreen = '\0';
+                    char sumBlue = '\0';
+                    char sumAlpha = '\0';
+
+                    // It goes through columns of output image,
+                    // what will be downscaled to one column.
+                    for (int k = 0; k < w; k++)
+                    {
+                        // It goes through rows of output image,
+                        // what will be downscaled to one row.
+                        for (int l = 0; l < h; l++)
+                        {
+                            // getting of current pixel
+                            int pixel = aRgb[(posY + l) * aWidth + (posX + k)];
+
+                            // adding values of one pixel
+                            sumRed += (pixel & 0xff0000) >> 16;
+                            sumGreen += (pixel & 0xff00) >> 8;
+                            sumBlue += pixel & 0xff;
+                            sumAlpha += (pixel & 0xff000000) >> 24;
+                        }
+
+                    }
+
+                    // calculating of new pixel
+                    aRgbS[j * widthS + i] = sumRed / (w * h) << 16 |
+                                            sumGreen / (w * h) << 8 |
+                                            sumBlue / (w * h)|
+                                            sumAlpha / (w * h) << 24;
+
+                    // new set of rows
+                    posY += h;
+                }
+            }
+
+            // new set of columns
+            posX += w;
+        }
+
+    }
+
+    /**
+     * This function returns array with the same RGB data as input,
+     * but with scanlenght > 0 and offset = 0.
+     * @param aRgb input RGB data
+     * @param aOffset offset of aRgb
+     * @param aScanlenght scalenght of aRgb
+     * @param aWidth width of aRgb
+     * @param aHeight height of aRgb
+     */
+    private int[] cleanRGB(int aRgb[],
+                           int aOffset,
+                           int aScanlenght,
+                           int aWidth,
+                           int aHeight)
+    {
+        // creating output array
+        int output[] = new int[aWidth * aHeight];
+
+        // resorting of input array to output array
+        for (int i = 0; i < aHeight; i++)
+        {
+            for (int j = 0; j < aWidth; j++)
+            {
+                output[i * aWidth + j] = aRgb[aOffset + i * aScanlenght + j];
+            }
+        }
+
+        // return of resorted array
+        return output;
+    }
+
+    private native int _create(int i, int j);
+
+    private static native int _drawPixels
+    (
+        int aBuffer,
+        int aHandle,
+        int aType,
+        int[] aArray,
+        int aOffset,
+        int aLength,
+        int aScanLength,
+        boolean aProcessAlpha,
+        int aX,
+        int aY,
+        int aWidth,
+        int aHeight,
+        int aTransform
+    );
+
+    private static native int _getDisplayColor(int aToolkit, int aHandle, int aRgb);
+}