summaryrefslogtreecommitdiffstats
path: root/bundles/org.eclipse.swt/Eclipse SWT/common/org
diff options
context:
space:
mode:
authorVeronika Irvine <torres>2001-05-11 13:46:50 +0000
committerVeronika Irvine <torres>2001-05-11 13:46:50 +0000
commit3275970ab8046022b8d2069b5c21bf117c223db7 (patch)
tree23ac5a3259be894e958f59fdd4103679c544e889 /bundles/org.eclipse.swt/Eclipse SWT/common/org
downloadeclipse.platform.swt-3275970ab8046022b8d2069b5c21bf117c223db7.tar.gz
eclipse.platform.swt-3275970ab8046022b8d2069b5c21bf117c223db7.tar.xz
eclipse.platform.swt-3275970ab8046022b8d2069b5c21bf117c223db7.zip
initializing database with SWT 0.105
Diffstat (limited to 'bundles/org.eclipse.swt/Eclipse SWT/common/org')
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/SWT.java1810
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/SWTError.java80
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/SWTException.java73
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ArmEvent.java29
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ArmListener.java32
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ControlAdapter.java40
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ControlEvent.java31
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ControlListener.java42
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/DisposeEvent.java30
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/DisposeListener.java33
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/FocusAdapter.java39
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/FocusEvent.java30
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/FocusListener.java42
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/HelpEvent.java30
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/HelpListener.java34
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/KeyAdapter.java39
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/KeyEvent.java48
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/KeyListener.java41
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MenuAdapter.java39
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MenuEvent.java30
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MenuListener.java40
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ModifyEvent.java30
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ModifyListener.java32
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MouseAdapter.java52
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MouseEvent.java68
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MouseListener.java51
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MouseMoveListener.java32
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MouseTrackAdapter.java53
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MouseTrackListener.java53
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/PaintEvent.java76
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/PaintListener.java33
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/SelectionAdapter.java39
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/SelectionEvent.java76
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/SelectionListener.java50
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ShellAdapter.java66
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ShellEvent.java30
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ShellListener.java61
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/TraverseEvent.java41
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/TraverseListener.java40
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/TreeAdapter.java39
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/TreeEvent.java30
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/TreeListener.java41
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/TypedEvent.java56
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/VerifyEvent.java51
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/VerifyListener.java39
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/package.html22
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Drawable.java45
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageData.java3451
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageLoader.java284
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageLoaderEvent.java78
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageLoaderListener.java39
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/PaletteData.java205
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Point.java93
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/RGB.java108
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Rectangle.java264
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/package.html17
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/Callback.java270
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/FileFormat.java108
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/GIFFileFormat.java522
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGAppn.java24
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGArithmeticConditioningTable.java17
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGComment.java21
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGEndOfImage.java25
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGFileFormat.java1891
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGFixedSizeSegment.java38
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGFrameHeader.java203
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGHuffmanTable.java262
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGQuantizationTable.java159
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGRestartInterval.java25
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGScanHeader.java117
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGSegment.java54
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGStartOfImage.java29
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGVariableSizeSegment.java32
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/LEDataInputStream.java88
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/LEDataOutputStream.java54
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/LZWCodec.java479
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/LZWNode.java13
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PNGFileFormat.java525
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngChunk.java333
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngChunkReader.java64
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngDecodingDataStream.java131
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngFileReadState.java20
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngHuffmanTable.java122
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngHuffmanTables.java156
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngIdatChunk.java36
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngIendChunk.java39
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngIhdrChunk.java372
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngLzBlockReader.java169
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngPlteChunk.java87
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngTrnsChunk.java133
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/WinBMPFileFormat.java667
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/WinICOFileFormat.java284
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/package.html18
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/package.html20
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/FillLayout.java67
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/GridData.java157
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/GridLayout.java638
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/RowData.java29
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/RowLayout.java151
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/package.html13
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/package.html15
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Dialog.java207
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Event.java84
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/EventTable.java85
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Item.java110
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Layout.java76
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Listener.java45
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/RunnableLock.java32
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Synchronizer.java140
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/TypedListener.java222
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/package.html15
111 files changed, 18050 insertions, 0 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/SWT.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/SWT.java
new file mode 100755
index 0000000000..1ace85cf6c
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/SWT.java
@@ -0,0 +1,1810 @@
+package org.eclipse.swt;
+
+import org.eclipse.swt.internal.*;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+/**
+ * This class provides access to a small number of SWT system-wide
+ * methods, and in addition defines the public constants provided
+ * by SWT.
+ * <p>
+ * By defining constants like UP and DOWN in a single class, SWT
+ * can share common names and concepts at the same time minimizing
+ * the number of classes, names and constants for the application
+ * programmer.
+ * </p><p>
+ * Note that, some of the constants provided by this class represent
+ * optional, appearance related aspects of widgets which are available
+ * either only on some window systems, or for a differing set of
+ * widgets on each window system. These constants are marked
+ * as <em>HINT</em>s. The set of widgets which support a particular
+ * <em>HINT</em> may change from release to release, although we typically
+ * will not withdraw support for a <em>HINT</em> once it is made available.
+ * </p>
+ */
+
+/* NOTE:
+ * Good javadoc coding style is to put the values of static final
+ * constants in the comments. This re-inforces the fact that
+ * consumers are allowed to rely on the value (and they must
+ * since the values are compiled inline in their code). We
+ * can <em>not</em> change the values of these constants between
+ * releases.
+ */
+public class SWT {
+
+ /* Widget Event Constants */
+
+ /**
+ * key down event type (value is 1)
+ */
+ public static final int KeyDown = 1;
+
+ /**
+ * key up event type (value is 2)
+ */
+ public static final int KeyUp = 2;
+
+ /**
+ * mouse down event type (value is 3)
+ */
+ public static final int MouseDown = 3;
+
+ /**
+ * mouse up event type (value is 4)
+ */
+ public static final int MouseUp = 4;
+
+ /**
+ * mouse move event type (value is 5)
+ */
+ public static final int MouseMove = 5;
+
+ /**
+ * mouse enter event type (value is 6)
+ */
+ public static final int MouseEnter = 6;
+
+ /**
+ * Mouse exit event type (value is 7)
+ */
+ public static final int MouseExit = 7;
+
+ /**
+ * mouse double click event type (value is 8)
+ */
+ public static final int MouseDoubleClick = 8;
+
+ /**
+ * paint event type (value is 9)
+ */
+ public static final int Paint = 9;
+
+ /**
+ * pove event type (value is 10)
+ */
+ public static final int Move = 10;
+
+ /**
+ * resize event type (value is 11)
+ */
+ public static final int Resize = 11;
+
+ /**
+ * dispose event type (value is 12)
+ */
+ public static final int Dispose = 12;
+
+ /**
+ * selection event type (value is 13)
+ */
+ public static final int Selection = 13;
+
+ /**
+ * default selection event type (value is 14)
+ */
+ public static final int DefaultSelection = 14;
+
+ /**
+ * focus in event type (value is 15)
+ */
+ public static final int FocusIn = 15;
+
+ /**
+ * focus out event type (value is 16)
+ */
+ public static final int FocusOut = 16;
+
+ /**
+ * expand event type (value is 17)
+ */
+ public static final int Expand = 17;
+
+ /**
+ * collapse event type (value is 18)
+ */
+ public static final int Collapse = 18;
+
+ /**
+ * iconify event type (value is 19)
+ */
+ public static final int Iconify = 19;
+
+ /**
+ * de-iconify event type (value is 20)
+ */
+ public static final int Deiconify = 20;
+
+ /**
+ * close event type (value is 21)
+ */
+ public static final int Close = 21;
+
+ /**
+ * show event type (value is 22)
+ */
+ public static final int Show = 22;
+
+ /**
+ * hide event type (value is 23)
+ */
+ public static final int Hide = 23;
+
+ /**
+ * modify event type (value is 24)
+ */
+ public static final int Modify = 24;
+
+ /**
+ * verify event type (value is 25)
+ */
+ public static final int Verify = 25;
+
+ /**
+ * activate event type (value is 26)
+ */
+ public static final int Activate = 26;
+
+ /**
+ * deactivate event type (value is 27)
+ */
+ public static final int Deactivate = 27;
+
+ /**
+ * help event type (value is 28)
+ */
+ public static final int Help = 28;
+
+ /**
+ * drag detect event type (value is 29)
+ */
+ public static final int DragDetect = 29;
+
+ /**
+ * arm event type (value is 30)
+ */
+ public static final int Arm = 30;
+
+ /**
+ * traverse event type (value is 31)
+ */
+ public static final int Traverse = 31;
+
+ /**
+ * mouse hover event type (value is 32)
+ */
+ public static final int MouseHover = 32;
+
+ /* Event Details */
+
+ /**
+ * a constant known to be zero (0), used in operations which
+ * take bit flags to indicate that "no bits are set"
+ */
+ public static final int NONE = 0;
+
+ /**
+ * indicates that a user-interface component is being dragged,
+ * for example dragging the thumb of a scroll bar (value is 1)
+ */
+ public static final int DRAG = 1;
+
+ /**
+ * a constant known to be zero (0), used in operations which
+ * take pointers to indicate a null argument
+ */
+ public static final int NULL = 0;
+
+ /**
+ * indicates that a default should be used (value is -1)
+ */
+ public static final int DEFAULT = -1;
+
+ /**
+ * <code>Menu</code> style constant for menu bar behavior (value is 1<<1)
+ */
+ public static final int BAR = 1 << 1;
+
+ /**
+ * <code>Menu</code> style constant for drop down menu behavior (value is 1<<2)
+ */
+ public static final int DROP_DOWN = 1 << 2;
+
+ /**
+ * <code>Menu</code> style constant for pop up menu behavior (value is 1<<3)
+ */
+ public static final int POP_UP = 1 << 3;
+
+ /**
+ * <code>MenuItem</code> style constant for line separator behavior (value is 1<<1)
+ */
+ public static final int SEPARATOR = 1 << 1;
+
+ /* Button, MenuItem Constants */
+
+ /**
+ * <code>Button</code> style constant for toggle button behavior (value is 1<<1)
+ */
+ public static final int TOGGLE = 1 << 1;
+
+ /**
+ * <code>Button</code> style constant for arrow button behavior (value is 1<<2)
+ */
+ public static final int ARROW = 1 << 2;
+
+ /**
+ * <code>Button</code> and <code>MenuItem</code>
+ * style constant for push button behavior (value is 1<<3)
+ */
+ public static final int PUSH = 1 << 3;
+
+ /**
+ * <code>Button</code> and <code>MenuItem</code>
+ * style constant for radio button behavior (value is 1<<4)
+ */
+ public static final int RADIO = 1 << 4;
+
+ /**
+ * <code>Button</code> and <code>MenuItem</code>
+ * style constant for check box behavior (value is 1<<5)
+ */
+ public static final int CHECK = 1 << 5;
+
+ /**
+ * <code>MenuItem</code> style constant for cascade behavior (value is 1<<6)
+ */
+ public static final int CASCADE = 1 << 6;
+
+ /**
+ * <code>Text</code> and <code>List</code>
+ * style constant for multi-selection behavior in lists
+ * and multiple line support on text fields (value is 1<<1)
+ */
+ public static final int MULTI = 1 << 1;
+
+ /**
+ * <code>Text</code> and <code>List</code>
+ * style constant for single selection behavior in lists
+ * and single line support on text fields (value is 1<<2)
+ */
+ public static final int SINGLE = 1 << 2;
+
+ /**
+ * <code>Text</code> style constant for read-only behavior (value is 1<<3)
+ */
+ public static final int READ_ONLY = 1 << 3;
+
+ /**
+ * <code>Text</code> style constant for auto-line wrap behavior (value is 1<<6)
+ */
+ public static final int WRAP = 1 << 6;
+
+ /**
+ * <code>Combo</code> style constant for simple (not drop down) behavior (value is 1<<6)
+ */
+ public static final int SIMPLE = 1 << 6;
+
+ /**
+ * <code>Group</code> and <code>Label</code>
+ * style constant for shadow in behavior (value is 1<<2)
+ */
+ public static final int SHADOW_IN = 1 << 2;
+
+ /**
+ * <code>Group</code>, <code>Label</code> and <code>CustomLabel</code>
+ * style constant for shadow out behavior (value is 1<<3)
+ */
+ public static final int SHADOW_OUT = 1 << 3;
+
+ /**
+ * <code>Group</code> style constant for shadow etched in behavior (value is 1<<4)
+ * NOTE: This style is ignored on all platforms except Motif
+ */
+ public static final int SHADOW_ETCHED_IN = 1 << 4;
+
+ /**
+ * <code>Label</code> style constant for no shadow behavior (value is 1<<5)
+ */
+ public static final int SHADOW_NONE = 1 << 5;
+
+ /**
+ * <code>Group</code> style constant for shadow etched out behavior (value is 1<<6)
+ * NOTE: This style is ignored on all platforms except Motif
+ */
+ public static final int SHADOW_ETCHED_OUT = 1 << 6;
+
+ /**
+ * <code>Shell</code> style constant for tool window behavior (value is 1<<2)
+ */
+ public static final int TOOL = 1 << 2;
+
+ /**
+ * <code>Shell</code> style constant to ensure no trimmings are used.
+ * This overrides all other trim styles (value is 1<<3)
+ */
+ public static final int NO_TRIM = 1 << 3;
+
+ /**
+ * <code>Shell</code> style constant for resize box trim (value is 1<<4)
+ */
+ public static final int RESIZE = 1 << 4;
+
+ /**
+ * <code>Shell</code> style constant for title area trim (value is 1<<5)
+ */
+ public static final int TITLE = 1 << 5;
+
+ /**
+ * <code>Shell</code> style constant for close box trim (value is 1<<6,
+ * since we do not distinguish between CLOSE style and MENU style)
+ */
+ public static final int CLOSE = 1 << 6;
+
+ /**
+ * <code>Shell</code> style constant for shell menu trim (value is 1<<6,
+ * since we do not distinguish between CLOSE style and MENU style)
+ */
+ public static final int MENU = CLOSE;
+
+ /**
+ * <code>Shell</code> style constant for minimize box trim (value is 1<<7)
+ */
+ public static final int MIN = 1 << 7;
+
+ /* ScrollBar, Composite, Shell Constants */
+
+ /**
+ * <code>ScrollBar</code>, <code>Composite</code> and <code>Shell</code>
+ * style constant for horizontal scrollbar behavior (value is 1<<8)
+ */
+ public static final int H_SCROLL = 1 << 8;
+
+ /**
+ * <code>ScrollBar</code>, <code>Composite</code> and <code>Shell</code>
+ * style constant for vertical scrollbar behavior (value is 1<<9)
+ */
+ public static final int V_SCROLL = 1 << 9;
+
+ /**
+ * <code>Shell</code> style constant for maximize box trim (value is 1<<10)
+ */
+ public static final int MAX = 1 << 10;
+
+ /**
+ * all <code>Widget</code> style constant for bordered behavior (value is 1<<11)
+ */
+ public static final int BORDER = 1 << 11;
+
+ /**
+ * all <code>Widget</code> style constant indicating that the window
+ * manager should clip a widget's children with respect to its viewable
+ * area. Note that this is a <em>HINT</em>. (value is 1<<12)
+ */
+ public static final int CLIP_CHILDREN = 1 << 12;
+
+ /**
+ * all <code>Widget</code> style constant indicating that the window
+ * manager should clip a widget's siblings with respect to its viewable
+ * area. Note that this is a <em>HINT</em>. (value is 1<<13)
+ */
+ public static final int CLIP_SIBLINGS = 1 << 13;
+
+ /**
+ * <code>Shell</code> style constant for always on top behavior (value is 1<<14)
+ */
+ public static final int ON_TOP = 1 << 14;
+
+ /**
+ * <code>Shell</code> trim style convenience constant for the
+ * most common top level shell appearance
+ * (value is CLOSE|TITLE|MIN|MAX|RESIZE)
+ */
+ public static final int SHELL_TRIM = CLOSE | TITLE | MIN | MAX | RESIZE;
+
+ /**
+ * <code>Shell</code> trim style convenience constant for the
+ * most common dialog shell appearance
+ * (value is CLOSE|TITLE|BORDER)
+ */
+ public static final int DIALOG_TRIM = TITLE | CLOSE | BORDER;
+
+ /**
+ * <code>Shell</code> style constant for modeless behavior (value is 0)
+ */
+ public static final int MODELESS = 0;
+
+ /**
+ * <code>Shell</code> style constant for primary modal behavior (value is 1<<15)
+ */
+ public static final int PRIMARY_MODAL = 1 << 15;
+
+ /**
+ * <code>Shell</code> style constant for application modal behavior (value is 1<<16)
+ */
+ public static final int APPLICATION_MODAL = 1 << 16;
+
+ /**
+ * <code>Shell</code> style constant for system modal behavior (value is 1<<17)
+ */
+ public static final int SYSTEM_MODAL = 1 << 17;
+
+ /**
+ * all <code>Widget</code> style constant for selection hiding
+ * behavior. Note that this is a <em>HINT</em>. (value is 1<<15)
+ */
+ public static final int HIDE_SELECTION = 1 << 15;
+
+ /**
+ * all <code>Widget</code> style constant for full row selection
+ * behavior. Note that this is a <em>HINT</em>. (value is 1<<16 since
+ * FULL_SELECTION and SMOOTH share the same value, but are
+ * implemented on non-intersecting sets of widgets)
+ */
+ public static final int FULL_SELECTION = 1 << 16;
+
+ /**
+ * all <code>Widget</code> style constant for flat appearance.
+ * Note that this is a <em>HINT</em>. (value is 1<<23)
+ */
+ public static final int FLAT = 1 << 23;
+
+ /**
+ * all <code>Widget</code> style constant for flat appearance.
+ * Note that this is a <em>HINT</em>. (value is 1<<16 since
+ * FULL_SELECTION and SMOOTH share the same value, but are
+ * implemented on non-intersecting sets of widgets)
+ */
+ public static final int SMOOTH = FULL_SELECTION;
+
+ /**
+ * <code>Canvas</code> style constant for no background behavior (value is 1<<18)
+ */
+ public static final int NO_BACKGROUND = 1 << 18;
+
+ /**
+ * <code>Canvas</code> style constant for does not take focus behavior (value is 1<<19)
+ */
+ public static final int NO_FOCUS = 1 << 19;
+
+ /**
+ * <code>Canvas</code> style constant for no redraw on resize behavior (value is 1<<20)
+ */
+ public static final int NO_REDRAW_RESIZE = 1 << 20;
+
+ /**
+ * <code>Canvas</code> style constant for no paint event merging
+ * behavior (value is 1<<21)
+ */
+ public static final int NO_MERGE_PAINTS = 1 << 21;
+
+ /**
+ * <code>Canvas</code> style constant for preventing child radio group
+ * behavior (value is 1<<22)
+ */
+ public static final int NO_RADIO_GROUP = 1 << 22;
+
+ /**
+ * various <code>Widget</code> and <code>Layout</code>
+ * style constant for align up behavior (value is 1<<7, since
+ * align UP and align TOP are considered the same)
+ */
+ public static final int UP = 1 << 7;
+
+ /**
+ * various <code>Widget</code> and <code>Layout</code>
+ * style constant for align top behavior (value is 1<<7, since
+ * align UP and align TOP are considered the same)
+ */
+ public static final int TOP = UP;
+
+ /**
+ * various <code>Widget</code> and <code>Layout</code>
+ * style constant for align down behavior (value is 1<<10, since
+ * align DOWN and align BOTTOM are considered the same)
+ */
+ public static final int DOWN = 1 << 10;
+
+ /**
+ * various <code>Widget</code> and <code>Layout</code>
+ * style constant for align bottom behavior (value is 1<<10, since
+ * align DOWN and align BOTTOM are considered the same)
+ */
+ public static final int BOTTOM = DOWN;
+
+ /**
+ * various <code>Widget</code> and <code>Layout</code>
+ * style constant for align left behavior (value is 1<<14)
+ */
+ public static final int LEFT = 1 << 14;
+
+ /**
+ * various <code>Widget</code> and <code>Layout</code>
+ * style constant for align right behavior (value is 1<<17)
+ */
+ public static final int RIGHT = 1 << 17;
+
+ /**
+ * various <code>Widget</code> and <code>Layout</code>
+ * style constant for align center behavior (value is 1<<24)
+ */
+ public static final int CENTER = 1 << 24;
+
+ /**
+ * various <code>Widget</code> and <code>Layout</code>
+ * style constant for align horizontal behavior (value is 1<<8)
+ */
+ public static final int HORIZONTAL = H_SCROLL;
+
+ /**
+ * various <code>Widget</code> and <code>Layout</code>
+ * style constant for align vertical behavior (value is 1<<9)
+ */
+ public static final int VERTICAL = V_SCROLL;
+
+ /**
+ * Input Method Editor style constant for double byte
+ * input behavior (value is 1<<1)
+ */
+ public static final int DBCS = 1 << 1;
+
+ /**
+ * Input Method Editor style constant for alpha
+ * input behavior (value is 1<<2)
+ */
+ public static final int ALPHA = 1 << 2;
+
+ /**
+ * Input Method Editor style constant for native
+ * input behavior (value is 1<<3)
+ */
+ public static final int NATIVE = 1 << 3;
+
+ /**
+ * Input Method Editor style constant for phonetic
+ * input behavior (value is 1<<4)
+ */
+ public static final int PHONETIC = 1 << 4;
+
+ /**
+ * Input Method Editor style constant for romanicized
+ * input behavior (value is 1<<5)
+ */
+ public static final int ROMAN = 1 << 5;
+
+ /**
+ * ASCII character convenience constant for the escape character
+ * (value is the <code>char</code> with value 27)
+ */
+ public static final char ESC = 27;
+
+ /**
+ * ASCII character convenience constant for the delete character
+ * (value is the <code>char</code> with value 127)
+ */
+ public static final char DEL = 0x7F;
+
+ /**
+ * ASCII character convenience constant for the backspace character
+ * (value is the <code>char</code> '\b')
+ */
+ public static final char BS = '\b';
+
+ /**
+ * ASCII character convenience constant for the carriage return character
+ * (value is the <code>char</code> '\r')
+ */
+ public static final char CR = '\r';
+
+ /**
+ * ASCII character convenience constant for the line feed character
+ * (value is the <code>char</code> '\n')
+ */
+ public static final char LF = '\n';
+
+ /**
+ * keyboard and/or mouse event mask indicating that the ALT key
+ * was pushed on the keyboard when the event was generated
+ * (value is 1<<16)
+ */
+ public static final int ALT = 1 << 16;
+
+ /**
+ * keyboard and/or mouse event mask indicating that the SHIFT key
+ * was pushed on the keyboard when the event was generated
+ * (value is 1<<17)
+ */
+ public static final int SHIFT = 1 << 17;
+
+ /**
+ * keyboard and/or mouse event mask indicating that the CTRL key
+ * was pushed on the keyboard when the event was generated
+ * (value is 1<<18)
+ */
+ public static final int CTRL = 1 << 18;
+
+ /**
+ * keyboard and/or mouse event mask indicating that the CTRL key
+ * was pushed on the keyboard when the event was generated. This
+ * is a synonym for CTRL (value is 1<<18)
+ */
+ public static final int CONTROL = CTRL;
+
+ /**
+ * keyboard and/or mouse event mask indicating that mouse button one
+ * was pushed when the event was generated. (value is 1<<19)
+ */
+ public static final int BUTTON1 = 1 << 19;
+
+ /**
+ * keyboard and/or mouse event mask indicating that mouse button two
+ * was pushed when the event was generated. (value is 1<<20)
+ */
+ public static final int BUTTON2 = 1 << 20;
+
+ /**
+ * keyboard and/or mouse event mask indicating that mouse button three
+ * was pushed when the event was generated. (value is 1<<21)
+ */
+ public static final int BUTTON3 = 1 << 21;
+
+ /**
+ * keyboard event constant representing the UP ARROW key
+ * (value is (1<<24)+1)
+ */
+ public static final int ARROW_UP = (1 << 24) + 1;
+
+ /**
+ * keyboard event constant representing the DOWN ARROW key
+ * (value is (1<<24)+2)
+ */
+ public static final int ARROW_DOWN = (1 << 24) + 2;
+
+ /**
+ * keyboard event constant representing the LEFT ARROW key
+ * (value is (1<<24)+3)
+ */
+ public static final int ARROW_LEFT = (1 << 24) + 3;
+
+ /**
+ * keyboard event constant representing the RIGHT ARROW key
+ * (value is (1<<24)+4)
+ */
+ public static final int ARROW_RIGHT = (1 << 24) + 4;
+
+ /**
+ * keyboard event constant representing the PAGE UP key
+ * (value is (1<<24)+5)
+ */
+ public static final int PAGE_UP = (1 << 24) + 5;
+
+ /**
+ * keyboard event constant representing the PAGE DOWN key
+ * (value is (1<<24)+6)
+ */
+ public static final int PAGE_DOWN = (1 << 24) + 6;
+
+ /**
+ * keyboard event constant representing the HOME key
+ * (value is (1<<24)+7)
+ */
+ public static final int HOME = (1 << 24) + 7;
+
+ /**
+ * keyboard event constant representing the END key
+ * (value is (1<<24)+8)
+ */
+ public static final int END = (1 << 24) + 8;
+
+ /**
+ * keyboard event constant representing the INSERT key
+ * (value is (1<<24)+9)
+ */
+ public static final int INSERT = (1 << 24) + 9;
+
+ /**
+ * keyboard event constant representing the F1 key
+ * (value is (1<<24)+10)
+ */
+ public static final int F1 = (1 << 24) + 10;
+
+ /**
+ * keyboard event constant representing the F2 key
+ * (value is (1<<24)+11)
+ */
+ public static final int F2 = (1 << 24) + 11;
+
+ /**
+ * keyboard event constant representing the F3 key
+ * (value is (1<<24)+12)
+ */
+ public static final int F3 = (1 << 24) + 12;
+
+ /**
+ * keyboard event constant representing the F4 key
+ * (value is (1<<24)+13)
+ */
+ public static final int F4 = (1 << 24) + 13;
+
+ /**
+ * keyboard event constant representing the F5 key
+ * (value is (1<<24)+14)
+ */
+ public static final int F5 = (1 << 24) + 14;
+
+ /**
+ * keyboard event constant representing the F6 key
+ * (value is (1<<24)+15)
+ */
+ public static final int F6 = (1 << 24) + 15;
+
+ /**
+ * keyboard event constant representing the F7 key
+ * (value is (1<<24)+16)
+ */
+ public static final int F7 = (1 << 24) + 16;
+
+ /**
+ * keyboard event constant representing the F8 key
+ * (value is (1<<24)+17)
+ */
+ public static final int F8 = (1 << 24) + 17;
+
+ /**
+ * keyboard event constant representing the F9 key
+ * (value is (1<<24)+18)
+ */
+ public static final int F9 = (1 << 24) + 18;
+
+ /**
+ * keyboard event constant representing the F10 key
+ * (value is (1<<24)+19)
+ */
+ public static final int F10 = (1 << 24) + 19;
+
+ /**
+ * keyboard event constant representing the F11 key
+ * (value is (1<<24)+20)
+ */
+ public static final int F11 = (1 << 24) + 20;
+
+ /**
+ * keyboard event constant representing the F12 key
+ * (value is (1<<24)+21)
+ */
+ public static final int F12 = (1 << 24) + 21;
+
+ /**
+ * <code>MessageBox</code> style constant for error icon
+ * behavior (value is 1)
+ */
+ public static final int ICON_ERROR = 1;
+
+ /**
+ * <code>MessageBox</code> style constant for information icon
+ * behavior (value is 1<<1)
+ */
+ public static final int ICON_INFORMATION = 1 << 1;
+
+ /**
+ * <code>MessageBox</code> style constant for question icon
+ * behavior (value is 1<<2)
+ */
+ public static final int ICON_QUESTION = 1 << 2;
+
+ /**
+ * <code>MessageBox</code> style constant for warning icon
+ * behavior (value is 1<<3)
+ */
+ public static final int ICON_WARNING = 1 << 3;
+
+ /**
+ * <code>MessageBox</code> style constant for "working" icon
+ * behavior (value is 1<<1)
+ */
+ public static final int ICON_WORKING = 1 << 4;
+
+ /**
+ * <code>MessageBox</code> style constant for an OK button.
+ * Valid combinations are OK, OK|CANCEL
+ * (value is 1<<5)
+ */
+ public static final int OK = 1 << 5;
+
+ /**
+ * <code>MessageBox</code> style constant for YES button.
+ * Valid combinations are YES|NO, YES|NO|CANCEL
+ * (value is 1<<6)
+ */
+ public static final int YES = 1 << 6;
+
+ /**
+ * <code>MessageBox</code> style constant for NO button.
+ * Valid combinations are YES|NO, YES|NO|CANCEL
+ * (value is 1<<7)
+ */
+ public static final int NO = 1 << 7;
+
+ /**
+ * <code>MessageBox</code> style constant for a CANCEL button.
+ * Valid combinations are OK|CANCEL, YES|NO|CANCEL, RETRY|CANCEL
+ * (value is 1<<8)
+ */
+ public static final int CANCEL = 1 << 8;
+
+ /**
+ * <code>MessageBox</code> style constant for an ABORT button.
+ * The only valid combination is ABORT|RETRY|IGNORE
+ * (value is 1<<9)
+ */
+ public static final int ABORT = 1 << 9;
+
+ /**
+ * <code>MessageBox</code> style constant for a RETRY button.
+ * Valid combinations are ABORT|RETRY|IGNORE, RETRY|CANCEL
+ * (value is 1<<10)
+ */
+ public static final int RETRY = 1 << 10;
+
+ /**
+ * <code>MessageBox</code> style constant for an IGNORE button.
+ * The only valid combination is ABORT|RETRY|IGNORE
+ * (value is 1<<11)
+ */
+ public static final int IGNORE = 1 << 11;
+
+ /**
+ * <code>FileDialog</code> style constant for open file dialog behavior
+ * (value is 1<<12)
+ */
+ public static final int OPEN = 1 << 12;
+
+ /**
+ * <code>FileDialog</code> style constant for save file dialog behavior
+ * (value is 1<<13)
+ */
+ public static final int SAVE = 1 << 13;
+
+ /**
+ * default color white (value is 1)
+ */
+ public static final int COLOR_WHITE = 1;
+
+ /**
+ * default color black (value is 2)
+ */
+ public static final int COLOR_BLACK = 2;
+
+ /**
+ * default color red (value is 3)
+ */
+ public static final int COLOR_RED = 3;
+
+ /**
+ * default color dark red (value is 4)
+ */
+ public static final int COLOR_DARK_RED = 4;
+
+ /**
+ * default color green (value is 5)
+ */
+ public static final int COLOR_GREEN = 5;
+
+ /**
+ * default color dark green (value is 6)
+ */
+ public static final int COLOR_DARK_GREEN = 6;
+
+ /**
+ * default color yellow (value is 7)
+ */
+ public static final int COLOR_YELLOW = 7;
+
+ /**
+ * default color dark yello (value is 8)
+ */
+ public static final int COLOR_DARK_YELLOW = 8;
+
+ /**
+ * default color blue (value is 9)
+ */
+ public static final int COLOR_BLUE = 9;
+
+ /**
+ * default color dark blue (value is 10)
+ */
+ public static final int COLOR_DARK_BLUE = 10;
+
+ /**
+ * default color magenta (value is 11)
+ */
+ public static final int COLOR_MAGENTA = 11;
+
+ /**
+ * default color dark magenta (value is 12)
+ */
+ public static final int COLOR_DARK_MAGENTA = 12;
+
+ /**
+ * default color cyan (value is 13)
+ */
+ public static final int COLOR_CYAN = 13;
+
+ /**
+ * default color dark cyan (value is 14)
+ */
+ public static final int COLOR_DARK_CYAN = 14;
+
+ /**
+ * default color gray (value is 15)
+ */
+ public static final int COLOR_GRAY = 15;
+
+ /**
+ * default color dark gray (value is 16)
+ */
+ public static final int COLOR_DARK_GRAY = 16;
+
+ /*
+ * System Colors
+ *
+ * Dealing with system colors is an area where there are
+ * many platform differences. On some platforms, system
+ * colors can change dynamically while the program is
+ * running. On other platforms, system colors can be
+ * changed for all instances of a particular widget.
+ * Therefore, the only truly portable method to obtain
+ * a widget color query is to query the color from an
+ * instance of the widget.
+ *
+ * It is expected that the list of supported colors
+ * will grow over time.
+ */
+
+ /**
+ * system color used to paint dark shadow areas (value is 17)
+ */
+ public static final int COLOR_WIDGET_DARK_SHADOW = 17;
+
+ /**
+ * system color used to paint normal shadow areas (value is 18)
+ */
+ public static final int COLOR_WIDGET_NORMAL_SHADOW = 18;
+
+ /**
+ * system color used to paint light shadow areas (value is 19)
+ */
+ public static final int COLOR_WIDGET_LIGHT_SHADOW = 19;
+
+ /**
+ * system color used to paint highlight shadow areas (value is 20)
+ */
+ public static final int COLOR_WIDGET_HIGHLIGHT_SHADOW = 20;
+
+ /**
+ * system color used to paint foreground areas (value is 21)
+ */
+ public static final int COLOR_WIDGET_FOREGROUND = 21;
+
+ /**
+ * system color used to paint background areas (value is 22)
+ */
+ public static final int COLOR_WIDGET_BACKGROUND = 22;
+
+ /**
+ * system color used to paint border areas (value is 23)
+ */
+ public static final int COLOR_WIDGET_BORDER = 23;
+
+ /**
+ * system color used to paint list foreground areas (value is 24)
+ */
+ public static final int COLOR_LIST_FOREGROUND = 24;
+
+ /**
+ * system color used to paint list background areas (value is 25)
+ */
+ public static final int COLOR_LIST_BACKGROUND = 25;
+
+ /**
+ * system color used to paint list selection background areas (value is 26)
+ */
+ public static final int COLOR_LIST_SELECTION = 26;
+
+ /**
+ * system color used to paint list selected text (value is 27)
+ */
+ public static final int COLOR_LIST_SELECTION_TEXT = 27;
+
+ /**
+ * system color used to paint tooltip text (value is 28)
+ */
+ public static final int COLOR_INFO_FOREGROUND = 28;
+
+ /**
+ * system color used to paint tooltip background areas (value is 29)
+ */
+ public static final int COLOR_INFO_BACKGROUND = 29;
+
+ /**
+ * system color used to paint title text (value is 30)
+ */
+ public static final int COLOR_TITLE_FOREGROUND = 30;
+
+ /**
+ * system color used to paint title background areas (value is 31)
+ */
+ public static final int COLOR_TITLE_BACKGROUND = 31;
+
+ /**
+ * system color used to paint title background gradient (value is 32)
+ */
+ public static final int COLOR_TITLE_BACKGROUND_GRADIENT = 32;
+
+ /**
+ * system color used to paint inactive title text (value is 33)
+ */
+ public static final int COLOR_TITLE_INACTIVE_FOREGROUND = 33;
+
+ /**
+ * system color used to paint inactive title background areas (value is 34)
+ */
+ public static final int COLOR_TITLE_INACTIVE_BACKGROUND = 34;
+
+ /**
+ * system color used to paint inactive title background gradient (value is 35)
+ */
+ public static final int COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT = 35;
+
+ /**
+ * SWT error constant indicating that no error number was specified
+ * (value is 1)
+ */
+ public static final int ERROR_UNSPECIFIED = 1;
+
+ /**
+ * SWT error constant indicating that no more handles for an
+ * operating system resource are available
+ * (value is 2)
+ */
+ public static final int ERROR_NO_HANDLES = 2;
+
+ /**
+ * SWT error constant indicating that no more callback resources are available
+ * (value is 3)
+ */
+ public static final int ERROR_NO_MORE_CALLBACKS = 3;
+
+ /**
+ * SWT error constant indicating that a null argument was passed in
+ * (value is 4)
+ */
+ public static final int ERROR_NULL_ARGUMENT = 4;
+
+ /**
+ * SWT error constant indicating that an invalid argument was passed in
+ * (value is 5)
+ */
+ public static final int ERROR_INVALID_ARGUMENT = 5;
+
+ /**
+ * SWT error constant indicating that a value was found to be
+ * outside the allowable range
+ * (value is 6)
+ */
+ public static final int ERROR_INVALID_RANGE = 6;
+
+ /**
+ * SWT error constant indicating that a value which can not be
+ * zero was found to be
+ * (value is 7)
+ */
+ public static final int ERROR_CANNOT_BE_ZERO = 7;
+
+ /**
+ * SWT error constant indicating that the underlying operating
+ * system was unable to provide the value of an item
+ * (value is 8)
+ */
+ public static final int ERROR_CANNOT_GET_ITEM = 8;
+
+ /**
+ * SWT error constant indicating that the underlying operating
+ * system was unable to provide the selection
+ * (value is 9)
+ */
+ public static final int ERROR_CANNOT_GET_SELECTION = 9;
+
+ /**
+ * SWT error constant indicating that the underlying operating
+ * system was unable to provide the height of an item
+ * (value is 11)
+ */
+ public static final int ERROR_CANNOT_GET_ITEM_HEIGHT = 11;
+
+ /**
+ * SWT error constant indicating that the underlying operating
+ * system was unable to provide the text of a widget
+ * (value is 12)
+ */
+ public static final int ERROR_CANNOT_GET_TEXT = 12;
+
+ /**
+ * SWT error constant indicating that the underlying operating
+ * system was unable to set the text of a widget
+ * (value is 13)
+ */
+ public static final int ERROR_CANNOT_SET_TEXT = 13;
+
+ /**
+ * SWT error constant indicating that the underlying operating
+ * system was unable to add an item
+ * (value is 14)
+ */
+ public static final int ERROR_ITEM_NOT_ADDED = 14;
+
+ /**
+ * SWT error constant indicating that the underlying operating
+ * system was unable to remove an item
+ * (value is 15)
+ */
+ public static final int ERROR_ITEM_NOT_REMOVED = 15;
+
+ /**
+ * SWT error constant indicating that a particular feature has
+ * not been implemented on this platform
+ * (value is 20)
+ */
+ public static final int ERROR_NOT_IMPLEMENTED = 20;
+
+ /**
+ * SWT error constant indicating that a menu which needed
+ * to have the drop down style had some other style instead
+ * (value is 21)
+ */
+ public static final int ERROR_MENU_NOT_DROP_DOWN = 21;
+
+ /**
+ * SWT error constant indicating that an attempt was made to
+ * invoke an SWT operation which can only be executed by the
+ * user-interface thread from some other thread
+ * (value is 22)
+ */
+ public static final int ERROR_THREAD_INVALID_ACCESS = 22;
+
+ /**
+ * SWT error constant indicating that an attempt was made to
+ * invoke an SWT operation using a widget which had already
+ * been disposed.
+ * (value is 24)
+ */
+ public static final int ERROR_WIDGET_DISPOSED = 24;
+
+ /**
+ * SWT error constant indicating that a menu item which needed
+ * to have the cascade style had some other style instead
+ * (value is 27)
+ */
+ public static final int ERROR_MENUITEM_NOT_CASCADE = 27;
+
+ /**
+ * SWT error constant indicating that the underlying operating
+ * system was unable to set the selection of a widget
+ * (value is 28)
+ */
+ public static final int ERROR_CANNOT_SET_SELECTION = 28;
+
+ /**
+ * SWT error constant indicating that the underlying operating
+ * system was unable to set the menu
+ * (value is 29)
+ */
+ public static final int ERROR_CANNOT_SET_MENU = 29;
+
+ /**
+ * SWT error constant indicating that the underlying operating
+ * system was unable to set the enabled state
+ * (value is 30)
+ */
+ public static final int ERROR_CANNOT_SET_ENABLED = 30;
+
+ /**
+ * SWT error constant indicating that the underlying operating
+ * system was unable to provide enabled/disabled state information
+ * (value is 31)
+ */
+ public static final int ERROR_CANNOT_GET_ENABLED = 31;
+
+ /**
+ * SWT error constant indicating that a provided widget can
+ * not be used as a parent in the current operation
+ * (value is 32)
+ */
+ public static final int ERROR_INVALID_PARENT = 32;
+
+ /**
+ * SWT error constant indicating that a menu which needed
+ * to have the menu bar style had some other style instead
+ * (value is 33)
+ */
+ public static final int ERROR_MENU_NOT_BAR = 33;
+
+ /**
+ * SWT error constant indicating that the underlying operating
+ * system was unable to provide count information
+ * (value is 36)
+ */
+ public static final int ERROR_CANNOT_GET_COUNT = 36;
+
+ /**
+ * SWT error constant indicating that a menu which needed
+ * to have the pop up menu style had some other style instead
+ * (value is 37)
+ */
+ public static final int ERROR_MENU_NOT_POP_UP = 37;
+
+ /**
+ * SWT error constant indicating that a graphics operation
+ * was attempted with an image of an unsupported depth
+ * (value is 38)
+ */
+ public static final int ERROR_UNSUPPORTED_DEPTH = 38;
+
+ /**
+ * SWT error constant indicating that an input/output operation
+ * failed during the execution of an SWT operation
+ * (value is 39)
+ */
+ public static final int ERROR_IO = 39;
+
+ /**
+ * SWT error constant indicating that a graphics operation
+ * was attempted with an image having an invalid format
+ * (value is 40)
+ */
+ public static final int ERROR_INVALID_IMAGE = 40;
+
+ /**
+ * SWT error constant indicating that a graphics operation
+ * was attempted with an image having a valid but unsupported
+ * format
+ * (value is 42)
+ */
+ public static final int ERROR_UNSUPPORTED_FORMAT = 42;
+
+ /**
+ * SWT error constant indicating that an attempt was made
+ * to subclass an SWT widget class without implementing the
+ * <code>checkSubclass()</code> method. For additional
+ * information see the comment in <code>Widget.checkSubclass()</code>
+ * (value is 43)
+ *
+ * @see Widget#checkSubclass
+ */
+ public static final int ERROR_INVALID_SUBCLASS = 43;
+
+ /**
+ * SWT error constant indicating that an attempt was made to
+ * invoke an SWT operation using a graphics object which had
+ * already been disposed.
+ * (value is 44)
+ */
+ public static final int ERROR_GRAPHIC_DISPOSED = 44;
+
+ /**
+ * SWT error constant indicating that an attempt was made to
+ * invoke an SWT operation using a device which had already
+ * been disposed.
+ * (value is 45)
+ */
+ public static final int ERROR_DEVICE_DISPOSED = 45;
+
+ /**
+ * traversal event detail field value indicating that the ESC
+ * key was pressed (value is 1<<1)
+ */
+ public static final int TRAVERSE_ESCAPE = 1 << 1;
+
+ /**
+ * traversal event detail field value indicating that the ENTER
+ * key was pressed (value is 1<<2)
+ */
+ public static final int TRAVERSE_RETURN = 1 << 2;
+
+ /**
+ * traversal event detail field value indicating that the SHIFT-TAB
+ * key was pressed (value is 1<<3)
+ */
+ public static final int TRAVERSE_TAB_PREVIOUS = 1 << 3;
+
+ /**
+ * traversal event detail field value indicating that the TAB
+ * key was pressed (value is 1<<4)
+ */
+ public static final int TRAVERSE_TAB_NEXT = 1 << 4;
+
+ /**
+ * traversal event detail field value indicating that the LEFT-ARROW
+ * or UP-ARROW keys was pressed (value is 1<<5)
+ */
+ public static final int TRAVERSE_ARROW_PREVIOUS = 1 << 5;
+
+ /**
+ * traversal event detail field value indicating that the RIGHT-ARROW
+ * or DOWN-ARROW keys was pressed (value is 1<<6)
+ */
+ public static final int TRAVERSE_ARROW_NEXT = 1 << 6;
+
+ /**
+ * constant indicating that an image or operation is of type bitmap (value is 0)
+ */
+ public static final int BITMAP = 0;
+
+ /**
+ * constant indicating that an image or operation is of type icon (value is 1)
+ */
+ public static final int ICON = 1;
+
+ /**
+ * <code>Image</code> constructor argument indicating that
+ * the new image should be a copy of the image provided as
+ * an argument (value is 0)
+ */
+ public static final int IMAGE_COPY = 0;
+
+ /**
+ * <code>Image</code> constructor argument indicating that
+ * the new image should have the appearance of a "disabled"
+ * (using the platform's rules for how this should look)
+ * copy of the image provided as an argument (value is 1)
+ */
+ public static final int IMAGE_DISABLE = 1;
+
+ /**
+ * <code>Image</code> constructor argument indicating that
+ * the new image should have the appearance of a "gray scaled"
+ * copy of the image provided as an argument (value is 2)
+ */
+ public static final int IMAGE_GRAY = 2;
+
+ /**
+ * font style constant indicating a normal weight, non-italic font
+ * (value is 0)
+ */
+ public static final int NORMAL = 0;
+
+ /**
+ * font style constant indicating a bold weight font
+ * (value is 1<<0)
+ */
+ public static final int BOLD = 1 << 0;
+
+ /**
+ * font style constant indicating an italic font
+ * (value is 1<<1)
+ */
+ public static final int ITALIC = 1 << 1;
+
+ /**
+ * system arrow cursor (value is 0)
+ */
+ public static final int CURSOR_ARROW = 0;
+
+ /**
+ * system wait cursor (value is 1)
+ */
+ public static final int CURSOR_WAIT = 1;
+
+ /**
+ * system cross hair cursor (value is 2)
+ */
+ public static final int CURSOR_CROSS = 2;
+
+ /**
+ * system app startup cursor (value is 3)
+ */
+ public static final int CURSOR_APPSTARTING = 3;
+
+ /**
+ * system help cursor (value is 4)
+ */
+ public static final int CURSOR_HELP = 4;
+
+ /**
+ * system resize all directions cursor (value is 5)
+ */
+ public static final int CURSOR_SIZEALL = 5;
+
+ /**
+ * system resize north-east-south-west cursor (value is 6)
+ */
+ public static final int CURSOR_SIZENESW = 6;
+
+ /**
+ * system resize north-south cursor (value is 7)
+ */
+ public static final int CURSOR_SIZENS = 7;
+
+ /**
+ * system resize north-west-south-east cursor (value is 8)
+ */
+ public static final int CURSOR_SIZENWSE = 8;
+
+ /**
+ * system resize west-east cursor (value is 9)
+ */
+ public static final int CURSOR_SIZEWE = 9;
+
+ /**
+ * system resize north cursor (value is 10)
+ */
+ public static final int CURSOR_SIZEN = 10;
+
+ /**
+ * system resize south cursor (value is 11)
+ */
+ public static final int CURSOR_SIZES = 11;
+
+ /**
+ * system resize east cursor (value is 12)
+ */
+ public static final int CURSOR_SIZEE = 12;
+
+ /**
+ * system resize west cursor (value is 13)
+ */
+ public static final int CURSOR_SIZEW = 13;
+
+ /**
+ * system resize north-east cursor (value is 14)
+ */
+ public static final int CURSOR_SIZENE = 14;
+
+ /**
+ * system resize south-east cursor (value is 15)
+ */
+ public static final int CURSOR_SIZESE = 15;
+
+ /**
+ * system resize south-west cursor (value is 16)
+ */
+ public static final int CURSOR_SIZESW = 16;
+
+ /**
+ * system resize north-west cursor (value is 17)
+ */
+ public static final int CURSOR_SIZENW = 17;
+
+ /**
+ * system up arrow cursor (value is 18)
+ */
+ public static final int CURSOR_UPARROW = 18;
+
+ /**
+ * system i-beam cursor (value is 19)
+ */
+ public static final int CURSOR_IBEAM = 19;
+
+ /**
+ * system "not allowed" cursor (value is 20)
+ */
+ public static final int CURSOR_NO = 20;
+
+ /**
+ * system hand cursor (value is 21)
+ */
+ public static final int CURSOR_HAND = 21;
+
+ /**
+ * line drawing style for solid lines (value is 1)
+ */
+ public static final int LINE_SOLID = 1;
+
+ /**
+ * line drawing style for dashed lines (value is 2)
+ */
+ public static final int LINE_DASH = 2;
+
+ /**
+ * line drawing style for dotted lines (value is 3)
+ */
+ public static final int LINE_DOT = 3;
+
+ /**
+ * line drawing style for alternating dash-dot lines (value is 4)
+ */
+ public static final int LINE_DASHDOT = 4;
+
+ /**
+ * line drawing style for dash-dot-dot lines (value is 5)
+ */
+ public static final int LINE_DASHDOTDOT = 5;
+
+ /**
+ * image format constant indicating an unknown image type (value is -1)
+ */
+ public static final int IMAGE_UNDEFINED = -1;
+
+ /**
+ * image format constant indicating a Windows BMP format image (value is 0)
+ */
+ public static final int IMAGE_BMP = 0;
+
+ /**
+ * image format constant indicating a run-length encoded
+ * Windows BMP format image (value is 1)
+ */
+ public static final int IMAGE_BMP_RLE = 1;
+
+ /**
+ * image format constant indicating a GIF format image (value is 2)
+ */
+ public static final int IMAGE_GIF = 2;
+
+ /**
+ * image format constant indicating a ICO format image (value is 3)
+ */
+ public static final int IMAGE_ICO = 3;
+
+ /**
+ * image format constant indicating a JPEG format image (value is 4)
+ */
+ public static final int IMAGE_JPEG = 4;
+
+ /**
+ * image format constant indicating a PNG format image (value is 5)
+ */
+ public static final int IMAGE_PNG = 5;
+
+ /**
+ * GIF image disposal method constants indicating that the
+ * disposal method is unspecified (value is 0)
+ */
+ public static final int DM_UNSPECIFIED = 0x0;
+
+ /**
+ * GIF image disposal method constants indicating that the
+ * disposal method is to do nothing. That is, to leave the
+ * previous image in place (value is 1)
+ */
+ public static final int DM_FILL_NONE = 0x1;
+
+ /**
+ * GIF image disposal method constants indicating that the
+ * the previous images should be covered with the background
+ * color before displaying the next image (value is 2)
+ */
+ public static final int DM_FILL_BACKGROUND = 0x2;
+
+ /**
+ * GIF image disposal method constants indicating that the
+ * disposal method is to restore the previous picture
+ * (value is 3)
+ */
+ public static final int DM_FILL_PREVIOUS = 0x3;
+
+ /**
+ * image transparency constant indicating that the image
+ * contains no transparency information (value is 0)
+ */
+ public static final int TRANSPARENCY_NONE = 0x0;
+
+ /**
+ * image transparency constant indicating that the image
+ * contains no transparency information (value is 1<<0)
+ */
+ public static final int TRANSPARENCY_ALPHA = 1 << 0;
+
+ /**
+ * image transparency constant indicating that the image
+ * contains no transparency information (value is 1<<1)
+ */
+ public static final int TRANSPARENCY_MASK = 1 << 1;
+
+ /**
+ * image transparency constant indicating that the image
+ * contains no transparency information (value is 1<<2)
+ */
+ public static final int TRANSPARENCY_PIXEL = 1 << 2;
+
+/**
+ * Answers a concise, human readable description of the error code.
+ *
+ * @param code the SWT error code.
+ * @return a description of the error code.
+ *
+ * @see SWT
+ */
+static String findErrorText (int code) {
+ switch (code) {
+ case ERROR_UNSPECIFIED: return "Unspecified error";
+ case ERROR_NO_HANDLES: return "No more handles";
+ case ERROR_NO_MORE_CALLBACKS: return "No more callbacks";
+ case ERROR_NULL_ARGUMENT: return "Argument cannot be null";
+ case ERROR_INVALID_ARGUMENT: return "Argument not valid";
+ case ERROR_INVALID_RANGE: return "Index out of bounds";
+ case ERROR_CANNOT_BE_ZERO: return "Argument cannot be zero";
+ case ERROR_CANNOT_GET_ITEM: return "Cannot get item";
+ case ERROR_CANNOT_GET_SELECTION: return "Cannot get selection";
+ case ERROR_CANNOT_GET_ITEM_HEIGHT: return "Cannot get item height";
+ case ERROR_CANNOT_GET_TEXT: return "Cannot get text";
+ case ERROR_CANNOT_SET_TEXT: return "Cannot set text";
+ case ERROR_ITEM_NOT_ADDED: return "Item not added";
+ case ERROR_ITEM_NOT_REMOVED: return "Item not removed";
+ case ERROR_NOT_IMPLEMENTED: return "Not implemented";
+ case ERROR_MENU_NOT_DROP_DOWN: return "Menu must be a drop down";
+ case ERROR_THREAD_INVALID_ACCESS: return "Invalid thread access";
+ case ERROR_WIDGET_DISPOSED: return "Widget is disposed";
+ case ERROR_MENUITEM_NOT_CASCADE: return "Menu item is not a CASCADE";
+ case ERROR_CANNOT_SET_SELECTION: return "Cannot set selection";
+ case ERROR_CANNOT_SET_MENU: return "Cannot set menu";
+ case ERROR_CANNOT_SET_ENABLED: return "Cannot set the enabled state";
+ case ERROR_CANNOT_GET_ENABLED: return "Cannot get the enabled state";
+ case ERROR_INVALID_PARENT: return "Widget has the wrong parent";
+ case ERROR_MENU_NOT_BAR: return "Menu is not a BAR";
+ case ERROR_CANNOT_GET_COUNT: return "Cannot get count";
+ case ERROR_MENU_NOT_POP_UP: return "Menu is not a POP_UP";
+ case ERROR_UNSUPPORTED_DEPTH: return "Unsupported color depth";
+ case ERROR_IO: return "i/o error";
+ case ERROR_INVALID_IMAGE: return "Invalid image";
+ case ERROR_UNSUPPORTED_FORMAT: return "Unsupported or unrecognized format";
+ case ERROR_INVALID_SUBCLASS: return "Subclassing not allowed";
+ case ERROR_GRAPHIC_DISPOSED: return "Graphic is disposed";
+ case ERROR_DEVICE_DISPOSED: return "Device is disposed";
+ }
+ return "Unknown error";
+}
+
+/**
+ * Answers the SWT platform name.
+ * Examples: "win32", "motif", "gtk", "photon"
+ *
+ * @return the SWT version number
+ */
+public static String getPlatform () {
+ return Callback.getPlatform ();
+}
+
+/**
+ * Answers the SWT version number as an integer.
+ * Example: "SWT051" == 51
+ *
+ * @return the SWT version number
+ */
+public static int getVersion () {
+ return Callback.getVersion ();
+}
+
+/**
+ * Throws an appropriate exception based on the passed in error code.
+ *
+ * @param code the SWT error code
+ */
+public static void error (int code) {
+ error (code, null);
+}
+
+/**
+ * Throws an appropriate exception based on the passed in error code.
+ * The <code>throwable</code> argument should be either null, or the
+ * throwable which caused SWT to throw an exception.
+ * <p>
+ * In SWT, errors are reported by throwing one of three exceptions:
+ * <dl>
+ * <dd>java.lang.IllegalArgumentException</dd>
+ * <dt>thrown whenever one of the API methods is invoked with an illegal argument</dt>
+ * <dd>org.eclipse.swt.SWTException (extends java.lang.RuntimeException)</dd>
+ * <dt>thrown whenever a recoverable error happens internally in SWT</dt>
+ * <dd>org.eclipse.swt.SWTError (extends java.lang.Error)</dd>
+ * <dt>thrown whenever a <b>non-recoverable</b> error happens internally in SWT</dt>
+ * </dl>
+ * This method provides the logic which maps between error codes
+ * and one of the above exceptions.
+ * </p>
+ *
+ * @param code the SWT error code.
+ * @param throwable the exception which caused the error to occur.
+ *
+ * @see SWTError
+ * @see SWTException
+ * @see IllegalArgumentException
+ */
+public static void error (int code, Throwable throwable) {
+
+ // This code prevents the creation of "chains" of SWTErrors and
+ // SWTExceptions which in turn contain other SWTErrors and
+ // SWTExceptions as their throwable. This can occur when low level
+ // code throws an exception past a point where a higher layer is
+ // being "safe" and catching all exceptions. (Note that, this is
+ // _a_bad_thing_ which we always try to avoid.)
+ //
+ // On the theory that the low level code is closest to the
+ // original problem, we simply re-throw the original exception here.
+ if (throwable instanceof SWTError) throw (SWTError) throwable;
+ if (throwable instanceof SWTException) throw (SWTException) throwable;
+
+ switch (code) {
+
+ // Illegal Arguments (non-fatal)
+ case ERROR_NULL_ARGUMENT:
+ case ERROR_CANNOT_BE_ZERO:
+ case ERROR_INVALID_ARGUMENT:
+ case ERROR_MENU_NOT_BAR:
+ case ERROR_MENU_NOT_DROP_DOWN:
+ case ERROR_MENU_NOT_POP_UP:
+ case ERROR_MENUITEM_NOT_CASCADE:
+ case ERROR_INVALID_PARENT:
+ case ERROR_INVALID_RANGE: {
+ throw new IllegalArgumentException (findErrorText (code));
+ }
+
+ // SWT Errors (non-fatal)
+ case ERROR_INVALID_SUBCLASS:
+ case ERROR_THREAD_INVALID_ACCESS:
+ case ERROR_WIDGET_DISPOSED:
+ case ERROR_GRAPHIC_DISPOSED:
+ case ERROR_DEVICE_DISPOSED:
+ case ERROR_INVALID_IMAGE:
+ case ERROR_UNSUPPORTED_DEPTH:
+ case ERROR_UNSUPPORTED_FORMAT:
+ case ERROR_IO: {
+ SWTException exception = new SWTException (code);
+ exception.throwable = throwable;
+ throw exception;
+ }
+
+ // OS Failure/Limit (fatal, may occur only on some platforms)
+ case ERROR_CANNOT_GET_COUNT:
+ case ERROR_CANNOT_GET_ENABLED:
+ case ERROR_CANNOT_GET_ITEM:
+ case ERROR_CANNOT_GET_ITEM_HEIGHT:
+ case ERROR_CANNOT_GET_SELECTION:
+ case ERROR_CANNOT_GET_TEXT:
+ case ERROR_CANNOT_SET_ENABLED:
+ case ERROR_CANNOT_SET_MENU:
+ case ERROR_CANNOT_SET_SELECTION:
+ case ERROR_CANNOT_SET_TEXT:
+ case ERROR_ITEM_NOT_ADDED:
+ case ERROR_ITEM_NOT_REMOVED:
+ case ERROR_NO_HANDLES: // fall through
+
+ // SWT Failure/Limit (fatal, may occur only on some platforms)
+ case ERROR_NO_MORE_CALLBACKS:
+ case ERROR_NOT_IMPLEMENTED:
+ case ERROR_UNSPECIFIED: {
+ SWTError error = new SWTError (code);
+ error.throwable = throwable;
+ throw error;
+ }
+ }
+
+ // Unknown/Undefined Error
+ SWTError error = new SWTError (code);
+ error.throwable = throwable;
+ throw error;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/SWTError.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/SWTError.java
new file mode 100755
index 0000000000..5dd494f2db
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/SWTError.java
@@ -0,0 +1,80 @@
+package org.eclipse.swt;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+/**
+ * This error is thrown whenever an unrecoverable error
+ * occurs internally in SWT. The message text and error code
+ * provide a further description of the problem. The exception
+ * has a <code>throwable</code> field which holds the underlying
+ * throwable that caused the problem (if this information is
+ * available (i.e. it may be null)).
+ * <p>
+ * SWTErrors are thrown when something fails internally which
+ * either leaves SWT in an unknown state (eg. the o/s call to
+ * remove an item from a list returns an error code) or when SWT
+ * is left in a known-to-be-unrecoverable state (eg. it runs out
+ * of callback resources). SWTErrors should not occur in typical
+ * programs, although "high reliability" applications should
+ * still catch them.
+ * </p><p>
+ * This class also provides support methods used by SWT to match
+ * error codes to the appropriate exception class (SWTError,
+ * SWTException, or IllegalArgumentException) and to provide
+ * human readable strings for SWT error codes.
+ * </p>
+ *
+ * @see SWTException
+ * @see SWT#error
+ */
+
+public class SWTError extends Error {
+ public int code;
+ public Throwable throwable;
+
+/**
+ * Constructs a new instance of this class with its
+ * walkback filled in. The error code is set to an
+ * unspecified value.
+ */
+public SWTError () {
+ this (SWT.ERROR_UNSPECIFIED);
+}
+
+/**
+ * Constructs a new instance of this class with its
+ * walkback and message filled in. The error code is
+ * set to an unspecified value.
+ *
+ * @param message the detail message for the exception
+ */
+public SWTError (String message) {
+ this (SWT.ERROR_UNSPECIFIED, message);
+}
+
+/**
+ * Constructs a new instance of this class with its
+ * walkback and error code filled in.
+ *
+ * @param code the SWT error code
+ */
+public SWTError (int code) {
+ this (code, SWT.findErrorText (code));
+}
+
+/**
+ * Constructs a new instance of this class with its
+ * walkback, error code and message filled in.
+ *
+ * @param code the SWT error code
+ * @param message the detail message for the exception
+ */
+public SWTError (int code, String message) {
+ super (message);
+ this.code = code;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/SWTException.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/SWTException.java
new file mode 100755
index 0000000000..7f04b7c9fd
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/SWTException.java
@@ -0,0 +1,73 @@
+package org.eclipse.swt;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+/**
+ * This runtime exception is thrown whenever a recoverable error
+ * occurs internally in SWT. The message text and error code
+ * provide a further description of the problem. The exception
+ * has a <code>throwable</code> field which holds the underlying
+ * exception that caused the problem (if this information is
+ * available (i.e. it may be null)).
+ * <p>
+ * SWTExceptions are thrown when something fails internally,
+ * but SWT is left in a known stable state (eg. a widget call
+ * was made from a non-u/i thread, or there is failure while
+ * reading an Image because the source file was corrupt).
+ * </p>
+ *
+ * @see SWTError
+ */
+
+public class SWTException extends RuntimeException {
+ public int code;
+ public Throwable throwable;
+
+/**
+ * Constructs a new instance of this class with its
+ * walkback filled in. The error code is set to an
+ * unspecified value.
+ */
+public SWTException () {
+ this (SWT.ERROR_UNSPECIFIED);
+}
+
+/**
+ * Constructs a new instance of this class with its
+ * walkback and message filled in. The error code is
+ * set to an unspecified value.
+ *
+ * @param message the detail message for the exception
+ */
+public SWTException (String message) {
+ this (SWT.ERROR_UNSPECIFIED, message);
+}
+
+/**
+ * Constructs a new instance of this class with its
+ * walkback and error code filled in.
+ *
+ * @param code the SWT error code
+ */
+public SWTException (int code) {
+ this (code, SWT.findErrorText (code));
+}
+
+/**
+ * Constructs a new instance of this class with its
+ * walkback, error code and message filled in.
+ *
+ * @param code the SWT error code
+ * @param message the detail message for the exception
+ */
+public SWTException (int code, String message) {
+ super (message);
+ this.code = code;
+}
+
+}
+
+
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ArmEvent.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ArmEvent.java
new file mode 100755
index 0000000000..339b4de0c2
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ArmEvent.java
@@ -0,0 +1,29 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * Instances of this class are sent as a result of
+ * a widget such as a menu item being armed.
+ *
+ * @see ArmListener
+ */
+
+public final class ArmEvent extends TypedEvent {
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public ArmEvent(Event e) {
+ super(e);
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ArmListener.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ArmListener.java
new file mode 100755
index 0000000000..44dda803cc
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ArmListener.java
@@ -0,0 +1,32 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import java.util.EventListener;
+
+/**
+ * Classes which implement this interface provide a method
+ * that deals with the event that is generated when a widget,
+ * such as a menu item, is armed.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to a widget using the
+ * <code>addArmListener</code> method and removed using
+ * the <code>removeArmListener</code> method. When the
+ * widget is armed, the widgetArmed method will be invoked.
+ * </p>
+ *
+ * @see ArmEvent
+ */
+public interface ArmListener extends EventListener {
+
+/**
+ * Sent when a widget is armed, or 'about to be selected'.
+ *
+ * @param e an event containing information about the arm
+ */
+public void widgetArmed(ArmEvent e);
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ControlAdapter.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ControlAdapter.java
new file mode 100755
index 0000000000..231baa31fb
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ControlAdapter.java
@@ -0,0 +1,40 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the <code>ControlListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>ControlEvent</code>s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ * </p>
+ *
+ * @see ControlListener
+ * @see ControlEvent
+ */
+public abstract class ControlAdapter implements ControlListener {
+
+/**
+ * Sent when the location (x, y) of a control changes relative
+ * to its parent (or relative to the display, for <code>Shell</code>s).
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the move
+ */
+public void controlMoved(ControlEvent e) {
+}
+
+/**
+ * Sent when the size (width, height) of a control changes.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the resize
+ */
+public void controlResized(ControlEvent e) {
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ControlEvent.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ControlEvent.java
new file mode 100755
index 0000000000..22af9a8e0f
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ControlEvent.java
@@ -0,0 +1,31 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * Instances of this class are sent as a result of
+ * controls being moved or resized.
+ *
+ * @see ControlListener
+ */
+
+public final class ControlEvent extends TypedEvent {
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public ControlEvent(Event e) {
+ super(e);
+}
+
+}
+
+
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ControlListener.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ControlListener.java
new file mode 100755
index 0000000000..63ca027961
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ControlListener.java
@@ -0,0 +1,42 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import java.util.EventListener;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the events that are generated by moving
+ * and resizing controls.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to a control using the
+ * <code>addControlListener</code> method and removed using
+ * the <code>removeControlListener</code> method. When a
+ * control is moved or resized, the appropriate method will
+ * be invoked.
+ * </p>
+ *
+ * @see ControlAdapter
+ * @see ControlEvent
+ */
+public interface ControlListener extends EventListener {
+
+/**
+ * Sent when the location (x, y) of a control changes relative
+ * to its parent (or relative to the display, for <code>Shell</code>s).
+ *
+ * @param e an event containing information about the move
+ */
+public void controlMoved(ControlEvent e);
+
+/**
+ * Sent when the size (width, height) of a control changes.
+ *
+ * @param e an event containing information about the resize
+ */
+public void controlResized(ControlEvent e);
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/DisposeEvent.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/DisposeEvent.java
new file mode 100755
index 0000000000..2bcac89d4e
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/DisposeEvent.java
@@ -0,0 +1,30 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * Instances of this class are sent as a result of
+ * widgets being disposed.
+ *
+ * @see DisposeListener
+ */
+
+public final class DisposeEvent extends TypedEvent {
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public DisposeEvent(Event e) {
+ super(e);
+}
+
+}
+
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/DisposeListener.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/DisposeListener.java
new file mode 100755
index 0000000000..586a3f467f
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/DisposeListener.java
@@ -0,0 +1,33 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import java.util.EventListener;
+
+/**
+ * Classes which implement this interface provide a method
+ * that deals with the event that is generated when a widget
+ * is disposed.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to a widget using the
+ * <code>addDisposeListener</code> method and removed using
+ * the <code>removeDisposeListener</code> method. When a
+ * widget is disposed, the widgetDisposed method will
+ * be invoked.
+ * </p>
+ *
+ * @see DisposeEvent
+ */
+public interface DisposeListener extends EventListener {
+
+/**
+ * Sent when the widget is disposed.
+ *
+ * @param e an event containing information about the dispose
+ */
+public void widgetDisposed(DisposeEvent e);
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/FocusAdapter.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/FocusAdapter.java
new file mode 100755
index 0000000000..d3e04295ec
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/FocusAdapter.java
@@ -0,0 +1,39 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the <code>FocusListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>FocusEvent</code>s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ * </p>
+ *
+ * @see FocusListener
+ * @see FocusEvent
+ */
+public abstract class FocusAdapter implements FocusListener {
+
+/**
+ * Sent when a control gets focus.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the focus change
+ */
+public void focusGained(FocusEvent e) {
+}
+
+/**
+ * Sent when a control loses focus.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the focus change
+ */
+public void focusLost(FocusEvent e) {
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/FocusEvent.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/FocusEvent.java
new file mode 100755
index 0000000000..997d6d81fa
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/FocusEvent.java
@@ -0,0 +1,30 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * Instances of this class are sent as a result of
+ * widgets gaining and losing focus.
+ *
+ * @see FocusListener
+ */
+
+public final class FocusEvent extends TypedEvent {
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public FocusEvent(Event e) {
+ super(e);
+}
+
+}
+
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/FocusListener.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/FocusListener.java
new file mode 100755
index 0000000000..d0c16d1244
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/FocusListener.java
@@ -0,0 +1,42 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import java.util.EventListener;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the events that are generated as controls
+ * gain and lose focus.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to a control using the
+ * <code>addFocusListener</code> method and removed using
+ * the <code>removeFocusListener</code> method. When a
+ * control gains or loses focus, the appropriate method
+ * will be invoked.
+ * </p>
+ *
+ * @see FocusAdapter
+ * @see FocusEvent
+ */
+public interface FocusListener extends EventListener {
+
+/**
+ * Sent when a control gets focus.
+ *
+ * @param e an event containing information about the focus change
+ */
+public void focusGained(FocusEvent e);
+
+/**
+ * Sent when a control loses focus.
+ *
+ * @param e an event containing information about the focus change
+ */
+public void focusLost(FocusEvent e);
+}
+
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/HelpEvent.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/HelpEvent.java
new file mode 100755
index 0000000000..d8a1666022
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/HelpEvent.java
@@ -0,0 +1,30 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * Instances of this class are sent as a result of
+ * help being requested for a widget.
+ *
+ * @see HelpListener
+ */
+
+public final class HelpEvent extends TypedEvent {
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public HelpEvent(Event e) {
+ super(e);
+}
+
+}
+
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/HelpListener.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/HelpListener.java
new file mode 100755
index 0000000000..bfd2c6587f
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/HelpListener.java
@@ -0,0 +1,34 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import java.util.EventListener;
+
+/**
+ * Classes which implement this interface provide a method
+ * that deals with the event that is generated when help is
+ * requested for a control, typically when the user presses F1.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to a control using the
+ * <code>addHelpListener</code> method and removed using
+ * the <code>removeHelpListener</code> method. When help
+ * is requested for a control, the helpRequested method
+ * will be invoked.
+ * </p>
+ *
+ * @see HelpEvent
+ */
+public interface HelpListener extends EventListener {
+
+/**
+ * Sent when help is requested for a control, typically
+ * when the user presses F1.
+ *
+ * @param e an event containing information about the help
+ */
+public void helpRequested(HelpEvent e);
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/KeyAdapter.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/KeyAdapter.java
new file mode 100755
index 0000000000..fda909927f
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/KeyAdapter.java
@@ -0,0 +1,39 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the <code>KeyListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>KeyEvent</code>s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ * </p>
+ *
+ * @see KeyListener
+ * @see KeyEvent
+ */
+public abstract class KeyAdapter implements KeyListener {
+
+/**
+ * Sent when a key is pressed on the system keyboard.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the key press
+ */
+public void keyPressed(KeyEvent e) {
+}
+
+/**
+ * Sent when a key is released on the system keyboard.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the key release
+ */
+public void keyReleased(KeyEvent e) {
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/KeyEvent.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/KeyEvent.java
new file mode 100755
index 0000000000..876c9a50c4
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/KeyEvent.java
@@ -0,0 +1,48 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * Instances of this class are sent as a result of
+ * keys being pressed and released on the keyboard
+ *
+ * @see KeyListener
+ */
+
+public class KeyEvent extends TypedEvent {
+
+ /**
+ * the character represented by the key that was typed
+ */
+ public char character;
+
+ /**
+ * the key code of the key that was typed
+ */
+ public int keyCode;
+
+ /**
+ * the state of the keyboard modifier keys at the time
+ * the event was generated
+ */
+ public int stateMask;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public KeyEvent(Event e) {
+ super(e);
+ this.character = e.character;
+ this.keyCode = e.keyCode;
+ this.stateMask = e.stateMask;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/KeyListener.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/KeyListener.java
new file mode 100755
index 0000000000..84b4cd1219
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/KeyListener.java
@@ -0,0 +1,41 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import java.util.EventListener;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the events that are generated as keys
+ * are pressed on the system keyboard.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to a control using the
+ * <code>addKeyListener</code> method and removed using
+ * the <code>removeKeyListener</code> method. When a
+ * key is pressed or released, the appropriate method will
+ * be invoked.
+ * </p>
+ *
+ * @see KeyAdapter
+ * @see KeyEvent
+ */
+public interface KeyListener extends EventListener {
+
+/**
+ * Sent when a key is pressed on the system keyboard.
+ *
+ * @param e an event containing information about the key press
+ */
+public void keyPressed(KeyEvent e);
+
+/**
+ * Sent when a key is released on the system keyboard.
+ *
+ * @param e an event containing information about the key release
+ */
+public void keyReleased(KeyEvent e);
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MenuAdapter.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MenuAdapter.java
new file mode 100755
index 0000000000..14fe8a5f32
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MenuAdapter.java
@@ -0,0 +1,39 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the <code>MenuListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>MenuEvent</code>s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ * </p>
+ *
+ * @see MenuListener
+ * @see MenuEvent
+ */
+public abstract class MenuAdapter implements MenuListener {
+
+/**
+ * Sent when a menu is hidden.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the menu operation
+ */
+public void menuHidden(MenuEvent e) {
+}
+
+/**
+ * Sent when a menu is shown.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the menu operation
+ */
+public void menuShown(MenuEvent e) {
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MenuEvent.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MenuEvent.java
new file mode 100755
index 0000000000..c0a144000f
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MenuEvent.java
@@ -0,0 +1,30 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * Instances of this class are sent as a result of
+ * menus being shown and hidden.
+ *
+ * @see MenuListener
+ */
+
+public final class MenuEvent extends TypedEvent {
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public MenuEvent(Event e) {
+ super(e);
+}
+
+}
+
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MenuListener.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MenuListener.java
new file mode 100755
index 0000000000..d88f93245d
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MenuListener.java
@@ -0,0 +1,40 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import java.util.EventListener;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the hiding and showing of menus.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to a control using the
+ * <code>addMenuListener</code> method and removed using
+ * the <code>removeMenuListener</code> method. When a
+ * menu is hidden or shown, the appropriate method will
+ * be invoked.
+ * </p>
+ *
+ * @see MenuAdapter
+ * @see MenuEvent
+ */
+public interface MenuListener extends EventListener {
+
+/**
+ * Sent when a menu is hidden.
+ *
+ * @param e an event containing information about the menu operation
+ */
+public void menuHidden(MenuEvent e);
+
+/**
+ * Sent when a menu is shown.
+ *
+ * @param e an event containing information about the menu operation
+ */
+public void menuShown(MenuEvent e);
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ModifyEvent.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ModifyEvent.java
new file mode 100755
index 0000000000..b71249856a
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ModifyEvent.java
@@ -0,0 +1,30 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * Instances of this class are sent as a result of
+ * text being modified.
+ *
+ * @see ModifyListener
+ */
+
+public final class ModifyEvent extends TypedEvent {
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public ModifyEvent(Event e) {
+ super(e);
+}
+
+}
+
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ModifyListener.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ModifyListener.java
new file mode 100755
index 0000000000..e95b010440
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ModifyListener.java
@@ -0,0 +1,32 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import java.util.EventListener;
+
+/**
+ * Classes which implement this interface provide a method
+ * that deals with the events that are generated when text
+ * is modified.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to a text widget using the
+ * <code>addModifyListener</code> method and removed using
+ * the <code>removeModifyListener</code> method. When the
+ * text is modified, the modifyText method will be invoked.
+ * </p>
+ *
+ * @see ModifyEvent
+ */
+public interface ModifyListener extends EventListener {
+
+/**
+ * Sent when the text is modified.
+ *
+ * @param e an event containing information about the modify
+ */
+public void modifyText(ModifyEvent e);
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MouseAdapter.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MouseAdapter.java
new file mode 100755
index 0000000000..3b10ac7b45
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MouseAdapter.java
@@ -0,0 +1,52 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the <code>MouseListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>MouseEvent</code>s
+ * which occur as mouse buttons are pressed and released can
+ * extend this class and override only the methods which they are
+ * interested in.
+ * </p>
+ *
+ * @see MouseListener
+ * @see MouseEvent
+ */
+public abstract class MouseAdapter implements MouseListener {
+
+/**
+ * Sent when a mouse button is pressed twice within the
+ * (operating system specified) double click period.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the mouse double click
+ *
+ * @see Display#getDoubleClickTime
+ */
+public void mouseDoubleClick(MouseEvent e) {
+}
+
+/**
+ * Sent when a mouse button is pressed.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the mouse button press
+ */
+public void mouseDown(MouseEvent e) {
+}
+
+/**
+ * Sent when a mouse button is released.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the mouse button release
+ */
+public void mouseUp(MouseEvent e) {
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MouseEvent.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MouseEvent.java
new file mode 100755
index 0000000000..eed4fbf8cc
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MouseEvent.java
@@ -0,0 +1,68 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * Instances of this class are sent whenever mouse
+ * related actions occur. This includes mouse buttons
+ * being pressed and released, the mouse pointer being
+ * moved and the mouse pointer crossing widget boundaries.
+ * <p>
+ * Note: The <code>button</code> field is an integer that
+ * represents the mouse button number. This is not the same
+ * as the <code>SWT</code> mask constants <code>BUTTONx</code>.
+ * </p>
+ *
+ * @see MouseListener
+ * @see MouseMoveListener
+ * @see MouseTrackListener
+ */
+
+public final class MouseEvent extends TypedEvent {
+
+ /**
+ * the button that was pressed or released; 1 for the
+ * first button, 2 for the second button, and 3 for the
+ * third button, etc.
+ */
+ public int button;
+
+ /**
+ * the state of the keyboard modifier keys at the time
+ * the event was generated
+ */
+ public int stateMask;
+
+ /**
+ * the widget-relative, x coordinate of the pointer
+ * at the time the mouse button was pressed or released
+ */
+ public int x;
+
+ /**
+ * the widget-relative, y coordinate of the pointer
+ * at the time the mouse button was pressed or released
+ */
+ public int y;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public MouseEvent(Event e) {
+ super(e);
+ this.x = e.x;
+ this.y = e.y;
+ this.button = e.button;
+ this.stateMask = e.stateMask;
+}
+
+}
+
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MouseListener.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MouseListener.java
new file mode 100755
index 0000000000..dc86605ff6
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MouseListener.java
@@ -0,0 +1,51 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import java.util.EventListener;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the events that are generated as mouse buttons
+ * are pressed.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to a control using the
+ * <code>addMouseListener</code> method and removed using
+ * the <code>removeMouseListener</code> method. When a
+ * mouse button is pressed or released, the appropriate method
+ * will be invoked.
+ * </p>
+ *
+ * @see MouseAdapter
+ * @see MouseEvent
+ */
+public interface MouseListener extends EventListener {
+
+/**
+ * Sent when a mouse button is pressed twice within the
+ * (operating system specified) double click period.
+ *
+ * @param e an event containing information about the mouse double click
+ *
+ * @see Display#getDoubleClickTime
+ */
+public void mouseDoubleClick(MouseEvent e);
+
+/**
+ * Sent when a mouse button is pressed.
+ *
+ * @param e an event containing information about the mouse button press
+ */
+public void mouseDown(MouseEvent e);
+
+/**
+ * Sent when a mouse button is released.
+ *
+ * @param e an event containing information about the mouse button release
+ */
+public void mouseUp(MouseEvent e);
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MouseMoveListener.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MouseMoveListener.java
new file mode 100755
index 0000000000..39a07d16f5
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MouseMoveListener.java
@@ -0,0 +1,32 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import java.util.EventListener;
+
+/**
+ * Classes which implement this interface provide a method
+ * that deals with the events that are generated as the mouse
+ * pointer moves.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to a control using the
+ * <code>addMouseMoveListener</code> method and removed using
+ * the <code>removeMouseMoveListener</code> method. As the
+ * mouse moves, the mouseMove method will be invoked.
+ * </p>
+ *
+ * @see MouseEvent
+ */
+public interface MouseMoveListener extends EventListener {
+
+/**
+ * Sent when the mouse moves.
+ *
+ * @param e an event containing information about the mouse move
+ */
+public void mouseMove(MouseEvent e);
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MouseTrackAdapter.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MouseTrackAdapter.java
new file mode 100755
index 0000000000..40e7e21888
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MouseTrackAdapter.java
@@ -0,0 +1,53 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the <code>MouseTrackListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>MouseEvent</code>s which
+ * occur as the mouse pointer passes (or hovers) over controls can
+ * extend this class and override only the methods which they are
+ * interested in.
+ * </p>
+ *
+ * @see MouseTrackListener
+ * @see MouseEvent
+ */
+public class MouseTrackAdapter implements MouseTrackListener {
+
+/**
+ * Sent when the mouse pointer passes into the area of
+ * the screen covered by a control.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the mouse enter
+ */
+public void mouseEnter(MouseEvent e) {
+}
+
+/**
+ * Sent when the mouse pointer passes out of the area of
+ * the screen covered by a control.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the mouse exit
+ */
+public void mouseExit(MouseEvent e) {
+}
+
+/**
+ * Sent when the mouse pointer hovers (that is, stops moving
+ * for an (operating system specified) period of time) over
+ * a control.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the hover
+ */
+public void mouseHover(MouseEvent e) {
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MouseTrackListener.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MouseTrackListener.java
new file mode 100755
index 0000000000..6ed12dbfbe
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/MouseTrackListener.java
@@ -0,0 +1,53 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import java.util.EventListener;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the events that are generated as the mouse
+ * pointer passes (or hovers) over controls.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to a control using the
+ * <code>addMouseTrackListener</code> method and removed using
+ * the <code>removeMouseTrackListener</code> method. When the
+ * mouse pointer passes into or out of the area of the screen
+ * covered by a control or pauses while over a control, the
+ * appropriate method will be invoked.
+ * </p>
+ *
+ * @see MouseTrackAdapter
+ * @see MouseEvent
+ */
+public interface MouseTrackListener extends EventListener {
+
+/**
+ * Sent when the mouse pointer passes into the area of
+ * the screen covered by a control.
+ *
+ * @param e an event containing information about the mouse enter
+ */
+public void mouseEnter(MouseEvent e);
+
+/**
+ * Sent when the mouse pointer passes out of the area of
+ * the screen covered by a control.
+ *
+ * @param e an event containing information about the mouse exit
+ */
+public void mouseExit(MouseEvent e);
+
+/**
+ * Sent when the mouse pointer hovers (that is, stops moving
+ * for an (operating system specified) period of time) over
+ * a control.
+ *
+ * @param e an event containing information about the hover
+ */
+public void mouseHover(MouseEvent e);
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/PaintEvent.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/PaintEvent.java
new file mode 100755
index 0000000000..2d25d9d2d2
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/PaintEvent.java
@@ -0,0 +1,76 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.graphics.GC;
+
+/**
+ * Instances of this class are sent as a result of
+ * visible areas of controls requiring re-painting.
+ *
+ * @see PaintListener
+ */
+
+public final class PaintEvent extends TypedEvent {
+
+ /**
+ * the graphics context to use when painting
+ * that is configured to use the colors, font and
+ * damaged region of the control. It is valid
+ * only during the paint and must not be disposed
+ */
+ public GC gc;
+
+ /**
+ * the x offset of the bounding rectangle of the
+ * region that requires painting
+ */
+ public int x;
+
+ /**
+ * the y offset of the bounding rectangle of the
+ * region that requires painting
+ */
+ public int y;
+
+ /**
+ * the width of the bounding rectangle of the
+ * region that requires painting
+ */
+ public int width;
+
+ /**
+ * the height of the bounding rectangle of the
+ * region that requires painting
+ */
+ public int height;
+
+ /**
+ * the number of following paint events which
+ * are pending which may always be zero on
+ * some platforms
+ */
+ public int count;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public PaintEvent(Event e) {
+ super(e);
+ this.gc = e.gc;
+ this.x = e.x;
+ this.y = e.y;
+ this.width = e.width;
+ this.height = e.height;
+ this.count = e.count;
+}
+
+}
+
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/PaintListener.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/PaintListener.java
new file mode 100755
index 0000000000..af30ca399d
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/PaintListener.java
@@ -0,0 +1,33 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import java.util.EventListener;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the events that are generated when the
+ * control needs to be painted.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to a control using the
+ * <code>addPaintListener</code> method and removed using
+ * the <code>removePaintListener</code> method. When a
+ * paint event occurs, the paintControl method will be
+ * invoked.
+ * </p>
+ *
+ * @see PaintEvent
+ */
+public interface PaintListener extends EventListener {
+
+/**
+ * Sent when a paint event occurs for the control.
+ *
+ * @param e an event containing information about the paint
+ */
+public void paintControl(PaintEvent e);
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/SelectionAdapter.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/SelectionAdapter.java
new file mode 100755
index 0000000000..7dec1624a1
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/SelectionAdapter.java
@@ -0,0 +1,39 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the <code>SelectionListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>SelectionEvent</code>s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ * </p>
+ *
+ * @see SelectionListener
+ * @see SelectionEvent
+ */
+public abstract class SelectionAdapter implements SelectionListener {
+
+/**
+ * Sent when selection occurs in the control.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the selection
+ */
+public void widgetSelected(SelectionEvent e) {
+}
+
+/**
+ * Sent when default selection occurs in the control.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the default selection
+ */
+public void widgetDefaultSelected(SelectionEvent e) {
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/SelectionEvent.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/SelectionEvent.java
new file mode 100755
index 0000000000..d86a6dbf66
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/SelectionEvent.java
@@ -0,0 +1,76 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Widget;
+
+/**
+ * Instances of this class are sent as a result of
+ * widgets being selected.
+ * <p>
+ * Note: The fields that are filled in depend on the widget.
+ * </p>
+ *
+ * @see SelectionListener
+ */
+
+public class SelectionEvent extends TypedEvent {
+
+ /**
+ * the item that was selected
+ */
+ public Widget item;
+
+ /**
+ * extra detail information about the selection
+ */
+ public int detail;
+
+ /**
+ * the x location of the selected area
+ */
+ public int x;
+
+ /**
+ * the y location of selected area
+ */
+ public int y;
+
+ /**
+ * the width of selected area
+ */
+ public int width;
+
+ /**
+ * the height of selected area
+ */
+ public int height;
+
+ /**
+ * a flag indicating whether the operation should be allowed
+ */
+ public boolean doit;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public SelectionEvent(Event e) {
+ super(e);
+ this.item = e.item;
+ this.x = e.x;
+ this.y = e.y;
+ this.width = e.width;
+ this.height = e.height;
+ this.detail = e.detail;
+ this.doit = e.doit;
+}
+
+}
+
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/SelectionListener.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/SelectionListener.java
new file mode 100755
index 0000000000..a65a2fc88b
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/SelectionListener.java
@@ -0,0 +1,50 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import java.util.EventListener;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the events that are generated when selection
+ * occurs in a control.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to a control using the
+ * <code>addSelectionListener</code> method and removed using
+ * the <code>removeSelectionListener</code> method. When
+ * selection occurs in a control the appropriate method
+ * will be invoked.
+ * </p>
+ *
+ * @see SelectionAdapter
+ * @see SelectionEvent
+ */
+public interface SelectionListener extends EventListener {
+
+/**
+ * Sent when selection occurs in the control.
+ * <p>
+ * For example, on some platforms selection occurs in
+ * a List when the user selects an item or items.
+ * </p>
+ *
+ * @param e an event containing information about the selection
+ */
+public void widgetSelected(SelectionEvent e);
+
+/**
+ * Sent when default selection occurs in the control.
+ * <p>
+ * For example, on some platforms default selection occurs
+ * in a List when the user double-clicks an item or types
+ * return in a Text.
+ * </p>
+ *
+ * @param e an event containing information about the default selection
+ */
+public void widgetDefaultSelected(SelectionEvent e);
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ShellAdapter.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ShellAdapter.java
new file mode 100755
index 0000000000..567187ff2d
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ShellAdapter.java
@@ -0,0 +1,66 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the <code>ShellListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>ShellEvent</code>s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ * </p>
+ *
+ * @see ShellListener
+ * @see ShellEvent
+ */
+public abstract class ShellAdapter implements ShellListener {
+
+/**
+ * Sent when a shell becomes the active window.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the activation
+ */
+public void shellActivated(ShellEvent e) {
+}
+
+/**
+ * Sent when a shell is closed.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the close
+ */
+public void shellClosed(ShellEvent e) {
+}
+
+/**
+ * Sent when a shell stops being the active window.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the deactivation
+ */
+public void shellDeactivated(ShellEvent e) {
+}
+
+/**
+ * Sent when a shell is un-minimized.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the un-minimization
+ */
+public void shellDeiconified(ShellEvent e) {
+}
+
+/**
+ * Sent when a shell is minimized.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the minimization
+ */
+public void shellIconified(ShellEvent e) {
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ShellEvent.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ShellEvent.java
new file mode 100755
index 0000000000..c73d2a067b
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ShellEvent.java
@@ -0,0 +1,30 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * Instances of this class are sent as a result of
+ * operations being performed on shells.
+ *
+ * @see ShellListener
+ */
+
+public final class ShellEvent extends TypedEvent {
+
+ /**
+ * a flag indicating whether the operation should be allowed
+ */
+ public boolean doit;
+
+public ShellEvent(Event e) {
+ super(e);
+ this.doit = e.doit;
+}
+
+}
+
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ShellListener.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ShellListener.java
new file mode 100755
index 0000000000..ee4f76cca6
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/ShellListener.java
@@ -0,0 +1,61 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import java.util.EventListener;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with changes in state of <code>Shell</code>s.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to a control using the
+ * <code>addShellListener</code> method and removed using
+ * the <code>removeShellListener</code> method. When the
+ * state of a shell changes, the appropriate method will
+ * be invoked.
+ * </p>
+ *
+ * @see ShellAdapter
+ * @see ShellEvent
+ */
+public interface ShellListener extends EventListener {
+
+/**
+ * Sent when a shell becomes the active window.
+ *
+ * @param e an event containing information about the activation
+ */
+public void shellActivated(ShellEvent e);
+
+/**
+ * Sent when a shell is closed.
+ *
+ * @param e an event containing information about the close
+ */
+public void shellClosed(ShellEvent e);
+
+/**
+ * Sent when a shell stops being the active window.
+ *
+ * @param e an event containing information about the deactivation
+ */
+public void shellDeactivated(ShellEvent e);
+
+/**
+ * Sent when a shell is un-minimized.
+ *
+ * @param e an event containing information about the un-minimization
+ */
+public void shellDeiconified(ShellEvent e);
+
+/**
+ * Sent when a shell is minimized.
+ *
+ * @param e an event containing information about the minimization
+ */
+public void shellIconified(ShellEvent e);
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/TraverseEvent.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/TraverseEvent.java
new file mode 100755
index 0000000000..26e378a961
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/TraverseEvent.java
@@ -0,0 +1,41 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * Instances of this class are sent as a result of
+ * widget traversal actions.
+ *
+ * @see TraverseListener
+ */
+
+public class TraverseEvent extends KeyEvent {
+
+ /**
+ * the type of traversal
+ */
+ public int detail;
+
+ /**
+ * a flag indicating whether the operation should be allowed
+ */
+ public boolean doit;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public TraverseEvent(Event e) {
+ super(e);
+ this.doit = e.doit;
+ this.detail = e.detail;
+}
+
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/TraverseListener.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/TraverseListener.java
new file mode 100755
index 0000000000..f78fcdb0eb
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/TraverseListener.java
@@ -0,0 +1,40 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import java.util.EventListener;
+
+/**
+ * Classes which implement this interface provide a method
+ * that deals with the events that are generated when a
+ * traverse event occurs in a control.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to a control using the
+ * <code>addTraverseListener</code> method and removed using
+ * the <code>removeTraverseListener</code> method. When a
+ * traverse event occurs in a control, the keyTraversed method
+ * will be invoked.
+ * </p>
+ *
+ * @see TraverseEvent
+ */
+public interface TraverseListener extends EventListener {
+
+/**
+ * Sent when a traverse event occurs in a control.
+ * <p>
+ * A traverse event occurs when the user presses a traversal
+ * key. Traversal keys are typically tab and arrow keys, along
+ * with certain other keys on some platforms. Traversal key
+ * constants beginning with <code>TRAVERSE_</code> are defined
+ * in the <code>SWT</code> class.
+ * </p>
+ *
+ * @param e an event containing information about the traverse
+ */
+public void keyTraversed(TraverseEvent e);
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/TreeAdapter.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/TreeAdapter.java
new file mode 100755
index 0000000000..f6c6d6867d
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/TreeAdapter.java
@@ -0,0 +1,39 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the <code>TreeListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>TreeEvent</code>s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ * </p>
+ *
+ * @see TreeListener
+ * @see TreeEvent
+ */
+public abstract class TreeAdapter implements TreeListener {
+
+/**
+ * Sent when a tree branch is collapsed.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the tree operation
+ */
+public void treeCollapsed(TreeEvent e) {
+}
+
+/**
+ * Sent when a tree branch is expanded.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the tree operation
+ */
+public void treeExpanded(TreeEvent e) {
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/TreeEvent.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/TreeEvent.java
new file mode 100755
index 0000000000..eb64963477
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/TreeEvent.java
@@ -0,0 +1,30 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * Instances of this class are sent as a result of
+ * trees being expanded and collapsed.
+ *
+ * @see TreeListener
+ */
+
+public final class TreeEvent extends SelectionEvent {
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public TreeEvent(Event e) {
+ super(e);
+}
+
+}
+
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/TreeListener.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/TreeListener.java
new file mode 100755
index 0000000000..77b0cdce84
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/TreeListener.java
@@ -0,0 +1,41 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import java.util.EventListener;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the expanding and collapsing of tree
+ * branches.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to a control using the
+ * <code>addTreeListener</code> method and removed using
+ * the <code>removeTreeListener</code> method. When a branch
+ * of a tree is expanded or collapsed, the appropriate method
+ * will be invoked.
+ * </p>
+ *
+ * @see TreeAdapter
+ * @see TreeEvent
+ */
+public interface TreeListener extends EventListener {
+
+/**
+ * Sent when a tree branch is collapsed.
+ *
+ * @param e an event containing information about the tree operation
+ */
+public void treeCollapsed(TreeEvent e);
+
+/**
+ * Sent when a tree branch is expanded.
+ *
+ * @param e an event containing information about the tree operation
+ */
+public void treeExpanded(TreeEvent e);
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/TypedEvent.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/TypedEvent.java
new file mode 100755
index 0000000000..19b53c21ef
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/TypedEvent.java
@@ -0,0 +1,56 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import org.eclipse.swt.widgets.*;
+import java.util.EventObject;
+
+/**
+ * This is the super class for all typed event classes provided
+ * by SWT. Typed events contain particular information which is
+ * applicable to the event occurance.
+ *
+ * @see org.eclipse.swt.widgets.Event
+ */
+public class TypedEvent extends EventObject {
+
+ /**
+ * the widget that issued the event
+ */
+ public Widget widget;
+
+ /**
+ * the time that the event occurred
+ */
+ public int time;
+
+ /**
+ * a field for application use
+ */
+ public Object data;
+
+/**
+ * Constructs a new instance of this class.
+ *
+ * @param source the object that fired the event
+ */
+public TypedEvent(Object object) {
+ super(object);
+}
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the argument.
+ *
+ * @param e the low level event to initialize the receiver with
+ */
+public TypedEvent(Event e) {
+ super(e.widget);
+ this.widget = e.widget;
+ this.time = e.time;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/VerifyEvent.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/VerifyEvent.java
new file mode 100755
index 0000000000..40aaa43e8d
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/VerifyEvent.java
@@ -0,0 +1,51 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * Instances of this class are sent as a result of
+ * widgets handling keyboard events
+ *
+ * @see VerifyListener
+ */
+
+public final class VerifyEvent extends KeyEvent {
+
+ /**
+ * the range of text being modified
+ */
+ public int start, end;
+
+ /**
+ * the new text that will be inserted
+ */
+ public String text;
+
+ /**
+ * a flag indicating whether the operation should be allowed
+ */
+ public boolean doit;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public VerifyEvent(Event e) {
+ super(e);
+ this.character = e.character;
+ this.keyCode = e.keyCode;
+ this.stateMask = e.stateMask;
+ this.start = e.start;
+ this.end = e.end;
+ this.text = e.text;
+ this.doit = e.doit;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/VerifyListener.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/VerifyListener.java
new file mode 100755
index 0000000000..b2d18ad8fc
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/VerifyListener.java
@@ -0,0 +1,39 @@
+package org.eclipse.swt.events;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import java.util.EventListener;
+
+/**
+ * Classes which implement this interface provide a method
+ * that deals with the events that are generated when text
+ * is about to be modified.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to a text widget using the
+ * <code>addVerifyListener</code> method and removed using
+ * the <code>removeVerifyListener</code> method. When the
+ * text is about to be modified, the verifyText method
+ * will be invoked.
+ * </p>
+ *
+ * @see VerifyEvent
+ */
+public interface VerifyListener extends EventListener {
+
+/**
+ * Sent when the text is about to be modified.
+ * <p>
+ * A verify event occurs after the user has done something
+ * to modify the text (typically typed a key), but before
+ * the text is modified. The doit field in the verify event
+ * indicates whether or not to modify the text.
+ * </p>
+ *
+ * @param e an event containing information about the verify
+ */
+public void verifyText(VerifyEvent e);
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/package.html b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/package.html
new file mode 100755
index 0000000000..6cb72031fc
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/events/package.html
@@ -0,0 +1,22 @@
+ <html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="Author" content="IBM">
+ <title>Package-level Javadoc</title>
+</head>
+<body>
+SWT <em>typed listener</em> support.
+<h2>
+Package Specification</h2>
+This package provides the typed events and listener interfaces and,
+where appropriate, matching adapter classes which make up the
+"high level" <em>typed listener</em> support provided by SWT.
+<p>
+For contrast, see also the <em>untyped listener</em> support provided
+by class <code>org.eclipse.swt.widgets.Event</code> and interface
+<code>org.eclipse.swt.widgets.Listener</code>, and the
+<code>addListener</code> and <code>removeListener</code> methods in
+class <code>org.eclipse.swt.widgets.Widget</code>.
+</p>
+</body>
+</html>
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Drawable.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Drawable.java
new file mode 100755
index 0000000000..08a180c95e
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Drawable.java
@@ -0,0 +1,45 @@
+package org.eclipse.swt.graphics;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+public interface Drawable {
+
+/**
+ * Invokes platform specific functionality to allocate a new GC handle.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Drawable</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param data the platform specific GC data
+ * @return the platform specific GC handle
+ *
+ * @private
+ */
+
+public int internal_new_GC (GCData data);
+
+/**
+ * Invokes platform specific functionality to dispose a GC handle.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Drawable</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param handle the platform specific GC handle
+ * @param data the platform specific GC data
+ *
+ * @private
+ */
+public void internal_dispose_GC (int handle, GCData data);
+
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageData.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageData.java
new file mode 100755
index 0000000000..cc455ff417
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageData.java
@@ -0,0 +1,3451 @@
+package org.eclipse.swt.graphics;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.io.*;
+import java.util.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.image.*;
+
+/**
+ * Instances of this class are device-independent descriptions
+ * of images. They are typically used as an intermediate format
+ * between loading from or writing to streams and creating an
+ * <code>Image</code>.
+ * <p>
+ * Note that the public fields <code>x</code>, <code>y</code>,
+ * <code>disposalMethod</code> and <code>delayTime</code> are
+ * typically only used when the image is in a set of images used
+ * for animation.
+ *
+ * @see Image
+ * @see ImageLoader
+ */
+
+public final class ImageData implements Cloneable {
+
+ /**
+ * the width of the image, in pixels
+ */
+ public int width;
+
+ /**
+ * the height of the image, in pixels
+ */
+ public int height;
+
+ /**
+ * the color depth of the image, in bits per pixel
+ */
+ public int depth;
+
+ /**
+ * the scanline padding. If one scanline of the image
+ * is not a multiple of this number, it will be padded
+ * with zeros until it is
+ */
+ public int scanlinePad;
+
+ /**
+ * the number of bytes per scanline. This is a multiple
+ * of the scanline padding
+ */
+ public int bytesPerLine;
+
+ /**
+ * the pixel data of the image
+ */
+ public byte[] data;
+
+ /**
+ * the color table for the image
+ */
+ public PaletteData palette;
+
+ /**
+ * the transparent pixel. Pixels with this value are transparent.
+ * The default is -1 which means 'no transparency'
+ */
+ public int transparentPixel;
+
+ /**
+ * icon-specific field containing the data from the icon mask
+ */
+ public byte[] maskData;
+
+ /**
+ * icon-specific field containing the scanline pad of the mask
+ */
+ public int maskPad;
+
+ /**
+ * the alpha data of the image. Every pixel can have an
+ * <em>alpha blending</em> value that varies from 0, meaning
+ * fully transparent, to 255 meaning fully opaque
+ */
+ public byte[] alphaData;
+
+ /**
+ * the global alpha value to be used for every pixel.
+ * If this value is set the <code>alphaData</code> field
+ * is ignored. The default is -1 which means 'no global alpha
+ * value'
+ */
+ public int alpha;
+
+ /**
+ * the type of file that the image was read in from,
+ * expressed as one of the following values:
+ * <dl>
+ * <dt><code>IMAGE_BMP</code></dt>
+ * <dd>Windows BMP file format, no compression</dd>
+ * <dt><code>IMAGE_BMP_RLE</code></dt>
+ * <dd>Windows BMP file format, RLE compression if appropriate</dd>
+ * <dt><code>IMAGE_GIF</code></dt>
+ * <dd>GIF file format</dd>
+ * <dt><code>IMAGE_ICO</code></dt>
+ * <dd>Windows ICO file format</dd>
+ * <dt><code>IMAGE_JPEG</code></dt>
+ * <dd>JPEG file format</dd>
+ * <dt><code>IMAGE_PNG</code></dt>
+ * <dd>PNG file format</dd>
+ * </dl>
+ */
+ public int type;
+
+ /**
+ * the x coordinate of the top left corner of the image
+ * within the logical screen (this field corresponds to
+ * the GIF89a Image Left Position value)
+ */
+ public int x;
+
+ /**
+ * The y coordinate of the top left corner of the image
+ * within the logical screen (this field corresponds to
+ * the GIF89a Image Top Position value)
+ */
+ public int y;
+
+ /**
+ * a description of how to dispose of the current image
+ * before displaying the next, expressed as one of the
+ * following values:
+ * <dl>
+ * <dt><code>DM_UNSPECIFIED</code></dt>
+ * <dd>disposal method not specified</dd>
+ * <dt><code>DM_FILL_NONE</code></dt>
+ * <dd>do nothing - leave the image in place</dd>
+ * <dt><code>DM_FILL_BACKGROUND</code></dt>
+ * <dd>fill with the background color</dd>
+ * <dt><code>DM_FILL_PREVIOUS</code></dt>
+ * <dd>restore the previous picture</dd>
+ * </dl>
+ * (this field corresponds to the GIF89a Disposal Method value)
+ */
+ public int disposalMethod;
+
+ /**
+ * the time to delay before displaying the next image
+ * in an animation (this field corresponds to the GIF89a
+ * Delay Time value)
+ */
+ public int delayTime;
+
+/**
+ * Constructs a new, empty ImageData with the given width, height,
+ * depth and palette. The data will be initialized to an (all zero)
+ * array of the appropriate size.
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ * @param depth the depth of the image
+ * @param palette the palette of the image (must not be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the width or height is negative</li>
+ * <li>ERROR_NULL_ARGUMENT - if the palette is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_UNSUPPORTED_DEPTH - if the depth argument is not one of 1, 2, 4, 8, 16, 24 or 32</li>
+ * </ul>
+ */
+public ImageData(int width, int height, int depth, PaletteData palette) {
+ this(width, height, depth, palette,
+ 4, null, 0, null,
+ null, -1, -1, SWT.IMAGE_UNDEFINED,
+ 0, 0, 0, 0);
+}
+
+/**
+ * Constructs a new, empty ImageData with the given width, height,
+ * depth, palette, scanlinePad and data.
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ * @param depth the depth of the image
+ * @param palette the palette of the image
+ * @param scanlinePad the padding of each line, in bytes
+ * @param data the data of the image
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the width or height is negative</li>
+ * <li>ERROR_NULL_ARGUMENT - if the palette or data is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_UNSUPPORTED_DEPTH - if the depth argument is not one of 1, 2, 4, 8, 16, 24 or 32</li>
+ * </ul>
+ */
+public ImageData(int width, int height, int depth, PaletteData palette, int scanlinePad, byte[] data) {
+ this(width, height, depth, palette,
+ scanlinePad, checkData(data), 0, null,
+ null, -1, -1, SWT.IMAGE_UNDEFINED,
+ 0, 0, 0, 0);
+}
+
+/**
+ * Constructs an <code>ImageData</code> loaded from the specified
+ * input stream. Throws an error if an error occurs while loading
+ * the image, or if the image has an unsupported type.
+ * <p>
+ * This constructor is provided for convenience when loading a single
+ * image only. If the stream contains multiple images, only the first
+ * one will be loaded. To load multiple images, use
+ * <code>ImageLoader.load()</code>.
+ * </p>
+ *
+ * @param stream the input stream to load the image from (must not be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the stream is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_INVALID_IMAGE - if the image file contains invalid data</li>
+ * <li>ERROR_IO - if an IO error occurs while reading data</li>
+ * </ul>
+ *
+ * @see ImageLoader#load
+ */
+public ImageData(InputStream stream) {
+ ImageData[] data = new ImageLoader().load(stream);
+ if (data.length < 1) SWT.error(SWT.ERROR_INVALID_IMAGE);
+ ImageData i = data[0];
+ setAllFields(
+ i.width,
+ i.height,
+ i.depth,
+ i.scanlinePad,
+ i.bytesPerLine,
+ i.data,
+ i.palette,
+ i.transparentPixel,
+ i.maskData,
+ i.maskPad,
+ i.alphaData,
+ i.alpha,
+ i.type,
+ i.x,
+ i.y,
+ i.disposalMethod,
+ i.delayTime);
+}
+
+/**
+ * Constructs an <code>ImageData</code> loaded from a file with the
+ * specified name. Throws an error if an error occurs loading the
+ * image, or if the image has an unsupported type.
+ * <p>
+ * This constructor is provided for convenience when loading a single
+ * image only. If the file contains multiple images, only the first
+ * one will be loaded. To load multiple images, use
+ * <code>ImageLoader.load()</code>.
+ * </p>
+ *
+ * @param filename the name of the file to load the image from (must not be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the file name is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_INVALID_IMAGE - if the image file contains invalid data</li>
+ * <li>ERROR_IO if an IO error occurs while reading data</li>
+ * </ul>
+ */
+public ImageData(String filename) {
+ ImageData[] data = new ImageLoader().load(filename);
+ if (data.length < 1) SWT.error(SWT.ERROR_INVALID_IMAGE);
+ ImageData i = data[0];
+ setAllFields(
+ i.width,
+ i.height,
+ i.depth,
+ i.scanlinePad,
+ i.bytesPerLine,
+ i.data,
+ i.palette,
+ i.transparentPixel,
+ i.maskData,
+ i.maskPad,
+ i.alphaData,
+ i.alpha,
+ i.type,
+ i.x,
+ i.y,
+ i.disposalMethod,
+ i.delayTime);
+}
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+ImageData() {
+}
+
+/**
+ * Constructs an image data by giving values for all non-computable fields.
+ * <p>
+ * This method is for internal use, and is not described further.
+ * </p>
+ */
+ImageData(
+ int width, int height, int depth, PaletteData palette,
+ int scanlinePad, byte[] data, int maskPad, byte[] maskData,
+ byte[] alphaData, int alpha, int transparentPixel, int type,
+ int x, int y, int disposalMethod, int delayTime)
+{
+
+ if (palette == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (!(depth == 1 || depth == 2 || depth == 4 || depth == 8
+ || depth == 16 || depth == 24 || depth == 32)) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (width <= 0 || height <= 0) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ int bytesPerLine = (((width * depth + 7) / 8) + (scanlinePad - 1))
+ / scanlinePad * scanlinePad;
+ setAllFields(
+ width,
+ height,
+ depth,
+ scanlinePad,
+ bytesPerLine,
+ data != null ? data : new byte[bytesPerLine * height],
+ palette,
+ transparentPixel,
+ maskData,
+ maskPad,
+ alphaData,
+ alpha,
+ type,
+ x,
+ y,
+ disposalMethod,
+ delayTime);
+}
+
+/**
+ * Initializes all fields in the receiver. This method must be called
+ * by all public constructors to ensure that all fields are initialized
+ * for a new ImageData object. If a new field is added to the class,
+ * then it must be added to this method.
+ * <p>
+ * This method is for internal use, and is not described further.
+ * </p>
+ */
+void setAllFields(int width, int height, int depth, int scanlinePad,
+ int bytesPerLine, byte[] data, PaletteData palette, int transparentPixel,
+ byte[] maskData, int maskPad, byte[] alphaData, int alpha,
+ int type, int x, int y, int disposalMethod, int delayTime) {
+
+ this.width = width;
+ this.height = height;
+ this.depth = depth;
+ this.scanlinePad = scanlinePad;
+ this.bytesPerLine = bytesPerLine;
+ this.data = data;
+ this.palette = palette;
+ this.transparentPixel = transparentPixel;
+ this.maskData = maskData;
+ this.maskPad = maskPad;
+ this.alphaData = alphaData;
+ this.alpha = alpha;
+ this.type = type;
+ this.x = x;
+ this.y = y;
+ this.disposalMethod = disposalMethod;
+ this.delayTime = delayTime;
+}
+
+/**
+ * Invokes internal SWT functionality to create a new instance of
+ * this class.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>ImageData</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is subject
+ * to change without notice, and should never be called from
+ * application code.
+ * </p>
+ * <p>
+ * This method is for internal use, and is not described further.
+ * </p>
+ *
+ * @private
+ */
+public static ImageData internal_new(
+ int width, int height, int depth, PaletteData palette,
+ int scanlinePad, byte[] data, int maskPad, byte[] maskData,
+ byte[] alphaData, int alpha, int transparentPixel, int type,
+ int x, int y, int disposalMethod, int delayTime)
+{
+ return new ImageData(
+ width, height, depth, palette, scanlinePad, data, maskPad, maskData,
+ alphaData, alpha, transparentPixel, type, x, y, disposalMethod, delayTime);
+}
+
+ImageData colorMaskImage(int pixel) {
+ ImageData mask = new ImageData(width, height, 1, bwPalette(),
+ Image.DEFAULT_SCANLINE_PAD, null, 0, null,
+ null, -1, -1, SWT.IMAGE_UNDEFINED,
+ 0, 0, 0, 0);
+ int[] row = new int[width];
+ for (int y = 0; y < height; y++) {
+ getPixels(0, y, width, row, 0);
+ for (int i = 0; i < width; i++) {
+ if (pixel != -1 && row[i] == pixel) {
+ row[i] = 0;
+ } else {
+ row[i] = 1;
+ }
+ }
+ mask.setPixels(0, y, width, row, 0);
+ }
+ return mask;
+}
+
+static byte[] checkData(byte [] data) {
+ if (data == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ return data;
+}
+
+/**
+ * Returns a new instance of the same class as the receiver,
+ * whose slots have been filled in with <em>copies</em> of
+ * the values in the slots of the receiver. That is, the
+ * returned object is a <em>deep copy</em> of the receiver.
+ *
+ * @return a copy of the receiver.
+ */
+public Object clone() {
+ byte[] cloneData = new byte[data.length];
+ System.arraycopy(data, 0, cloneData, 0, data.length);
+ byte[] cloneMaskData = null;
+ if (maskData != null) {
+ cloneMaskData = new byte[maskData.length];
+ System.arraycopy(maskData, 0, cloneMaskData, 0, maskData.length);
+ }
+ byte[] cloneAlphaData = null;
+ if (alphaData != null) {
+ cloneAlphaData = new byte[alphaData.length];
+ System.arraycopy(alphaData, 0, cloneAlphaData, 0, alphaData.length);
+ }
+ return new ImageData(
+ width,
+ height,
+ depth,
+ palette,
+ scanlinePad,
+ cloneData,
+ maskPad,
+ cloneMaskData,
+ cloneAlphaData,
+ alpha,
+ transparentPixel,
+ type,
+ x,
+ y,
+ disposalMethod,
+ delayTime);
+}
+
+/**
+ * Returns the alpha value at offset <code>x</code> in
+ * scanline <code>y</code> in the receiver's alpha data.
+ *
+ * @param x the x coodinate of the pixel to get the alpha value of
+ * @param y the y coordinate of the pixel to get the alpha value of
+ * @return the alpha value at the given coordinates
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if either argument is out of range</li>
+ * </ul>
+ */
+public int getAlpha(int x, int y) {
+ if (x > width || y > height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+
+ if (alphaData == null) return 255;
+ return alphaData[y * width + x] & 0xFF;
+}
+
+/**
+ * Returns <code>getWidth</code> alpha values starting at offset
+ * <code>x</code> in scanline <code>y</code> in the receiver's alpha
+ * data starting at <code>startIndex</code>.
+ *
+ * @param x the x position of the pixel to begin getting alpha values
+ * @param y the y position of the pixel to begin getting alpha values
+ * @param getWidth the width of the data to get
+ * @param alphas the buffer in which to put the alpha values
+ * @param startIndex the offset into the image to begin getting alpha values
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if pixels is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if <code>x</code> or <code>y</code> is out of bounds</li>
+ * </ul>
+ */
+public void getAlphas(int x, int y, int getWidth, byte[] alphas, int startIndex) {
+ if (alphas == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (getWidth <= 0) return;
+ if (x >= width || y >= height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+
+ if (alphaData == null) {
+ int endIndex = startIndex + getWidth;
+ for (int i = startIndex; i < endIndex; i++) {
+ alphas[i] = (byte)255;
+ }
+ return;
+ }
+ System.arraycopy(alphaData, y * width + x, alphas, startIndex, getWidth);
+}
+
+/**
+ * Returns the pixel value at offset <code>x</code> in
+ * scanline <code>y</code> in the receiver's data.
+ *
+ * @param x the x position of the pixel to get
+ * @param y the y position of the pixel to get
+ * @return the pixel at the given coordinates
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if either argument is out of bounds</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_UNSUPPORTED_DEPTH if the depth is not one of 1, 2, 4, 8, 16, 24 or 32</li>
+ * </ul>
+ */
+public int getPixel(int x, int y) {
+ if (x > width || y > height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int index;
+ int theByte;
+ int mask;
+ if (depth == 1) {
+ index = (y * bytesPerLine) + (x >> 3);
+ theByte = data[index] & 0xFF;
+ mask = 1 << (7 - (x & 0x7));
+ if ((theByte & mask) == 0) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+ if (depth == 2) {
+ index = (y * bytesPerLine) + (x >> 2);
+ theByte = data[index] & 0xFF;
+ int offset = 3 - (x % 4);
+ mask = 3 << (offset * 2);
+ return (theByte & mask) >> (offset * 2);
+ }
+ if (depth == 4) {
+ index = (y * bytesPerLine) + (x >> 1);
+ theByte = data[index] & 0xFF;
+ if ((x & 0x1) == 0) {
+ return theByte >> 4;
+ } else {
+ return theByte & 0x0F;
+ }
+ }
+ if (depth == 8) {
+ index = (y * bytesPerLine) + x ;
+ return data[index] & 0xFF;
+ }
+ if (depth == 16) {
+ index = (y * bytesPerLine) + (x * 2);
+ return ((data[index+1] & 0xFF) << 8) + (data[index] & 0xFF);
+ }
+ if (depth == 24) {
+ index = (y * bytesPerLine) + (x * 3);
+ return ((data[index] & 0xFF) << 16) + ((data[index+1] & 0xFF) << 8) +
+ (data[index+2] & 0xFF);
+ }
+ if (depth == 32) {
+ index = (y * bytesPerLine) + (x * 4);
+ return ((data[index] & 0xFF) << 24) + ((data[index+1] & 0xFF) << 16) +
+ ((data[index+2] & 0xFF) << 8) + (data[index+3] & 0xFF);
+ }
+ SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+ return 0;
+}
+
+/**
+ * Returns <code>getWidth</code> pixel values starting at offset
+ * <code>x</code> in scanline <code>y</code> in the receiver's
+ * data starting at <code>startIndex</code>.
+ *
+ * @param x the x position of the first pixel to get
+ * @param y the y position of the first pixel to get
+ * @param getWidth the width of the data to get
+ * @param pixels the buffer in which to put the pixels
+ * @param startIndex the offset into the byte array to begin storing pixels
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if pixels is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_UNSUPPORTED_DEPTH - if the depth is not one of 1, 2, 4 or 8
+ * (For higher depths, use the int[] version of this method.)</li>
+ * </ul>
+ */
+public void getPixels(int x, int y, int getWidth, byte[] pixels, int startIndex) {
+ if (pixels == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (getWidth <= 0) return;
+ if (x >= width || y >= height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int index;
+ int theByte;
+ int mask = 0;
+ int n = getWidth;
+ int i = startIndex;
+ int srcX = x, srcY = y;
+ if (depth == 1) {
+ index = (y * bytesPerLine) + (x >> 3);
+ theByte = data[index] & 0xFF;
+ while (n > 1) {
+ mask = 1 << (7 - (srcX & 0x7));
+ if ((theByte & mask) == 0) {
+ pixels[i] = 0;
+ } else {
+ pixels[i] = 1;
+ }
+ i++;
+ n--;
+ srcX++;
+ if (srcX >= width) {
+ srcY++;
+ index = srcY * bytesPerLine;
+ if (n > 0) theByte = data[index] & 0xFF;
+ srcX = 0;
+ } else {
+ if (mask == 1) {
+ index++;
+ if (n > 0) theByte = data[index] & 0xFF;
+ }
+ }
+ }
+ return;
+ }
+ if (depth == 2) {
+ index = (y * bytesPerLine) + (x >> 2);
+ theByte = data[index] & 0xFF;
+ int offset;
+ while (n > 0) {
+ offset = 3 - (srcX % 4);
+ mask = 3 << (offset * 2);
+ pixels[i] = (byte)((theByte & mask) >> (offset * 2));
+ i++;
+ n--;
+ srcX++;
+ if (srcX >= width) {
+ srcY++;
+ index = srcY * bytesPerLine;
+ if (n > 0) theByte = data[index] & 0xFF;
+ srcX = 0;
+ } else {
+ if (offset == 0) {
+ index++;
+ theByte = data[index] & 0xFF;
+ }
+ }
+ }
+ return;
+ }
+ if (depth == 4) {
+ index = (y * bytesPerLine) + (x >> 1);
+ if ((x & 0x1) == 1) {
+ theByte = data[index] & 0xFF;
+ pixels[i] = (byte)(theByte & 0x0F);
+ i++;
+ n--;
+ srcX++;
+ if (srcX >= width) {
+ srcY++;
+ index = srcY * bytesPerLine;
+ srcX = 0;
+ } else {
+ index++;
+ }
+ }
+ while (n > 1) {
+ theByte = data[index] & 0xFF;
+ pixels[i] = (byte)(theByte >> 4);
+ i++;
+ n--;
+ srcX++;
+ if (srcX >= width) {
+ srcY++;
+ index = srcY * bytesPerLine;
+ srcX = 0;
+ } else {
+ pixels[i] = (byte)(theByte & 0x0F);
+ i++;
+ n--;
+ srcX++;
+ if (srcX >= width) {
+ srcY++;
+ index = srcY * bytesPerLine;
+ srcX = 0;
+ } else {
+ index++;
+ }
+ }
+ }
+ if (n > 0) {
+ theByte = data[index] & 0xFF;
+ pixels[i] = (byte)(theByte >> 4);
+ }
+ return;
+ }
+ if (depth == 8) {
+ index = (y * bytesPerLine) + x;
+ for (int j = 0; j < getWidth; j++) {
+ pixels[i] = data[index];
+ i++;
+ srcX++;
+ if (srcX >= width) {
+ srcY++;
+ index = srcY * bytesPerLine;
+ srcX = 0;
+ } else {
+ index++;
+ }
+ }
+ return;
+ }
+ SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+}
+
+/**
+ * Returns <code>getWidth</code> pixel values starting at offset
+ * <code>x</code> in scanline <code>y</code> in the receiver's
+ * data starting at <code>startIndex</code>.
+ *
+ * @param x the x position of the first pixel to get
+ * @param y the y position of the first pixel to get
+ * @param getWidth the width of the data to get
+ * @param pixels the buffer in which to put the pixels
+ * @param startIndex the offset into the buffer to begin storing pixels
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if pixels is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_UNSUPPORTED_DEPTH - if the depth is not one of 1, 2, 4, 8, 16, 24 or 32</li>
+ * </ul>
+ */
+public void getPixels(int x, int y, int getWidth, int[] pixels, int startIndex) {
+ if (pixels == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (getWidth <= 0) return;
+ if (x > width || y > height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int index;
+ int theByte;
+ int mask;
+ int n = getWidth;
+ int i = startIndex;
+ int srcX = x, srcY = y;
+ if (depth == 1) {
+ index = (y * bytesPerLine) + (x >> 3);
+ theByte = data[index] & 0xFF;
+ while (n > 0) {
+ mask = 1 << (7 - (srcX & 0x7));
+ if ((theByte & mask) == 0) {
+ pixels[i] = 0;
+ } else {
+ pixels[i] = 1;
+ }
+ i++;
+ n--;
+ srcX++;
+ if (srcX >= width) {
+ srcY++;
+ index = srcY * bytesPerLine;
+ if (n > 0) theByte = data[index] & 0xFF;
+ srcX = 0;
+ } else {
+ if (mask == 1) {
+ index++;
+ if (n > 0) theByte = data[index] & 0xFF;
+ }
+ }
+ }
+ return;
+ }
+ if (depth == 2) {
+ index = (y * bytesPerLine) + (x >> 2);
+ theByte = data[index] & 0xFF;
+ int offset;
+ while (n > 0) {
+ offset = 3 - (srcX % 4);
+ mask = 3 << (offset * 2);
+ pixels[i] = (byte)((theByte & mask) >> (offset * 2));
+ i++;
+ n--;
+ srcX++;
+ if (srcX >= width) {
+ srcY++;
+ index = srcY * bytesPerLine;
+ if (n > 0) theByte = data[index] & 0xFF;
+ srcX = 0;
+ } else {
+ if (offset == 0) {
+ index++;
+ theByte = data[index] & 0xFF;
+ }
+ }
+ }
+ return;
+ }
+ if (depth == 4) {
+ index = (y * bytesPerLine) + (x >> 1);
+ if ((x & 0x1) == 1) {
+ theByte = data[index] & 0xFF;
+ pixels[i] = theByte & 0x0F;
+ i++;
+ n--;
+ srcX++;
+ if (srcX >= width) {
+ srcY++;
+ index = srcY * bytesPerLine;
+ srcX = 0;
+ } else {
+ index++;
+ }
+ }
+ while (n > 1) {
+ theByte = data[index] & 0xFF;
+ pixels[i] = theByte >> 4;
+ i++;
+ n--;
+ srcX++;
+ if (srcX >= width) {
+ srcY++;
+ index = srcY * bytesPerLine;
+ srcX = 0;
+ } else {
+ pixels[i] = theByte & 0x0F;
+ i++;
+ n--;
+ srcX++;;
+ if (srcX >= width) {
+ srcY++;
+ index = srcY * bytesPerLine;
+ srcX = 0;
+ } else {
+ index++;
+ }
+ }
+ }
+ if (n > 0) {
+ theByte = data[index] & 0xFF;
+ pixels[i] = theByte >> 4;
+ }
+ return;
+ }
+ if (depth == 8) {
+ index = (y * bytesPerLine) + x;
+ for (int j = 0; j < getWidth; j++) {
+ pixels[i] = data[index] & 0xFF;
+ i++;
+ srcX++;
+ if (srcX >= width) {
+ srcY++;
+ index = srcY * bytesPerLine;
+ srcX = 0;
+ } else {
+ index++;
+ }
+ }
+ return;
+ }
+ if (depth == 16) {
+ index = (y * bytesPerLine) + (x * 2);
+ for (int j = 0; j < getWidth; j++) {
+ pixels[i] = ((data[index+1] & 0xFF) << 8) + (data[index] & 0xFF);
+ i++;
+ srcX++;
+ if (srcX >= width) {
+ srcY++;
+ index = srcY * bytesPerLine;
+ srcX = 0;
+ } else {
+ index += 2;
+ }
+ }
+ return;
+ }
+ if (depth == 24) {
+ index = (y * bytesPerLine) + (x * 3);
+ for (int j = 0; j < getWidth; j++) {
+ pixels[i] = ((data[index] & 0xFF) << 16) | ((data[index+1] & 0xFF) << 8)
+ | (data[index+2] & 0xFF);
+ i++;
+ srcX++;
+ if (srcX >= width) {
+ srcY++;
+ index = srcY * bytesPerLine;
+ srcX = 0;
+ } else {
+ index += 3;
+ }
+ }
+ return;
+ }
+ if (depth == 32) {
+ index = (y * bytesPerLine) + (x * 4);
+ i = startIndex;
+ for (int j = 0; j < getWidth; j++) {
+ pixels[i] = ((data[index] & 0xFF) << 24) | ((data[index+1] & 0xFF) << 16)
+ | ((data[index+2] & 0xFF) << 8) | (data[index+3] & 0xFF);
+ i++;
+ srcX++;
+ if (srcX >= width) {
+ srcY++;
+ index = srcY * bytesPerLine;
+ srcX = 0;
+ } else {
+ index += 4;
+ }
+ }
+ return;
+ }
+ SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+}
+
+/**
+ * Returns an array of <code>RGB</code>s which comprise the
+ * indexed color table of the receiver, or null if the receiver
+ * has a direct color model.
+ *
+ * @return the RGB values for the image or null if direct color
+ *
+ * @see PaletteData#getRGBs
+ */
+public RGB[] getRGBs() {
+ return palette.getRGBs();
+}
+
+/**
+ * Returns an <code>ImageData</code> which specifies the
+ * transparency mask information for the receiver, or null if the
+ * receiver has no transparency and is not an icon.
+ *
+ * @return the transparency mask or null if none exists
+ */
+public ImageData getTransparencyMask() {
+ if (getTransparencyType() == SWT.TRANSPARENCY_MASK) {
+ return new ImageData(width, height, 1, bwPalette(), maskPad, maskData);
+ } else {
+ return colorMaskImage(transparentPixel);
+ }
+}
+
+/**
+ * Returns the image transparency type.
+ *
+ * @return the receiver's transparency type
+ */
+public int getTransparencyType() {
+ if (maskData != null) return SWT.TRANSPARENCY_MASK;
+ if (transparentPixel != -1) return SWT.TRANSPARENCY_PIXEL;
+ if (alphaData != null) return SWT.TRANSPARENCY_ALPHA;
+ return SWT.TRANSPARENCY_NONE;
+}
+
+/**
+ * Returns a copy of the receiver which has been stretched or
+ * shrunk to the specified size. If either the width or height
+ * is negative, the resulting image will be inverted in the
+ * associated axis.
+ *
+ * @param width the width of the new ImageData
+ * @param height the height of the new ImageData
+ * @return a scaled copy of the image
+ */
+public ImageData scaledTo(int width, int height) {
+ /* Create a destination image with no data,
+ * and then scale all of the data. */
+ ImageData destImage = new ImageData(
+ width, height, depth, palette,
+ scanlinePad, null, 0, null,
+ null, -1, transparentPixel, type,
+ x, y, disposalMethod, delayTime);
+ scaleImage(destImage, 0, 0, this.width, this.height, 0, 0, width, height);
+ return destImage;
+}
+
+void scaleImage(ImageData destImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight) {
+ boolean flipX, flipY;
+ /* Flip rects if necessary so that src width and height are positive. */
+ if (srcWidth < 0) {
+ srcWidth = -srcWidth;
+ srcX = srcX - srcWidth;
+ destWidth = -destWidth;
+ destX = destX - destWidth;
+ }
+ if (srcHeight < 0) {
+ srcHeight = -srcHeight;
+ srcY = srcY - srcHeight;
+ destHeight = -destHeight;
+ destY = destY - destHeight;
+ }
+ /* Ensure dest width and height are positive, remembering whether to flip. */
+ flipX = destWidth < 0;
+ if (flipX) {
+ destWidth = -destWidth;
+ destX = destX - destWidth;
+ }
+ flipY = destHeight < 0;
+ if (flipY) {
+ destHeight = -destHeight;
+ destY = destY - destHeight;
+ }
+ /* Check source rect bounds. Succeed with 0 if out of bounds, rather
+ * than failing.
+ */
+ if (srcX < 0 || srcY < 0 || (srcX + srcWidth > width) ||
+ (srcY + srcHeight > height)) {
+ return;
+ }
+ if (destX < 0 || destY < 0 || (destX + destWidth > destImage.width) ||
+ (destY + destHeight > destImage.height)) {
+ return;
+ }
+ /* If dest rect is 0, there is nothing to do. */
+ if (destWidth == 0 || destHeight == 0) {
+ return;
+ }
+ switch (depth) {
+ case 1:
+ stretch1(data, bytesPerLine, MSB_FIRST, srcX, srcY, srcWidth, srcHeight, destImage.data, destImage.bytesPerLine, MSB_FIRST, destX, destY, destWidth, destHeight, flipX, flipY);
+ break;
+ case 2:
+ stretch2(data, bytesPerLine, srcX, srcY, srcWidth, srcHeight, destImage.data, destImage.bytesPerLine, destX, destY, destWidth, destHeight, null, flipX, flipY);
+ break;
+ case 4:
+ stretch4(data, bytesPerLine, srcX, srcY, srcWidth, srcHeight, destImage.data, destImage.bytesPerLine, destX, destY, destWidth, destHeight, null, flipX, flipY);
+ break;
+ case 8:
+ stretch8(data, bytesPerLine, srcX, srcY, srcWidth, srcHeight, destImage.data, destImage.bytesPerLine, destX, destY, destWidth, destHeight, null, flipX, flipY);
+ break;
+ case 16:
+ stretch16(data, bytesPerLine, srcX, srcY, srcWidth, srcHeight, destImage.data, destImage.bytesPerLine, destX, destY, destWidth, destHeight, flipX, flipY);
+ break;
+ case 24:
+ stretch24(data, bytesPerLine, srcX, srcY, srcWidth, srcHeight, destImage.data, destImage.bytesPerLine, destX, destY, destWidth, destHeight, flipX, flipY);
+ break;
+ case 32:
+ stretch32(data, bytesPerLine, srcX, srcY, srcWidth, srcHeight, destImage.data, destImage.bytesPerLine, destX, destY, destWidth, destHeight, flipX, flipY);
+ break;
+ default:
+ SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+ }
+ if (getTransparencyType() == SWT.TRANSPARENCY_MASK) {
+ destImage.maskPad = maskPad;
+ int destBpl = (destWidth + 7) / 8;
+ destBpl = (destBpl + (maskPad - 1)) / maskPad * maskPad;
+ destImage.maskData = new byte[destBpl * destHeight];
+ int srcBpl = (srcWidth + 7) / 8;
+ srcBpl = (srcBpl + (maskPad - 1)) / maskPad * maskPad;
+ stretch1(maskData, srcBpl, MSB_FIRST, srcX, srcY, srcWidth, srcHeight, destImage.maskData, destBpl, MSB_FIRST, destX, destY, destWidth, destHeight, flipX, flipY);
+ } else if (alpha != -1) {
+ destImage.alpha = alpha;
+ } else if (alphaData != null) {
+ destImage.alphaData = new byte[destImage.width * destImage.height];
+ stretch8(alphaData, width, srcX, srcY, srcWidth, srcHeight, destImage.alphaData, destImage.width, destX, destY, destWidth, destHeight, null, flipX, flipY);
+ }
+}
+
+/**
+ * Sets the alpha value at offset <code>x</code> in
+ * scanline <code>y</code> in the receiver's alpha data.
+ *
+ * @param x the x coordinate of the alpha value to set
+ * @param y the y coordinate of the alpha value to set
+ * @param alpha the value to set the alpha to
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
+ * </ul>
+ */
+public void setAlpha(int x, int y, int alpha) {
+ if (x > width || y > height || x < 0 || y < 0 || alpha < 0 || alpha > 255)
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+
+ if (alphaData == null) alphaData = new byte[width * height];
+ alphaData[y * width + x] = (byte)alpha;
+}
+
+/**
+ * Sets the alpha values starting at offset <code>x</code> in
+ * scanline <code>y</code> in the receiver's alpha data to the
+ * values from the array <code>alphas</code> starting at
+ * <code>startIndex</code>.
+ *
+ * @param x the x coordinate of the pixel to being setting the alpha values
+ * @param y the y coordinate of the pixel to being setting the alpha values
+ * @param putWidth the width of the alpha values to set
+ * @param alphas the alpha values to set
+ * @param startIndex the index at which to begin setting
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if pixels is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
+ * </ul>
+ */
+public void setAlphas(int x, int y, int putWidth, byte[] alphas, int startIndex) {
+ if (alphas == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (putWidth <= 0) return;
+ if (x > width || y > height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+
+ if (alphaData == null) alphaData = new byte[width * height];
+ System.arraycopy(alphas, startIndex, alphaData, y * width + x, putWidth);
+}
+
+/**
+ * Sets the pixel value at offset <code>x</code> in
+ * scanline <code>y</code> in the receiver's data.
+ *
+ * @param x the x coordinate of the pixel to set
+ * @param y the y coordinate of the pixel to set
+ * @param pixelValue the value to set the pixel to
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_UNSUPPORTED_DEPTH if the depth is not one of 1, 2, 4, 8, 16, 24 or 32</li>
+ * </ul>
+ */
+public void setPixel(int x, int y, int pixelValue) {
+ if (x > width || y > height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int index;
+ byte theByte;
+ int mask;
+ if (depth == 1) {
+ index = (y * bytesPerLine) + (x >> 3);
+ theByte = data[index];
+ mask = 1 << (7 - (x & 0x7));
+ if ((pixelValue & 0x1) == 1) {
+ data[index] = (byte)(theByte | mask);
+ } else {
+ data[index] = (byte)(theByte & (mask ^ -1));
+ }
+ return;
+ }
+ if (depth == 2) {
+ index = (y * bytesPerLine) + (x >> 2);
+ theByte = data[index];
+ int offset = 3 - (x % 4);
+ mask = 0xFF ^ (3 << (offset * 2));
+ data[index] = (byte)((data[index] & mask) | (pixelValue << (offset * 2)));
+ return;
+ }
+ if (depth == 4) {
+ index = (y * bytesPerLine) + (x >> 1);
+ if ((x & 0x1) == 0) {
+ data[index] = (byte)((data[index] & 0x0F) | ((pixelValue & 0x0F) << 4));
+ } else {
+ data[index] = (byte)((data[index] & 0xF0) | (pixelValue & 0x0F));
+ }
+ return;
+ }
+ if (depth == 8) {
+ index = (y * bytesPerLine) + x ;
+ data[index] = (byte)(pixelValue & 0xFF);
+ return;
+ }
+ if (depth == 16) {
+ index = (y * bytesPerLine) + (x * 2);
+ data[index + 1] = (byte)((pixelValue >> 8) & 0xFF);
+ data[index] = (byte)(pixelValue & 0xFF);
+ return;
+ }
+ if (depth == 24) {
+ index = (y * bytesPerLine) + (x * 3);
+ data[index] = (byte)((pixelValue >> 16) & 0xFF);
+ data[index + 1] = (byte)((pixelValue >> 8) & 0xFF);
+ data[index + 2] = (byte)(pixelValue & 0xFF);
+ return;
+ }
+ if (depth == 32) {
+ index = (y * bytesPerLine) + (x * 4);
+ data[index] = (byte)((pixelValue >> 24) & 0xFF);
+ data[index + 1] = (byte)((pixelValue >> 16) & 0xFF);
+ data[index + 2] = (byte)((pixelValue >> 8) & 0xFF);
+ data[index + 3] = (byte)(pixelValue & 0xFF);
+ return;
+ }
+ SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+}
+
+/**
+ * Sets the pixel values starting at offset <code>x</code> in
+ * scanline <code>y</code> in the receiver's data to the
+ * values from the array <code>pixels</code> starting at
+ * <code>startIndex</code>.
+ *
+ * @param x the x position of the pixel to set
+ * @param y the y position of the pixel to set
+ * @param putWidth the width of the pixels to set
+ * @param pixels the pixels to set
+ * @param startIndex the index at which to begin setting
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if pixels is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_UNSUPPORTED_DEPTH if the depth is not one of 1, 2, 4, 8
+ * (For higher depths, use the int[] version of this method.)</li>
+ * </ul>
+ */
+public void setPixels(int x, int y, int putWidth, byte[] pixels, int startIndex) {
+ if (pixels == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (putWidth <= 0) return;
+ if (x > width || y > height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int index;
+ int theByte;
+ int mask;
+ int n = putWidth;
+ int i = startIndex;
+ int pixel;
+ int srcX = x, srcY = y;
+ if (depth == 1) {
+ index = (y * bytesPerLine) + (x >> 3);
+ while (n > 0) {
+ mask = 1 << (7 - (srcX & 0x7));
+ if ((pixels[i] & 0x1) == 1) {
+ data[index] = (byte)((data[index] & 0xFF) | mask);
+ } else {
+ data[index] = (byte)((data[index] & 0xFF) & (mask ^ -1));
+ }
+ i++;
+ n--;
+ srcX++;
+ if (srcX >= width) {
+ srcY++;
+ index = srcY * bytesPerLine;
+ srcX = 0;
+ } else {
+ if (mask == 1) {
+ index++;
+ }
+ }
+ }
+ return;
+ }
+ if (depth == 2) {
+ byte [] masks = { (byte)0xFC, (byte)0xF3, (byte)0xCF, (byte)0x3F };
+ index = (y * bytesPerLine) + (x >> 2);
+ int offset = 3 - (x % 4);
+ while (n > 0) {
+ theByte = pixels[i] & 0x3;
+ data[index] = (byte)((data[index] & masks[offset]) | (theByte << (offset * 2)));
+ i++;
+ n--;
+ srcX++;
+ if (srcX >= width) {
+ srcY++;
+ index = srcY * bytesPerLine;
+ offset = 0;
+ srcX = 0;
+ } else {
+ if (offset == 0) {
+ index++;
+ offset = 3;
+ } else {
+ offset--;
+ }
+ }
+ }
+ return;
+ }
+ if (depth == 4) {
+ index = (y * bytesPerLine) + (x >> 1);
+ boolean high = (x & 0x1) == 0;
+ while (n > 0) {
+ theByte = pixels[i] & 0x0F;
+ if (high) {
+ data[index] = (byte)((data[index] & 0x0F) | (theByte << 4));
+ } else {
+ data[index] = (byte)((data[index] & 0xF0) | theByte);
+ }
+ i++;
+ n--;
+ srcX++;
+ if (srcX >= width) {
+ srcY++;
+ index = srcY * bytesPerLine;
+ high = true;
+ srcX = 0;
+ } else {
+ if (!high) index++;
+ high = !high;
+ }
+ }
+ return;
+ }
+ if (depth == 8) {
+ index = (y * bytesPerLine) + x;
+ for (int j = 0; j < putWidth; j++) {
+ data[index] = (byte)(pixels[i] & 0xFF);
+ i++;
+ srcX++;
+ if (srcX >= width) {
+ srcY++;
+ index = srcY * bytesPerLine;
+ srcX = 0;
+ } else {
+ index++;
+ }
+ }
+ return;
+ }
+ SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+}
+
+/**
+ * Sets the pixel values starting at offset <code>x</code> in
+ * scanline <code>y</code> in the receiver's data to the
+ * values from the array <code>pixels</code> starting at
+ * <code>startIndex</code>.
+ *
+ * @param x the x position of the pixel to set
+ * @param y the y position of the pixel to set
+ * @param putWidth the width of the pixels to set
+ * @param pixels the pixels to set
+ * @param startIndex the index at which to begin setting
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if pixels is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_UNSUPPORTED_DEPTH if the depth is not one of 1, 2, 4, 8, 16, 24 or 32</li>
+ * </ul>
+ */
+public void setPixels(int x, int y, int putWidth, int[] pixels, int startIndex) {
+ if (pixels == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (putWidth <= 0) return;
+ if (x > width || y > height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int index;
+ int theByte;
+ int mask;
+ int n = putWidth;
+ int i = startIndex;
+ int pixel;
+ int srcX = x, srcY = y;
+ if (depth == 1) {
+ index = (y * bytesPerLine) + (x >> 3);
+ while (n > 0) {
+ mask = 1 << (7 - (srcX & 0x7));
+ if ((pixels[i] & 0x1) == 1) {
+ data[index] = (byte)((data[index] & 0xFF) | mask);
+ } else {
+ data[index] = (byte)((data[index] & 0xFF) & (mask ^ -1));
+ }
+ i++;
+ n--;
+ srcX++;
+ if (srcX >= width) {
+ srcY++;
+ index = srcY * bytesPerLine;
+ srcX = 0;
+ } else {
+ if (mask == 1) {
+ index++;
+ }
+ }
+ }
+ return;
+ }
+ if (depth == 2) {
+ byte [] masks = { (byte)0xFC, (byte)0xF3, (byte)0xCF, (byte)0x3F };
+ index = (y * bytesPerLine) + (x >> 2);
+ int offset = 3 - (x % 4);
+ while (n > 0) {
+ theByte = pixels[i] & 0x3;
+ data[index] = (byte)((data[index] & masks[offset]) | (theByte << (offset * 2)));
+ i++;
+ n--;
+ srcX++;
+ if (srcX >= width) {
+ srcY++;
+ index = srcY * bytesPerLine;
+ offset = 3;
+ srcX = 0;
+ } else {
+ if (offset == 0) {
+ index++;
+ offset = 3;
+ } else {
+ offset--;
+ }
+ }
+ }
+ return;
+ }
+ if (depth == 4) {
+ index = (y * bytesPerLine) + (x >> 1);
+ boolean high = (x & 0x1) == 0;
+ while (n > 0) {
+ theByte = pixels[i] & 0x0F;
+ if (high) {
+ data[index] = (byte)((data[index] & 0x0F) | (theByte << 4));
+ } else {
+ data[index] = (byte)((data[index] & 0xF0) | theByte);
+ }
+ i++;
+ n--;
+ srcX++;
+ if (srcX >= width) {
+ srcY++;
+ index = srcY * bytesPerLine;
+ high = true;
+ srcX = 0;
+ } else {
+ if (!high) index++;
+ high = !high;
+ }
+ }
+ return;
+ }
+ if (depth == 8) {
+ index = (y * bytesPerLine) + x;
+ for (int j = 0; j < putWidth; j++) {
+ data[index] = (byte)(pixels[i] & 0xFF);
+ i++;
+ srcX++;
+ if (srcX >= width) {
+ srcY++;
+ index = srcY * bytesPerLine;
+ srcX = 0;
+ } else {
+ index++;
+ }
+ }
+ return;
+
+ }
+ if (depth == 16) {
+ index = (y * bytesPerLine) + (x * 2);
+ for (int j = 0; j < putWidth; j++) {
+ pixel = pixels[i];
+ data[index] = (byte)(pixel & 0xFF);
+ data[index + 1] = (byte)((pixel >> 8) & 0xFF);
+ i++;
+ srcX++;
+ if (srcX >= width) {
+ srcY++;
+ index = srcY * bytesPerLine;
+ srcX = 0;
+ } else {
+ index += 2;
+ }
+ }
+ return;
+ }
+ if (depth == 24) {
+ index = (y * bytesPerLine) + (x * 3);
+ for (int j = 0; j < putWidth; j++) {
+ pixel = pixels[i];
+ data[index] = (byte)((pixel >> 16) & 0xFF);
+ data[index + 1] = (byte)((pixel >> 8) & 0xFF);
+ data[index + 2] = (byte)(pixel & 0xFF);
+ i++;
+ srcX++;
+ if (srcX >= width) {
+ srcY++;
+ index = srcY * bytesPerLine;
+ srcX = 0;
+ } else {
+ index += 3;
+ }
+ }
+ return;
+ }
+ if (depth == 32) {
+ index = (y * bytesPerLine) + (x * 4);
+ for (int j = 0; j < putWidth; j++) {
+ pixel = pixels[i];
+ data[index] = (byte)((pixel >> 24) & 0xFF);
+ data[index + 1] = (byte)((pixel >> 16) & 0xFF);
+ data[index + 2] = (byte)((pixel >> 8) & 0xFF);
+ data[index + 3] = (byte)(pixel & 0xFF);
+ i++;
+ srcX++;
+ if (srcX >= width) {
+ srcY++;
+ index = srcY * bytesPerLine;
+ srcX = 0;
+ } else {
+ index += 4;
+ }
+ }
+ return;
+ }
+ SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+}
+
+/**
+ * Returns a palette with 2 colors: black & white.
+ */
+static PaletteData bwPalette() {
+ return new PaletteData(new RGB[] {new RGB(0, 0, 0), new RGB(255, 255, 255)});
+}
+
+/**
+ * Blit operations.
+ */
+static final int BLIT_SRC = 1;
+static final int BLIT_ALPHA = 2;
+/**
+ * Byte and bit order constants.
+ */
+static final int MSB_FIRST = 1;
+static final int LSB_FIRST = 2;
+
+/**
+ * Masks for blitting.
+ */
+static final byte[] msbMasks1 = {
+ (byte)0x80, (byte)0x40, (byte)0x20, (byte)0x10,
+ (byte)0x08, (byte)0x04, (byte)0x02, (byte)0x01
+};
+static final byte[] lsbMasks1 = {
+ (byte)0x01, (byte)0x02, (byte)0x04, (byte)0x08,
+ (byte)0x10, (byte)0x20, (byte)0x40, (byte)0x80
+};
+static final byte[] msbInverseMasks1 = {
+ (byte)0x7F, (byte)0xBF, (byte)0xDF, (byte)0xEF,
+ (byte)0xF7, (byte)0xFB, (byte)0xFD, (byte)0xFE
+};
+static final byte[] lsbInverseMasks1 = {
+ (byte)0xFE, (byte)0xFD, (byte)0xFB, (byte)0xF7,
+ (byte)0xEF, (byte)0xDF, (byte)0xBF, (byte)0x7F
+};
+static final byte[] masks2 = {
+ (byte)0x03, (byte)0x0C, (byte)0x30, (byte)0xC0
+};
+static final byte[] inverseMasks2 = {
+ (byte)0xFC, (byte)0xF3, (byte)0xCF, (byte)0x3F
+};
+
+/**
+ * Gets the offset of the most significant bit for
+ * the given mask.
+ */
+static int getMSBOffset(int mask) {
+ for (int i = 31; i >= 0; i--) {
+ if (((mask >> i) & 0x1) != 0) return i + 1;
+ }
+ return 0;
+}
+
+/**
+ * Finds the closest match.
+ */
+static int closestMatch(int depth, byte red, byte green, byte blue, int redMask, int greenMask, int blueMask, byte[] reds, byte[] greens, byte[] blues) {
+ if (depth > 8) {
+ int rshift = 32 - getMSBOffset(redMask);
+ int gshift = 32 - getMSBOffset(greenMask);
+ int bshift = 32 - getMSBOffset(blueMask);
+ return (((red << 24) >>> rshift) & redMask) |
+ (((green << 24) >>> gshift) & greenMask) |
+ (((blue << 24) >>> bshift) & blueMask);
+ }
+ int r, g, b;
+ int minDistance = 0x7fffffff;
+ int nearestPixel = 0;
+ int n = reds.length;
+ for (int j = 0; j < n; j++) {
+ r = (reds[j] & 0xFF) - (red & 0xFF);
+ g = (greens[j] & 0xFF) - (green & 0xFF);
+ b = (blues[j] & 0xFF) - (blue & 0xFF);
+ int distance = r*r + g*g + b*b;
+ if (distance < minDistance) {
+ nearestPixel = j;
+ if (distance == 0) break;
+ minDistance = distance;
+ }
+ }
+ return nearestPixel;
+}
+
+/**
+ * Blits a direct palette image into a direct palette image.
+ */
+static void blit(int op, byte[] srcData, int srcDepth, int srcStride, int srcOrder, int srcX, int srcY, int srcWidth, int srcHeight, int srcRedMask, int srcGreenMask, int srcBlueMask, int srcGlobalAlpha, byte[] srcAlphaData, int srcAlphaStride, byte[] destData, int destDepth, int destStride, int destOrder, int destX, int destY, int destWidth, int destHeight, int destRedMask, int destGreenMask, int destBlueMask, boolean flipX, boolean flipY) {
+ int xs1, ys1, xs2, ys2, xd1, yd1, xd2, yd2;
+ int dyd, dys, ey, dy, dyd2, dys2, ys, yd;
+ short syd, sys;
+ int dxd, dxs, ex, dx, dxd2, dxs2;
+ short sxd, sxs, sas;
+ int sp, dp, sap = 0;
+ int sr = 0, sg = 0, sb = 0, sa = 0, dr = 0, dg = 0, db = 0, da = 0;
+ int srcPixel = 0, destPixel = 0;
+ short so0 = 0, so1 = 1, so2 = 2, so3 = 3;
+ short do0 = 0, do1 = 1, do2 = 2, do3 = 3;
+ int srcRedShift, srcGreenShift, srcBlueShift;
+ int destRedShift, destGreenShift, destBlueShift;
+
+ if (op == BLIT_SRC && srcDepth == destDepth &&
+ srcRedMask == destRedMask &&
+ srcGreenMask == destGreenMask &&
+ srcBlueMask == destBlueMask)
+ {
+ switch (srcDepth) {
+ case 16:
+ stretch16(srcData, srcStride, srcX, srcY, srcWidth, srcHeight, destData, destStride, destX, destY, destWidth, destHeight, flipX, flipY);
+ break;
+ case 24:
+ stretch24(srcData, srcStride, srcX, srcY, srcWidth, srcHeight, destData, destStride, destX, destY, destWidth, destHeight, flipX, flipY);
+ break;
+ case 32:
+ stretch32(srcData, srcStride, srcX, srcY, srcWidth, srcHeight, destData, destStride, destX, destY, destWidth, destHeight, flipX, flipY);
+ break;
+ }
+ return;
+ }
+
+ srcRedShift = 32 - getMSBOffset(srcRedMask);
+ srcGreenShift = 32 - getMSBOffset(srcGreenMask);
+ srcBlueShift = 32 - getMSBOffset(srcBlueMask);
+ destRedShift = 32 - getMSBOffset(destRedMask);
+ destGreenShift = 32 - getMSBOffset(destGreenMask);
+ destBlueShift = 32 - getMSBOffset(destBlueMask);
+ if (srcOrder == LSB_FIRST) {
+ switch (srcDepth) {
+ case 16: so0 = 1; so1 = 0; break;
+ case 24: so0 = 2; so1 = 1; so2 = 0; break;
+ case 32: so0 = 3; so1 = 2; so2 = 1; so3 = 0; break;
+ }
+ }
+ if (destOrder == LSB_FIRST) {
+ switch (destDepth) {
+ case 16: do0 = 1; do1 = 0; break;
+ case 24: do0 = 2; do1 = 1; do2 = 0; break;
+ case 32: do0 = 3; do1 = 2; do2 = 1; do3 = 0; break;
+ }
+ }
+
+ xs1 = srcX; xs2 = srcX + srcWidth - 1;
+ ys1 = srcY; ys2 = srcY + srcHeight - 1;
+ if (flipX) {
+ xd1 = destX + destWidth - 1;
+ xd2 = destX;
+ } else {
+ xd1 = destX;
+ xd2 = destX + destWidth - 1;
+ }
+ if (flipY) {
+ yd1 = destY + destHeight - 1;
+ yd2 = destY;
+ } else {
+ yd1 = destY;
+ yd2 = destY + destHeight - 1;
+ }
+
+ /* Y preliminary calculations */
+ dyd = yd2 - yd1;
+ if (dyd < 0) dyd = -dyd;
+ dys = ys2 - ys1;
+ if (dys < 0) dys = -dys;
+ dyd2 = dyd << 1;
+ dys2 = dys << 1;
+ syd = (short)((yd2 - yd1) > 0 ? 1 : -1);
+ sys = (short)((ys2 - ys1) > 0 ? 1 : -1);
+ ey = dys2 - dyd;
+ ys = ys1;
+ yd = yd1;
+ /* X preliminary calculations */
+ dxd = xd2 - xd1;
+ if (dxd < 0) dxd = -dxd;
+ dxs = xs2 - xs1;
+ if (dxs < 0) dxs = -dxs;
+ dxs2 = dxs << 1;
+ dxd2 = dxd << 1;
+ sxs = sas = (short)((xs2 - xs1) > 0 ? 1 : -1);
+ sxd = (short)((xd2 - xd1) > 0 ? 1 : -1);
+
+ sxs *= srcDepth / 8;
+ xs1 *= srcDepth / 8;
+ sxd *= destDepth / 8;
+ xd1 *= destDepth / 8;
+
+ if (srcGlobalAlpha != -1) srcAlphaData = null;
+ sa = srcGlobalAlpha;
+ for (dy = 0; dy <= dyd; dy++) {
+ /* X stretch starts here */
+ ex = dxs2 - dxd;
+ sp = ys * srcStride + xs1;
+ dp = yd * destStride + xd1;
+ if (srcAlphaData != null) sap = ys * srcAlphaStride + xs1;
+ for (dx = 0; dx < dxd; dx++) {
+ if (srcAlphaData != null) sa = srcAlphaData[sap] & 0xFF;
+ switch (srcDepth) {
+ case 16:
+ srcPixel = ((srcData[sp+so0] & 0xFF) << 8) | (srcData[sp+so1] & 0xFF);
+ break;
+ case 24:
+ srcPixel = ((srcData[sp+so0] & 0xFF) << 16) | ((srcData[sp+so1] & 0xFF) << 8) |
+ (srcData[sp+so2] & 0xFF);
+ break;
+ case 32:
+ srcPixel = ((srcData[sp+so0] & 0xFF) << 24) | ((srcData[sp+so1] & 0xFF) << 16) |
+ ((srcData[sp+so2] & 0xFF) << 8) | (srcData[sp+so3] & 0xFF);
+ break;
+ }
+ dr = sr = ((srcPixel & srcRedMask) << srcRedShift) >>> 24;
+ dg = sg = ((srcPixel & srcGreenMask) << srcGreenShift) >>> 24;
+ db = sb = ((srcPixel & srcBlueMask) << srcBlueShift) >>> 24;
+ if (op != BLIT_SRC) {
+ switch (destDepth) {
+ case 16:
+ destPixel = ((destData[dp+do0] & 0xFF) << 8) | (destData[dp+do1] & 0xFF);
+ break;
+ case 24:
+ destPixel = ((destData[dp+do0] & 0xFF) << 16) | ((destData[dp+do1] & 0xFF) << 8) |
+ (destData[dp+do2] & 0xFF);
+ break;
+ case 32:
+ destPixel = ((destData[dp+do0] & 0xFF) << 24) | ((destData[dp+do1] & 0xFF) << 16) |
+ ((destData[dp+do2] & 0xFF) << 8) | (destData[dp+do3] & 0xFF);
+ break;
+ }
+ dr = ((destPixel & destRedMask) << destRedShift) >>> 24;
+ dg = ((destPixel & destGreenMask) << destGreenShift) >>> 24;
+ db = ((destPixel & destBlueMask) << destBlueShift) >>> 24;
+ switch (op) {
+ case BLIT_ALPHA:
+ dr += (sr - dr) * sa / 255;
+ dg += (sg - dg) * sa / 255;
+ db += (sb - db) * sa / 255;
+ break;
+ }
+ }
+ destPixel =
+ (((dr << 24) >> destRedShift) & destRedMask) |
+ (((dg << 24) >> destGreenShift) & destGreenMask) |
+ (((db << 24) >> destBlueShift) & destBlueMask);
+ switch (destDepth) {
+ case 16:
+ destData[dp + do0] = (byte)((destPixel >> 8) & 0xFF);
+ destData[dp + do1] = (byte)(destPixel & 0xFF);
+ break;
+ case 24:
+ destData[dp + do0] = (byte)((destPixel >> 16) & 0xFF);
+ destData[dp + do1] = (byte)((destPixel >> 8) & 0xFF);
+ destData[dp + do2] = (byte)(destPixel & 0xFF);
+ break;
+ case 32:
+ destData[dp + do0] = (byte)((destPixel >> 24) & 0xFF);
+ destData[dp + do1] = (byte)((destPixel >> 16) & 0xFF);
+ destData[dp + do2] = (byte)((destPixel >> 8) & 0xFF);
+ destData[dp + do3] = (byte)(destPixel & 0xFF);
+ break;
+ }
+ while (ex >= 0) {
+ sp += sxs;
+ ex -= dxd2;
+ if (srcAlphaData != null) sap += sas;
+ }
+ dp += sxd;
+ ex += dxs2;
+ }
+
+ if (srcAlphaData != null) sa = srcAlphaData[sap] & 0xFF;
+ switch (srcDepth) {
+ case 16:
+ srcPixel = ((srcData[sp+so0] & 0xFF) << 8) | (srcData[sp+so1] & 0xFF);
+ break;
+ case 24:
+ srcPixel = ((srcData[sp+so0] & 0xFF) << 16) | ((srcData[sp+so1] & 0xFF) << 8) |
+ (srcData[sp+so2] & 0xFF);
+ break;
+ case 32:
+ srcPixel = ((srcData[sp+so0] & 0xFF) << 24) | ((srcData[sp+so1] & 0xFF) << 16) |
+ ((srcData[sp+so2] & 0xFF) << 8) | (srcData[sp+so3] & 0xFF);
+ break;
+ }
+ dr = sr = ((srcPixel & srcRedMask) << srcRedShift) >>> 24;
+ dg = sg = ((srcPixel & srcGreenMask) << srcGreenShift) >>> 24;
+ db = sb = ((srcPixel & srcBlueMask) << srcBlueShift) >>> 24;
+ if (op != BLIT_SRC) {
+ switch (destDepth) {
+ case 16:
+ destPixel = ((destData[dp+do0] & 0xFF) << 8) | (destData[dp+do1] & 0xFF);
+ break;
+ case 24:
+ destPixel = ((destData[dp+do0] & 0xFF) << 16) | ((destData[dp+do1] & 0xFF) << 8) |
+ (destData[dp+do2] & 0xFF);
+ break;
+ case 32:
+ destPixel = ((destData[dp+do0] & 0xFF) << 24) | ((destData[dp+do1] & 0xFF) << 16) |
+ ((destData[dp+do2] & 0xFF) << 8) | (destData[dp+do3] & 0xFF);
+ break;
+ }
+ dr = ((destPixel & destRedMask) << destRedShift) >>> 24;
+ dg = ((destPixel & destGreenMask) << destGreenShift) >>> 24;
+ db = ((destPixel & destBlueMask) << destBlueShift) >>> 24;
+ switch (op) {
+ case BLIT_ALPHA:
+ dr += (sr - dr) * sa / 255;
+ dg += (sg - dg) * sa / 255;
+ db += (sb - db) * sa / 255;
+ break;
+ }
+ }
+ destPixel =
+ (((dr << 24) >> destRedShift) & destRedMask) |
+ (((dg << 24) >> destGreenShift) & destGreenMask) |
+ (((db << 24) >> destBlueShift) & destBlueMask);
+ switch (destDepth) {
+ case 16:
+ destData[dp + do0] = (byte)((destPixel >> 8) & 0xFF);
+ destData[dp + do1] = (byte)(destPixel & 0xFF);
+ break;
+ case 24:
+ destData[dp + do0] = (byte)((destPixel >> 16) & 0xFF);
+ destData[dp + do1] = (byte)((destPixel >> 8) & 0xFF);
+ destData[dp + do2] = (byte)(destPixel & 0xFF);
+ break;
+ case 32:
+ destData[dp + do0] = (byte)((destPixel >> 24) & 0xFF);
+ destData[dp + do1] = (byte)((destPixel >> 16) & 0xFF);
+ destData[dp + do2] = (byte)((destPixel >> 8) & 0xFF);
+ destData[dp + do3] = (byte)(destPixel & 0xFF);
+ break;
+ }
+ /* X stretch ends here */
+ if (dy == dyd)
+ break;
+ while (ey >= 0) {
+ ys += sys;
+ ey -= dyd2;
+ }
+ yd += syd;
+ ey += dys2;
+ }
+}
+
+/**
+ * Blits an index palette image into a direct palette image.
+ */
+static void blit(int op, byte[] srcData, int srcDepth, int srcStride, int srcOrder, int srcX, int srcY, int srcWidth, int srcHeight, byte[] srcReds, byte[] srcGreens, byte[] srcBlues, int srcGlobalAlpha, byte[] srcAlphaData, int srcAlphaStride, byte[] destData, int destDepth, int destStride, int destOrder, int destX, int destY, int destWidth, int destHeight, int destRedMask, int destGreenMask, int destBlueMask, boolean flipX, boolean flipY) {
+ int xs1, ys1, xs2, ys2, xd1, yd1, xd2, yd2;
+ int dyd, dys, ey, dy, dyd2, dys2, ys, yd;
+ short syd, sys;
+ int dxd, dxs, ex, dx, dxd2, dxs2, xs;
+ short sxd, sxs, sas;
+ int sp, dp, sap = 0;
+ int sr = 0, sg = 0, sb = 0, sa = 0, dr = 0, dg = 0, db = 0, da = 0;
+ int srcPixel = 0, destPixel = 0;
+ short do0 = 0, do1 = 1, do2 = 2, do3 = 3;
+ int destRedShift, destGreenShift, destBlueShift;
+ int i, offset = 0;
+ byte[] srcMasks = null;
+ int srcN = 1 << srcDepth;
+ int[] mapping = null;
+
+ destRedShift = 32 - getMSBOffset(destRedMask);
+ destGreenShift = 32 - getMSBOffset(destGreenMask);
+ destBlueShift = 32 - getMSBOffset(destBlueMask);
+ if (srcReds != null && srcN > srcReds.length) srcN = srcReds.length;
+ if (op == BLIT_SRC) {
+ mapping = new int[srcN];
+ for (i = 0; i < srcN; i++) {
+ dr = srcReds[i] & 0xFF;
+ dg = srcGreens[i] & 0xFF;
+ db = srcBlues[i] & 0xFF;
+ mapping[i] =
+ (((dr << 24) >>> destRedShift) & destRedMask) |
+ (((dg << 24) >>> destGreenShift) & destGreenMask) |
+ (((db << 24) >>> destBlueShift) & destBlueMask);
+ }
+ }
+ switch (srcDepth) {
+ case 1: srcMasks = msbMasks1; break;
+ case 2: srcMasks = masks2; break;
+ }
+ if (srcOrder == LSB_FIRST) {
+ switch (srcDepth) {
+ case 1: srcMasks = lsbMasks1; break;
+ }
+ }
+ if (destOrder == LSB_FIRST) {
+ switch (destDepth) {
+ case 16: do0 = 1; do1 = 0; break;
+ case 24: do0 = 2; do1 = 1; do2 = 0; break;
+ case 32: do0 = 3; do1 = 2; do2 = 1; do3 = 0; break;
+ }
+ }
+
+ xs1 = srcX; xs2 = srcX + srcWidth - 1;
+ ys1 = srcY; ys2 = srcY + srcHeight - 1;
+ if (flipX) {
+ xd1 = destX + destWidth - 1;
+ xd2 = destX;
+ } else {
+ xd1 = destX;
+ xd2 = destX + destWidth - 1;
+ }
+ if (flipY) {
+ yd1 = destY + destHeight - 1;
+ yd2 = destY;
+ } else {
+ yd1 = destY;
+ yd2 = destY + destHeight - 1;
+ }
+
+ /* Y preliminary calculations */
+ dyd = yd2 - yd1;
+ if (dyd < 0) dyd = -dyd;
+ dys = ys2 - ys1;
+ if (dys < 0) dys = -dys;
+ dyd2 = dyd << 1;
+ dys2 = dys << 1;
+ syd = (short)((yd2 - yd1) > 0 ? 1 : -1);
+ sys = (short)((ys2 - ys1) > 0 ? 1 : -1);
+ ey = dys2 - dyd;
+ ys = ys1;
+ yd = yd1;
+ /* X preliminary calculations */
+ dxd = xd2 - xd1;
+ if (dxd < 0) dxd = -dxd;
+ dxs = xs2 - xs1;
+ if (dxs < 0) dxs = -dxs;
+ dxs2 = dxs << 1;
+ dxd2 = dxd << 1;
+ sxs = sas = (short)((xs2 - xs1) > 0 ? 1 : -1);
+ sxd = (short)((xd2 - xd1) > 0 ? 1 : -1);
+
+ sxd *= destDepth / 8;
+ xd1 *= destDepth / 8;
+
+ if (srcGlobalAlpha != -1) srcAlphaData = null;
+ sa = srcGlobalAlpha;
+ for (dy = 0; dy <= dyd; dy++) {
+ /* X stretch starts here */
+ offset = 3 - (srcX % 4);
+ ex = dxs2 - dxd;
+ xs = xs1;
+ sp = ys * srcStride;
+ dp = yd * destStride + xd1;
+ if (srcAlphaData != null) sap = ys * srcAlphaStride + xs1;
+ for (dx = 0; dx < dxd; dx++) {
+ if (srcAlphaData != null) sa = srcAlphaData[sap] & 0xFF;
+ switch (srcDepth) {
+ case 1:
+ srcPixel = (srcData[sp + (xs >> 3)] & srcMasks[xs & 7]) == 0 ? 0 : 1;
+ break;
+ case 2:
+ srcPixel = ((srcData[sp + (xs >> 2)] & srcMasks[offset]) & 0xFF) >> (offset * 2);
+ break;
+ case 4:
+ srcPixel = srcData[sp + (xs >> 1)] & 0xFF;
+ if ((xs & 0x1) == 0) {
+ srcPixel = srcPixel >> 4;
+ } else {
+ srcPixel = srcPixel & 0x0F;
+ }
+ break;
+ case 8:
+ srcPixel = srcData[sp + xs] & 0xFF;
+ break;
+ }
+ if (mapping != null) {
+ destPixel = mapping[srcPixel];
+ } else {
+ dr = sr = srcReds[srcPixel] & 0xFF;
+ dg = sg = srcGreens[srcPixel] & 0xFF;
+ db = sb = srcBlues[srcPixel] & 0xFF;
+ if (op != BLIT_SRC) {
+ switch (destDepth) {
+ case 16:
+ destPixel = ((destData[dp+do0] & 0xFF) << 8) | (destData[dp+do1] & 0xFF);
+ break;
+ case 24:
+ destPixel = ((destData[dp+do0] & 0xFF) << 16) | ((destData[dp+do1] & 0xFF) << 8) |
+ (destData[dp+do2] & 0xFF);
+ break;
+ case 32:
+ destPixel = ((destData[dp+do0] & 0xFF) << 24) | ((destData[dp+do1] & 0xFF) << 16) |
+ ((destData[dp+do2] & 0xFF) << 8) | (destData[dp+do3] & 0xFF);
+ break;
+ }
+ dr = ((destPixel & destRedMask) << destRedShift) >>> 24;
+ dg = ((destPixel & destGreenMask) << destGreenShift) >>> 24;
+ db = ((destPixel & destBlueMask) << destBlueShift) >>> 24;
+ switch (op) {
+ case BLIT_ALPHA:
+ dr += (sr - dr) * sa / 255;
+ dg += (sg - dg) * sa / 255;
+ db += (sb - db) * sa / 255;
+ break;
+ }
+ }
+ destPixel =
+ (((dr << 24) >>> destRedShift) & destRedMask) |
+ (((dg << 24) >>> destGreenShift) & destGreenMask) |
+ (((db << 24) >>> destBlueShift) & destBlueMask);
+ }
+ switch (destDepth) {
+ case 16:
+ destData[dp + do0] = (byte)((destPixel >> 8) & 0xFF);
+ destData[dp + do1] = (byte)(destPixel & 0xFF);
+ break;
+ case 24:
+ destData[dp + do0] = (byte)((destPixel >> 16) & 0xFF);
+ destData[dp + do1] = (byte)((destPixel >> 8) & 0xFF);
+ destData[dp + do2] = (byte)(destPixel & 0xFF);
+ break;
+ case 32:
+ destData[dp + do0] = (byte)((destPixel >> 24) & 0xFF);
+ destData[dp + do1] = (byte)((destPixel >> 16) & 0xFF);
+ destData[dp + do2] = (byte)((destPixel >> 8) & 0xFF);
+ destData[dp + do3] = (byte)(destPixel & 0xFF);
+ break;
+ }
+ while (ex >= 0) {
+ xs += sxs;
+ ex -= dxd2;
+ if (srcAlphaData != null) sap += sas;
+ }
+ dp += sxd;
+ ex += dxs2;
+ if (offset == 0) {
+ offset = 3;
+ } else {
+ offset--;
+ }
+ }
+
+ if (srcAlphaData != null) sa = srcAlphaData[sap] & 0xFF;
+ switch (srcDepth) {
+ case 1:
+ srcPixel = (srcData[sp + (xs >> 3)] & srcMasks[xs & 7]) == 0 ? 0 : 1;
+ break;
+ case 2:
+ srcPixel = ((srcData[sp + (xs >> 2)] & srcMasks[offset]) & 0xFF) >> (offset * 2);
+ break;
+ case 4:
+ srcPixel = srcData[sp + (xs >> 1)] & 0xFF;
+ if ((xs & 0x1) == 0) {
+ srcPixel = srcPixel >> 4;
+ } else {
+ srcPixel = srcPixel & 0x0F;
+ }
+ break;
+ case 8:
+ srcPixel = srcData[sp + xs] & 0xFF;
+ break;
+ }
+ if (mapping != null) {
+ destPixel = mapping[srcPixel];
+ } else {
+ dr = sr = srcReds[srcPixel] & 0xFF;
+ dg = sg = srcGreens[srcPixel] & 0xFF;
+ db = sb = srcBlues[srcPixel] & 0xFF;
+ if (op != BLIT_SRC) {
+ switch (destDepth) {
+ case 16:
+ destPixel = ((destData[dp+do0] & 0xFF) << 8) | (destData[dp+do1] & 0xFF);
+ break;
+ case 24:
+ destPixel = ((destData[dp+do0] & 0xFF) << 16) | ((destData[dp+do1] & 0xFF) << 8) |
+ (destData[dp+do2] & 0xFF);
+ break;
+ case 32:
+ destPixel = ((destData[dp+do0] & 0xFF) << 24) | ((destData[dp+do1] & 0xFF) << 16) |
+ ((destData[dp+do2] & 0xFF) << 8) | (destData[dp+do3] & 0xFF);
+ break;
+ }
+ dr = ((destPixel & destRedMask) << destRedShift) >>> 24;
+ dg = ((destPixel & destGreenMask) << destGreenShift) >>> 24;
+ db = ((destPixel & destBlueMask) << destBlueShift) >>> 24;
+ switch (op) {
+ case BLIT_ALPHA:
+ dr += (sr - dr) * sa / 255;
+ dg += (sg - dg) * sa / 255;
+ db += (sb - db) * sa / 255;
+ break;
+ }
+ }
+ destPixel =
+ (((dr << 24) >>> destRedShift) & destRedMask) |
+ (((dg << 24) >>> destGreenShift) & destGreenMask) |
+ (((db << 24) >>> destBlueShift) & destBlueMask);
+ }
+ switch (destDepth) {
+ case 16:
+ destData[dp + do0] = (byte)((destPixel >> 8) & 0xFF);
+ destData[dp + do1] = (byte)(destPixel & 0xFF);
+ break;
+ case 24:
+ destData[dp + do0] = (byte)((destPixel >> 16) & 0xFF);
+ destData[dp + do1] = (byte)((destPixel >> 8) & 0xFF);
+ destData[dp + do2] = (byte)(destPixel & 0xFF);
+ break;
+ case 32:
+ destData[dp + do0] = (byte)((destPixel >> 24) & 0xFF);
+ destData[dp + do1] = (byte)((destPixel >> 16) & 0xFF);
+ destData[dp + do2] = (byte)((destPixel >> 8) & 0xFF);
+ destData[dp + do3] = (byte)(destPixel & 0xFF);
+ break;
+ }
+ /* X stretch ends here */
+ if (dy == dyd)
+ break;
+ while (ey >= 0) {
+ ys += sys;
+ ey -= dyd2;
+ }
+ yd += syd;
+ ey += dys2;
+ }
+}
+
+/**
+ * Blits an index palette image into an index palette image.
+ */
+static void blit(int op, byte[] srcData, int srcDepth, int srcStride, int srcOrder, int srcX, int srcY, int srcWidth, int srcHeight, byte[] srcReds, byte[] srcGreens, byte[] srcBlues, int srcGlobalAlpha, byte[] srcAlphaData, int srcAlphaStride, byte[] destData, int destDepth, int destStride, int destOrder, int destX, int destY, int destWidth, int destHeight, byte[] destReds, byte[] destGreens, byte[] destBlues, boolean flipX, boolean flipY) {
+ int xs1, ys1, xs2, ys2, xd1, yd1, xd2, yd2;
+ int dyd, dys, ey, dy, dyd2, dys2, ys, yd;
+ short syd, sys;
+ int dxd, dxs, ex, dx, dxd2, dxs2, xs, xd;
+ short sxd, sxs, sas;
+ int sp, dp, sap = 0;
+ int sr = 0, sg = 0, sb = 0, sa = 0, dr = 0, dg = 0, db = 0, da = 0;
+ int srcPixel = 0, destPixel = 0;
+ int i, j, offset = 0;
+ byte[] srcMasks = null, destMasks = null, destInverseMasks = null;
+ int destN = 1 << destDepth, srcN = 1 << srcDepth;
+ int r, g, b, nearestPixel = 0, lastPixel = -1;
+ int distance, minDistance;
+ int[] mapping = null;
+ boolean samePalette = srcReds == destReds && srcGreens == destGreens && srcBlues == srcBlues;
+ boolean sameAsSrc = op == BLIT_SRC && samePalette && srcDepth <= destDepth;
+
+ if (srcReds != null && srcN > srcReds.length) srcN = srcReds.length;
+ if (destReds != null && destN > destReds.length) destN = destReds.length;
+ if (op == BLIT_SRC && srcReds != null) {
+ mapping = new int[srcN];
+ for (i = 0; i < srcN; i++) {
+ minDistance = 0x7FFFFFFF;
+ nearestPixel = 0;
+ for (j = 0; j < destN; j++) {
+ r = (destReds[j] & 0xFF) - (srcReds[i] & 0xFF);
+ g = (destGreens[j] & 0xFF) - (srcGreens[i] & 0xFF);
+ b = (destBlues[j] & 0xFF) - (srcBlues[i] & 0xFF);
+ distance = r*r + g*g + b*b;
+ if (distance < minDistance) {
+ nearestPixel = j;
+ if (distance == 0) break;
+ minDistance = distance;
+ }
+ }
+ mapping[i] = nearestPixel;
+ }
+ }
+ if (op == BLIT_SRC && srcDepth == destDepth && (mapping != null || samePalette))
+ {
+ switch (srcDepth) {
+ case 1:
+ stretch1(srcData, srcStride, srcOrder, srcX, srcY, srcWidth, srcHeight, destData, destStride, destOrder, destX, destY, destWidth, destHeight, flipX, flipY);
+ break;
+ case 2:
+ stretch2(srcData, srcStride, srcX, srcY, srcWidth, srcHeight, destData, destStride, destX, destY, destWidth, destHeight, mapping, flipX, flipY);
+ break;
+ case 4:
+ stretch4(srcData, srcStride, srcX, srcY, srcWidth, srcHeight, destData, destStride, destX, destY, destWidth, destHeight, mapping, flipX, flipY);
+ break;
+ case 8:
+ stretch8(srcData, srcStride, srcX, srcY, srcWidth, srcHeight, destData, destStride, destX, destY, destWidth, destHeight, mapping, flipX, flipY);
+ break;
+ }
+ return;
+ }
+ switch (srcDepth) {
+ case 1: srcMasks = msbMasks1; break;
+ case 2: srcMasks = masks2; break;
+ }
+ switch (destDepth) {
+ case 1: destMasks = msbMasks1; destInverseMasks = msbInverseMasks1; break;
+ case 2: destMasks = masks2; destInverseMasks = inverseMasks2; break;
+ }
+ if (srcOrder == LSB_FIRST) {
+ switch (srcDepth) {
+ case 1: srcMasks = lsbMasks1; break;
+ }
+ }
+ if (destOrder == LSB_FIRST) {
+ switch (destDepth) {
+ case 1: destMasks = lsbMasks1; destInverseMasks = lsbInverseMasks1; break;
+ }
+ }
+
+ xs1 = srcX; xs2 = srcX + srcWidth - 1;
+ ys1 = srcY; ys2 = srcY + srcHeight - 1;
+ if (flipX) {
+ xd1 = destX + destWidth - 1;
+ xd2 = destX;
+ } else {
+ xd1 = destX;
+ xd2 = destX + destWidth - 1;
+ }
+ if (flipY) {
+ yd1 = destY + destHeight - 1;
+ yd2 = destY;
+ } else {
+ yd1 = destY;
+ yd2 = destY + destHeight - 1;
+ }
+
+ /* Y preliminary calculations */
+ dyd = yd2 - yd1;
+ if (dyd < 0) dyd = -dyd;
+ dys = ys2 - ys1;
+ if (dys < 0) dys = -dys;
+ dyd2 = dyd << 1;
+ dys2 = dys << 1;
+ syd = (short)((yd2 - yd1) > 0 ? 1 : -1);
+ sys = (short)((ys2 - ys1) > 0 ? 1 : -1);
+ ey = dys2 - dyd;
+ ys = ys1;
+ yd = yd1;
+ /* X preliminary calculations */
+ dxd = xd2 - xd1;
+ if (dxd < 0) dxd = -dxd;
+ dxs = xs2 - xs1;
+ if (dxs < 0) dxs = -dxs;
+ dxs2 = dxs << 1;
+ dxd2 = dxd << 1;
+ sxs = sas = (short)((xs2 - xs1) > 0 ? 1 : -1);
+ sxd = (short)((xd2 - xd1) > 0 ? 1 : -1);
+
+ if (srcGlobalAlpha != -1) srcAlphaData = null;
+ sa = srcGlobalAlpha;
+ for (dy = 0; dy <= dyd; dy++) {
+ /* X stretch starts here */
+ offset = 3 - (srcX % 4);
+ ex = dxs2 - dxd;
+ xs = xs1;
+ xd = xd1;
+ sp = ys * srcStride;
+ dp = yd * destStride;
+ if (srcAlphaData != null) sap = ys * srcAlphaStride;
+ for (dx = 0; dx < dxd; dx++) {
+ if (srcAlphaData != null) sa = srcAlphaData[sap] & 0xFF;
+ switch (srcDepth) {
+ case 1:
+ srcPixel = (srcData[sp + (xs >> 3)] & srcMasks[xs & 7]) == 0 ? 0 : 1;
+ break;
+ case 2:
+ srcPixel = ((srcData[sp + (xs >> 2)] & srcMasks[offset]) & 0xFF) >> (offset * 2);
+ break;
+ case 4:
+ srcPixel = srcData[sp + (xs >> 1)] & 0xFF;
+ if ((xs & 0x1) == 0) {
+ srcPixel = srcPixel >> 4;
+ } else {
+ srcPixel = srcPixel & 0x0F;
+ }
+ break;
+ case 8:
+ srcPixel = srcData[sp + xs] & 0xFF;
+ break;
+ }
+ if (mapping != null) {
+ destPixel = mapping[srcPixel];
+ } else if (sameAsSrc) {
+ destPixel = srcPixel;
+ } else {
+ dr = sr = srcReds[srcPixel] & 0xFF;
+ dg = sg = srcGreens[srcPixel] & 0xFF;
+ db = sb = srcBlues[srcPixel] & 0xFF;
+ if (op != BLIT_SRC) {
+ switch (destDepth) {
+ case 1:
+ destPixel = (destData[dp + (xd >> 3)] & destMasks[xd & 7]) == 0 ? 0 : 1;
+ break;
+ case 2:
+ destPixel = ((destData[dp + (xd >> 2)] & destMasks[offset]) & 0xFF) >> (offset * 2);
+ break;
+ case 4:
+ destPixel = destData[dp + (xd >> 1)] & 0xFF;
+ if ((xs & 0x1) == 0) {
+ destPixel = destPixel >> 4;
+ } else {
+ destPixel = destPixel & 0x0F;
+ }
+ break;
+ case 8:
+ destPixel = destData[dp + xd] & 0xFF;
+ break;
+ }
+ dr = destReds[destPixel] & 0xFF;
+ dg = destGreens[destPixel] & 0xFF;
+ db = destBlues[destPixel] & 0xFF;
+ switch (op) {
+ case BLIT_ALPHA:
+ dr += (sr - dr) * sa / 255;
+ dg += (sg - dg) * sa / 255;
+ db += (sb - db) * sa / 255;
+ break;
+ }
+ }
+ if (lastPixel == -1 || lastPixel != srcPixel) {
+ minDistance = 0x7FFFFFFF;
+ nearestPixel = 0;
+ for (j = 0; j < destN; j++) {
+ r = (destReds[j] & 0xFF) - dr;
+ g = (destGreens[j] & 0xFF) - dg;
+ b = (destBlues[j] & 0xFF) - db;
+ distance = r*r + g*g + b*b;
+ if (distance < minDistance) {
+ nearestPixel = j;
+ if (distance == 0) break;
+ minDistance = distance;
+ }
+ }
+ lastPixel = srcPixel;
+ }
+ destPixel = nearestPixel;
+ }
+ switch (destDepth) {
+ case 1:
+ if ((destPixel & 0x1) == 1) {
+ destData[dp + (xd >> 3)] |= destInverseMasks[xd & 7];
+ } else {
+ destData[dp + (xd >> 3)] &= destInverseMasks[xd & 7] ^ -1;
+ }
+ break;
+ case 2:
+ destData[dp + (xd >> 2)] = (byte)((destData[dp + (xd >> 2)] & destInverseMasks[offset]) | (destPixel << (offset * 2)));
+ break;
+ case 4:
+ if ((xd & 0x1) == 0) {
+ destData[dp + (xd >> 1)] = (byte)((destData[dp + (xd >> 1)] & 0x0F) | ((destPixel & 0x0F) << 4));
+ } else {
+ destData[dp + (xd >> 1)] = (byte)((destData[dp + (xd >> 1)] & 0xF0) | (destPixel & 0x0F));
+ }
+ break;
+ case 8:
+ destData[dp + xd] = (byte)(destPixel & 0xFF);
+ break;
+ }
+ while (ex >= 0) {
+ xs += sxs;
+ ex -= dxd2;
+ if (srcAlphaData != null) sap += sas;
+ }
+ xd += sxd;
+ ex += dxs2;
+ if (offset == 0) {
+ offset = 3;
+ } else {
+ offset--;
+ }
+ }
+
+ if (srcAlphaData != null) sa = srcAlphaData[sap] & 0xFF;
+ switch (srcDepth) {
+ case 1:
+ srcPixel = (srcData[sp + (xs >> 3)] & srcMasks[xs & 7]) == 0 ? 0 : 1;
+ break;
+ case 2:
+ srcPixel = ((srcData[sp + (xs >> 2)] & srcMasks[offset]) & 0xFF) >> (offset * 2);
+ break;
+ case 4:
+ srcPixel = srcData[sp + (xs >> 1)] & 0xFF;
+ if ((xs & 0x1) == 0) {
+ srcPixel = srcPixel >> 4;
+ } else {
+ srcPixel = srcPixel & 0x0F;
+ }
+ break;
+ case 8:
+ srcPixel = srcData[sp + xs] & 0xFF;
+ break;
+ }
+ if (mapping != null) {
+ destPixel = mapping[srcPixel];
+ } else if (sameAsSrc) {
+ destPixel = srcPixel;
+ } else {
+ dr = sr = srcReds[srcPixel] & 0xFF;
+ dg = sg = srcGreens[srcPixel] & 0xFF;
+ db = sb = srcBlues[srcPixel] & 0xFF;
+ if (op != BLIT_SRC) {
+ switch (destDepth) {
+ case 1:
+ destPixel = (destData[dp + (xd >> 3)] & destMasks[xd & 7]) == 0 ? 0 : 1;
+ break;
+ case 2:
+ destPixel = ((destData[dp + (xd >> 2)] & destMasks[offset]) & 0xFF) >> (offset * 2);
+ break;
+ case 4:
+ destPixel = destData[dp + (xd >> 1)] & 0xFF;
+ if ((xs & 0x1) == 0) {
+ destPixel = destPixel >> 4;
+ } else {
+ destPixel = destPixel & 0x0F;
+ }
+ break;
+ case 8:
+ destPixel = destData[dp + xd] & 0xFF;
+ break;
+ }
+ dr = destReds[destPixel] & 0xFF;
+ dg = destGreens[destPixel] & 0xFF;
+ db = destBlues[destPixel] & 0xFF;
+ switch (op) {
+ case BLIT_ALPHA:
+ dr += (sr - dr) * sa / 255;
+ dg += (sg - dg) * sa / 255;
+ db += (sb - db) * sa / 255;
+ break;
+ }
+ }
+ if (lastPixel == -1 || lastPixel != srcPixel) {
+ minDistance = 0x7FFFFFFF;
+ nearestPixel = 0;
+ for (j = 0; j < destN; j++) {
+ r = (destReds[j] & 0xFF) - dr;
+ g = (destGreens[j] & 0xFF) - dg;
+ b = (destBlues[j] & 0xFF) - db;
+ distance = r*r + g*g + b*b;
+ if (distance < minDistance) {
+ nearestPixel = j;
+ if (distance == 0) break;
+ minDistance = distance;
+ }
+ }
+ lastPixel = srcPixel;
+ }
+ destPixel = nearestPixel;
+ }
+ switch (destDepth) {
+ case 1:
+ if ((destPixel & 0x1) == 1) {
+ destData[dp + (xd >> 3)] |= destInverseMasks[xd & 7];
+ } else {
+ destData[dp + (xd >> 3)] &= destInverseMasks[xd & 7] ^ -1;
+ }
+ break;
+ case 2:
+ destData[dp + (xd >> 2)] = (byte)((destData[dp + (xd >> 2)] & destInverseMasks[offset]) | (destPixel << (offset * 2)));
+ break;
+ case 4:
+ if ((xd & 0x1) == 0) {
+ destData[dp + (xd >> 1)] = (byte)((destData[dp + (xd >> 1)] & 0x0F) | ((destPixel & 0x0F) << 4));
+ } else {
+ destData[dp + (xd >> 1)] = (byte)((destData[dp + (xd >> 1)] & 0xF0) | (destPixel & 0x0F));
+ }
+ break;
+ case 8:
+ destData[dp + xd] = (byte)(destPixel & 0xFF);
+ break;
+ }
+ /* X stretch ends here */
+ if (dy == dyd)
+ break;
+ while (ey >= 0) {
+ ys += sys;
+ ey -= dyd2;
+ }
+ yd += syd;
+ ey += dys2;
+ }
+}
+
+/**
+ * Blits a direct palette image into an index palette image.
+ */
+static void blit(int op, byte[] srcData, int srcDepth, int srcStride, int srcOrder, int srcX, int srcY, int srcWidth, int srcHeight, int srcRedMask, int srcGreenMask, int srcBlueMask, int srcGlobalAlpha, byte[] srcAlphaData, int srcAlphaStride, byte[] destData, int destDepth, int destStride, int destOrder, int destX, int destY, int destWidth, int destHeight, byte[] destReds, byte[] destGreens, byte[] destBlues, boolean flipX, boolean flipY) {
+ int xs1, ys1, xs2, ys2, xd1, yd1, xd2, yd2;
+ int dyd, dys, ey, dy, dyd2, dys2, ys, yd;
+ short syd, sys;
+ int dxd, dxs, ex, dx, dxd2, dxs2, xd;
+ short sxd, sxs, sas;
+ int sp, dp, sap = 0;
+ int sr = 0, sg = 0, sb = 0, sa = 0, dr = 0, dg = 0, db = 0, da = 0;
+ int srcPixel = 0, destPixel = 0;
+ short so0 = 0, so1 = 1, so2 = 2, so3 = 3;
+ int srcRedShift, srcGreenShift, srcBlueShift;
+ int j, offset = 0;
+ byte[] destMasks = null, destInverseMasks = null;
+ int destN = 1 << destDepth;
+ int r, g, b, nearestPixel = 0, lastPixel = -1;
+ int distance, minDistance;
+
+ srcRedShift = 32 - getMSBOffset(srcRedMask);
+ srcGreenShift = 32 - getMSBOffset(srcGreenMask);
+ srcBlueShift = 32 - getMSBOffset(srcBlueMask);
+ if (destReds != null && destN > destReds.length) destN = destReds.length;
+ switch (destDepth) {
+ case 1: destMasks = msbMasks1; destInverseMasks = msbInverseMasks1; break;
+ case 2: destMasks = masks2; destInverseMasks = inverseMasks2; break;
+ }
+ if (srcOrder == LSB_FIRST) {
+ switch (srcDepth) {
+ case 16: so0 = 1; so1 = 0; break;
+ case 24: so0 = 2; so1 = 1; so2 = 0; break;
+ case 32: so0 = 3; so1 = 2; so2 = 1; so3 = 0; break;
+ }
+ }
+ if (destOrder == LSB_FIRST) {
+ switch (destDepth) {
+ case 1: destMasks = lsbMasks1; destInverseMasks = lsbInverseMasks1; break;
+ }
+ }
+
+ xs1 = srcX; xs2 = srcX + srcWidth - 1;
+ ys1 = srcY; ys2 = srcY + srcHeight - 1;
+ if (flipX) {
+ xd1 = destX + destWidth - 1;
+ xd2 = destX;
+ } else {
+ xd1 = destX;
+ xd2 = destX + destWidth - 1;
+ }
+ if (flipY) {
+ yd1 = destY + destHeight - 1;
+ yd2 = destY;
+ } else {
+ yd1 = destY;
+ yd2 = destY + destHeight - 1;
+ }
+
+ /* Y preliminary calculations */
+ dyd = yd2 - yd1;
+ if (dyd < 0) dyd = -dyd;
+ dys = ys2 - ys1;
+ if (dys < 0) dys = -dys;
+ dyd2 = dyd << 1;
+ dys2 = dys << 1;
+ syd = (short)((yd2 - yd1) > 0 ? 1 : -1);
+ sys = (short)((ys2 - ys1) > 0 ? 1 : -1);
+ ey = dys2 - dyd;
+ ys = ys1;
+ yd = yd1;
+ /* X preliminary calculations */
+ dxd = xd2 - xd1;
+ if (dxd < 0) dxd = -dxd;
+ dxs = xs2 - xs1;
+ if (dxs < 0) dxs = -dxs;
+ dxs2 = dxs << 1;
+ dxd2 = dxd << 1;
+ sxs = sas = (short)((xs2 - xs1) > 0 ? 1 : -1);
+ sxd = (short)((xd2 - xd1) > 0 ? 1 : -1);
+
+ sxs *= srcDepth / 8;
+ xs1 *= srcDepth / 8;
+
+ if (srcGlobalAlpha != -1) srcAlphaData = null;
+ sa = srcGlobalAlpha;
+ for (dy = 0; dy <= dyd; dy++) {
+ /* X stretch starts here */
+ offset = 3 - (srcX % 4);
+ ex = dxs2 - dxd;
+ xd = xd1;
+ sp = ys * srcStride + xs1;
+ dp = yd * destStride;
+ if (srcAlphaData != null) sap = ys * srcAlphaStride + xs1;
+ for (dx = 0; dx < dxd; dx++) {
+ if (srcAlphaData != null) sa = srcAlphaData[sap] & 0xFF;
+ switch (srcDepth) {
+ case 16:
+ srcPixel = ((srcData[sp+so0] & 0xFF) << 8) | (srcData[sp+so1] & 0xFF);
+ break;
+ case 24:
+ srcPixel = ((srcData[sp+so0] & 0xFF) << 16) | ((srcData[sp+so1] & 0xFF) << 8) |
+ (srcData[sp+so2] & 0xFF);
+ break;
+ case 32:
+ srcPixel = ((srcData[sp+so0] & 0xFF) << 24) | ((srcData[sp+so1] & 0xFF) << 16) |
+ ((srcData[sp+so2] & 0xFF) << 8) | (srcData[sp+so3] & 0xFF);
+ break;
+ }
+ dr = sr = ((srcPixel & srcRedMask) << srcRedShift) >>> 24;
+ dg = sg = ((srcPixel & srcGreenMask) << srcGreenShift) >>> 24;
+ db = sb = ((srcPixel & srcBlueMask) << srcBlueShift) >>> 24;
+ if (op != BLIT_SRC) {
+ switch (destDepth) {
+ case 1:
+ destPixel = (destData[dp + (xd >> 3)] & destMasks[xd & 7]) == 0 ? 0 : 1;
+ break;
+ case 2:
+ destPixel = ((destData[dp + (xd >> 2)] & destMasks[offset]) & 0xFF) >> (offset * 2);
+ break;
+ case 4:
+ destPixel = destData[dp + (xd >> 1)] & 0xFF;
+ if ((xd & 0x1) == 0) {
+ destPixel = destPixel >> 4;
+ } else {
+ destPixel = destPixel & 0x0F;
+ }
+ break;
+ case 8:
+ destPixel = destData[dp + xd] & 0xFF;
+ break;
+ }
+ dr = destReds[destPixel] & 0xFF;
+ dg = destGreens[destPixel] & 0xFF;
+ db = destBlues[destPixel] & 0xFF;
+ switch (op) {
+ case BLIT_ALPHA:
+ dr += (sr - dr) * sa / 255;
+ dg += (sg - dg) * sa / 255;
+ db += (sb - db) * sa / 255;
+ break;
+ }
+ }
+ if (lastPixel == -1 || lastPixel != srcPixel) {
+ minDistance = 0x7FFFFFFF;
+ nearestPixel = 0;
+ for (j = 0; j < destN; j++) {
+ r = (destReds[j] & 0xFF) - dr;
+ g = (destGreens[j] & 0xFF) - dg;
+ b = (destBlues[j] & 0xFF) - db;
+ distance = r*r + g*g + b*b;
+ if (distance < minDistance) {
+ nearestPixel = j;
+ if (distance == 0) break;
+ minDistance = distance;
+ }
+ }
+ lastPixel = srcPixel;
+ }
+ destPixel = nearestPixel;
+ switch (destDepth) {
+ case 1:
+ if ((destPixel & 0x1) == 1) {
+ destData[dp + (xd >> 3)] |= destInverseMasks[xd & 7];
+ } else {
+ destData[dp + (xd >> 3)] &= destInverseMasks[xd & 7] ^ -1;
+ }
+ break;
+ case 2:
+ destData[dp + (xd >> 2)] = (byte)((destData[dp + (xd >> 2)] & destInverseMasks[offset]) | (destPixel << (offset * 2)));
+ break;
+ case 4:
+ if ((xd & 0x1) == 0) {
+ destData[dp + (xd >> 1)] = (byte)((destData[dp + (xd >> 1)] & 0x0F) | ((destPixel & 0x0F) << 4));
+ } else {
+ destData[dp + (xd >> 1)] = (byte)((destData[dp + (xd >> 1)] & 0xF0) | (destPixel & 0x0F));
+ }
+ break;
+ case 8:
+ destData[dp + xd] = (byte)(destPixel & 0xFF);
+ break;
+ }
+ while (ex >= 0) {
+ sp += sxs;
+ ex -= dxd2;
+ if (srcAlphaData != null) sap += sas;
+ }
+ xd += sxd;
+ ex += dxs2;
+ if (offset == 0) {
+ offset = 3;
+ } else {
+ offset--;
+ }
+ }
+
+ if (srcAlphaData != null) sa = srcAlphaData[sap] & 0xFF;
+ switch (srcDepth) {
+ case 16:
+ srcPixel = ((srcData[sp+so0] & 0xFF) << 8) | (srcData[sp+so1] & 0xFF);
+ break;
+ case 24:
+ srcPixel = ((srcData[sp+so0] & 0xFF) << 16) | ((srcData[sp+so1] & 0xFF) << 8) |
+ (srcData[sp+so2] & 0xFF);
+ break;
+ case 32:
+ srcPixel = ((srcData[sp+so0] & 0xFF) << 24) | ((srcData[sp+so1] & 0xFF) << 16) |
+ ((srcData[sp+so2] & 0xFF) << 8) | (srcData[sp+so3] & 0xFF);
+ break;
+ }
+ dr = sr = ((srcPixel & srcRedMask) << srcRedShift) >>> 24;
+ dg = sg = ((srcPixel & srcGreenMask) << srcGreenShift) >>> 24;
+ db = sb = ((srcPixel & srcBlueMask) << srcBlueShift) >>> 24;
+ if (op != BLIT_SRC) {
+ switch (destDepth) {
+ case 1:
+ destPixel = (destData[dp + (xd >> 3)] & destMasks[xd & 7]) == 0 ? 0 : 1;
+ break;
+ case 2:
+ destPixel = ((destData[dp + (xd >> 2)] & destMasks[offset]) & 0xFF) >> (offset * 2);
+ break;
+ case 4:
+ destPixel = destData[dp + (xd >> 1)] & 0xFF;
+ if ((xd & 0x1) == 0) {
+ destPixel = destPixel >> 4;
+ } else {
+ destPixel = destPixel & 0x0F;
+ }
+ break;
+ case 8:
+ destPixel = destData[dp + xd] & 0xFF;
+ break;
+ }
+ dr = destReds[destPixel] & 0xFF;
+ dg = destGreens[destPixel] & 0xFF;
+ db = destBlues[destPixel] & 0xFF;
+ switch (op) {
+ case BLIT_ALPHA:
+ dr += (sr - dr) * sa / 255;
+ dg += (sg - dg) * sa / 255;
+ db += (sb - db) * sa / 255;
+ break;
+ }
+ }
+ if (lastPixel == -1 || lastPixel != srcPixel) {
+ minDistance = 0x7FFFFFFF;
+ nearestPixel = 0;
+ for (j = 0; j < destN; j++) {
+ r = (destReds[j] & 0xFF) - dr;
+ g = (destGreens[j] & 0xFF) - dg;
+ b = (destBlues[j] & 0xFF) - db;
+ distance = r*r + g*g + b*b;
+ if (distance < minDistance) {
+ nearestPixel = j;
+ if (distance == 0) break;
+ minDistance = distance;
+ }
+ }
+ lastPixel = srcPixel;
+ }
+ destPixel = nearestPixel;
+ switch (destDepth) {
+ case 1:
+ if ((destPixel & 0x1) == 1) {
+ destData[dp + (xd >> 3)] |= destInverseMasks[xd & 7];
+ } else {
+ destData[dp + (xd >> 3)] &= destInverseMasks[xd & 7] ^ -1;
+ }
+ break;
+ case 2:
+ destData[dp + (xd >> 2)] = (byte)((destData[dp + (xd >> 2)] & destInverseMasks[offset]) | (destPixel << (offset * 2)));
+ break;
+ case 4:
+ if ((xd & 0x1) == 0) {
+ destData[dp + (xd >> 1)] = (byte)((destData[dp + (xd >> 1)] & 0x0F) | ((destPixel & 0x0F) << 4));
+ } else {
+ destData[dp + (xd >> 1)] = (byte)((destData[dp + (xd >> 1)] & 0xF0) | (destPixel & 0x0F));
+ }
+ break;
+ case 8:
+ destData[dp + xd] = (byte)(destPixel & 0xFF);
+ break;
+ }
+ /* X stretch ends here */
+ if (dy == dyd)
+ break;
+ while (ey >= 0) {
+ ys += sys;
+ ey -= dyd2;
+ }
+ yd += syd;
+ ey += dys2;
+ }
+}
+
+/**
+ * Stretches the source, a 1-bit image, into the destination, a 1-bit image.
+ */
+static void stretch1(byte[] srcData, int srcStride, int srcOrder, int srcX, int srcY, int srcWidth, int srcHeight, byte[] destData, int destStride, int destOrder, int destX, int destY, int destWidth, int destHeight, boolean flipX, boolean flipY) {
+ int xs1, ys1, xs2, ys2, xd1, yd1, xd2, yd2;
+ int dyd, dys, ey, dy, dyd2, dys2, ys, yd;
+ short syd, sys;
+ int dxd, dxs, ex, dx, dxd2, dxs2, xs, xd;
+ short sxd, sxs;
+ byte pixel;
+ int sp, dp;
+ byte[] masks, inverseMasks;
+
+ if (srcOrder == LSB_FIRST) {
+ masks = lsbMasks1;
+ } else {
+ masks = msbMasks1;
+ }
+ if (destOrder == LSB_FIRST) {
+ inverseMasks = lsbInverseMasks1;
+ } else {
+ inverseMasks = msbInverseMasks1;
+ }
+
+ xs1 = srcX; xs2 = srcX + srcWidth - 1;
+ ys1 = srcY; ys2 = srcY + srcHeight - 1;
+ if (flipX) {
+ xd1 = destX + destWidth - 1;
+ xd2 = destX;
+ } else {
+ xd1 = destX;
+ xd2 = destX + destWidth - 1;
+ }
+ if (flipY) {
+ yd1 = destY + destHeight - 1;
+ yd2 = destY;
+ } else {
+ yd1 = destY;
+ yd2 = destY + destHeight - 1;
+ }
+
+ /* Y preliminary calculations */
+ dyd = yd2 - yd1;
+ if (dyd < 0) dyd = -dyd;
+ dys = ys2 - ys1;
+ if (dys < 0) dys = -dys;
+ dyd2 = dyd << 1;
+ dys2 = dys << 1;
+ syd = (short)((yd2 - yd1) > 0 ? 1 : -1);
+ sys = (short)((ys2 - ys1) > 0 ? 1 : -1);
+ ey = dys2 - dyd;
+ ys = ys1;
+ yd = yd1;
+ /* X preliminary calculations */
+ dxd = xd2 - xd1;
+ if (dxd < 0) dxd = -dxd;
+ dxs = xs2 - xs1;
+ if (dxs < 0) dxs = -dxs;
+ dxd2 = dxd << 1;
+ dxs2 = dxs << 1;
+ sxd = (short)((xd2 - xd1) > 0 ? 1 : -1);
+ sxs = (short)((xs2 - xs1) > 0 ? 1 : -1);
+
+ for (dy = 0; dy <= dyd; dy++) {
+ /* X stretch starts here */
+ ex = dxs2 - dxd;
+ xs = xs1;
+ xd = xd1;
+ sp = ys * srcStride;
+ dp = yd * destStride;
+ pixel = (byte)(srcData[sp + (xs >> 3)] & masks[xs & 7]);
+ for (dx = 0; dx < dxd; dx++) {
+ if (pixel != 0)
+ destData[dp + (xd >> 3)] |= masks[xd & 7];
+ else
+ destData[dp + (xd >> 3)] &= inverseMasks[xd & 7];
+ if (ex >= 0) {
+ do {
+ xs += sxs;
+ ex -= dxd2;
+ } while (ex >= 0);
+ pixel = (byte)(srcData[sp + (xs >> 3)] & masks[xs & 7]);
+ }
+ xd += sxd;
+ ex += dxs2;
+ }
+ if (pixel != 0)
+ destData[dp + (xd >> 3)] |= masks[xd & 7];
+ else
+ destData[dp + (xd >> 3)] &= inverseMasks[xd & 7];
+ /* X stretch ends here */
+ if (dy == dyd)
+ break;
+ while (ey >= 0) {
+ ys += sys;
+ ey -= dyd2;
+ }
+ yd += syd;
+ ey += dys2;
+ }
+}
+
+/**
+ * Stretches the source, a 16-bit image, into the destination, a 16-bit image.
+ * The images are assumed to have the same red, green, and blue masks.
+ *
+ * Untested - would need an X server with the same red, green and blue
+ * masks as the file has, namely, 0x7C00, 0x3E0, 0x1F. Most 16-bit X servers
+ * have masks of 0xF800, 0x7E0, 0x1F.
+ */
+static void stretch16(byte[] srcData, int srcStride, int srcX, int srcY, int srcWidth, int srcHeight, byte[] destData, int destStride, int destX, int destY, int destWidth, int destHeight, boolean flipX, boolean flipY) {
+ int xs1, ys1, xs2, ys2, xd1, yd1, xd2, yd2;
+ int dyd, dys, ey, dy, dyd2, dys2, yd, ys;
+ short syd, sys;
+ int dxd, dxs, ex, dx, dxd2, dxs2, xs, xd;
+ short sxd, sxs;
+ byte pixel0, pixel1;
+ int sp, dp;
+
+ xs1 = srcX; xs2 = srcX + srcWidth - 1;
+ ys1 = srcY; ys2 = srcY + srcHeight - 1;
+ if (flipX) {
+ xd1 = destX + destWidth - 1;
+ xd2 = destX;
+ } else {
+ xd1 = destX;
+ xd2 = destX + destWidth - 1;
+ }
+ if (flipY) {
+ yd1 = destY + destHeight - 1;
+ yd2 = destY;
+ } else {
+ yd1 = destY;
+ yd2 = destY + destHeight - 1;
+ }
+
+ /* Y preliminary calculations */
+ dyd = yd2 - yd1;
+ if (dyd < 0) dyd = -dyd;
+ dys = ys2 - ys1;
+ if (dys < 0) dys = -dys;
+ dyd2 = dyd << 1;
+ dys2 = dys << 1;
+ syd = (short)((yd2 - yd1) > 0 ? 1 : -1);
+ sys = (short)((ys2 - ys1) > 0 ? 1 : -1);
+ ey = dys2 - dyd;
+ ys = ys1;
+ yd = yd1;
+ /* X preliminary calculations */
+ dxd = xd2 - xd1;
+ if (dxd < 0) dxd = -dxd;
+ dxs = xs2 - xs1;
+ if (dxs < 0) dxs = -dxs;
+ dxd2 = dxd << 1;
+ dxs2 = dxs << 1;
+ sxd = (short)((xd2 - xd1) > 0 ? 1 : -1);
+ sxs = (short)((xs2 - xs1) > 0 ? 1 : -1);
+
+ for (dy = 0; dy <= dyd; dy++) {
+ /* X stretch starts here */
+ ex = dxs2 - dxd;
+ xs = xs1;
+ xd = xd1;
+ sp = ys * srcStride;
+ dp = yd * destStride;
+ pixel0 = srcData[sp + xs];
+ pixel1 = srcData[sp + xs + 1];
+ for (dx = 0; dx < dxd; dx++) {
+ destData[dp + xd] = pixel0;
+ destData[dp + xd + 1] = pixel1;
+ if (ex >= 0) {
+ do {
+ xs += (sxs << 1);
+ ex -= dxd2;
+ } while (ex >= 0);
+ pixel0 = srcData[sp + xs];
+ pixel1 = srcData[sp + xs + 1];
+ }
+ xd += (sxd << 1);
+ ex += dxs2;
+ }
+ destData[dp + xd] = pixel0;
+ destData[dp + xd + 1] = pixel1;
+ /* X stretch ends here */
+ if (dy == dyd)
+ break;
+ while (ey >= 0) {
+ ys += sys;
+ ey -= dyd2;
+ }
+ yd += syd;
+ ey += dys2;
+ }
+}
+
+/**
+ * Stretches the source, a 2-bit image, into the destination, a 2-bit image.
+ */
+static void stretch2(byte[] srcData, int srcStride, int srcX, int srcY, int srcWidth, int srcHeight, byte[] destData, int destStride, int destX, int destY, int destWidth, int destHeight, int[] mapping, boolean flipX, boolean flipY) {
+ int xs1, ys1, xs2, ys2, xd1, yd1, xd2, yd2;
+ int dyd, dys, ey, dy, dyd2, dys2, yd, ys;
+ short syd, sys;
+ int dxd, dxs, ex, dx, dxd2, dxs2, xs, xd;
+ short sxd, sxs;
+ byte pixel;
+ int sp, dp, x;
+ byte [] masks = { (byte)0x03, (byte)0x0C, (byte)0x30, (byte)0xC0 };
+ byte [] inverseMasks = { (byte)0xFC, (byte)0xF3, (byte)0xCF, (byte)0x3F };
+
+ xs1 = srcX; xs2 = srcX + srcWidth - 1;
+ ys1 = srcY; ys2 = srcY + srcHeight - 1;
+ if (flipX) {
+ xd1 = destX + destWidth - 1;
+ xd2 = destX;
+ } else {
+ xd1 = destX;
+ xd2 = destX + destWidth - 1;
+ }
+ if (flipY) {
+ yd1 = destY + destHeight - 1;
+ yd2 = destY;
+ } else {
+ yd1 = destY;
+ yd2 = destY + destHeight - 1;
+ }
+
+ /* Y preliminary calculations */
+ dyd = yd2 - yd1;
+ if (dyd < 0) dyd = -dyd;
+ dys = ys2 - ys1;
+ if (dys < 0) dys = -dys;
+ dyd2 = dyd << 1;
+ dys2 = dys << 1;
+ syd = (short)((yd2 - yd1) > 0 ? 1 : -1);
+ sys = (short)((ys2 - ys1) > 0 ? 1 : -1);
+ ey = dys2 - dyd;
+ ys = ys1;
+ yd = yd1;
+ /* X preliminary calculations */
+ dxd = xd2 - xd1;
+ if (dxd < 0) dxd = -dxd;
+ dxs = xs2 - xs1;
+ if (dxs < 0) dxs = -dxs;
+ dxd2 = dxd << 1;
+ dxs2 = dxs << 1;
+ sxd = (short)((xd2 - xd1) > 0 ? 1 : -1);
+ sxs = (short)((xs2 - xs1) > 0 ? 1 : -1);
+
+ for (dy = 0; dy <= dyd; dy++) {
+ /* X stretch starts here */
+ int offset = 3 - (srcX % 4);
+ ex = dxs2 - dxd;
+ xs = xs1;
+ xd = xd1;
+ sp = ys * srcStride;
+ dp = yd * destStride;
+ x = (byte)(((srcData[sp + (xs >> 2)] & masks[offset]) & 0xFF) >> (offset * 2));
+ pixel = (byte)(mapping == null ? x : mapping[x]);
+ for (dx = 0; dx < dxd; dx++) {
+ destData[dp + (xd >> 2)] = (byte)((destData[dp + (xd >> 2)] & inverseMasks[offset]) | (pixel << (offset * 2)));
+ if (ex >= 0) {
+ do {
+ xs += sxs;
+ ex -= dxd2;
+ } while (ex >= 0);
+ x = (byte)(((srcData[sp + (xs >> 2)] & masks[offset]) & 0xFF) >> (offset * 2));
+ pixel = (byte)(mapping == null ? x : mapping[x]);
+ }
+ xd += sxd;
+ ex += dxs2;
+ if (offset == 0) {
+ offset = 3;
+ } else {
+ offset--;
+ }
+ }
+ destData[dp + (xd >> 2)] = (byte)((destData[dp + (xd >> 2)] & inverseMasks[offset]) | (pixel << (offset * 2)));
+ /* X stretch ends here */
+ if (dy == dyd)
+ break;
+ while (ey >= 0) {
+ ys += sys;
+ ey -= dyd2;
+ }
+ yd += syd;
+ ey += dys2;
+ }
+}
+
+/**
+ * Stretches the source, a 24-bit image, into the destination, a 24-bit image.
+ * The images must have the same red, green, and blue masks.
+ * The image are assumed to have 24 bits per pixel; many 24-bit images
+ * use 32 bits per pixel.
+ *
+ * Untested. Would require an X server with a depth of 24 which has 24 bits per
+ * pixel. Most X servers with depth 24 actually have 32 bits per pixel.
+ */
+static void stretch24(byte[] srcData, int srcStride, int srcX, int srcY, int srcWidth, int srcHeight, byte[] destData, int destStride, int destX, int destY, int destWidth, int destHeight, boolean flipX, boolean flipY) {
+ int xs1, ys1, xs2, ys2, xd1, yd1, xd2, yd2;
+ int dyd, dys, ey, dy, dyd2, dys2, ys, yd;
+ short syd, sys;
+ int dxd, dxs, ex, dx, dxd2, dxs2;
+ short sxd, sxs;
+ byte r, g, b;
+ int sp, dp;
+
+ xs1 = srcX; xs2 = srcX + srcWidth - 1;
+ ys1 = srcY; ys2 = srcY + srcHeight - 1;
+ if (flipX) {
+ xd1 = destX + destWidth - 1;
+ xd2 = destX;
+ } else {
+ xd1 = destX;
+ xd2 = destX + destWidth - 1;
+ }
+ if (flipY) {
+ yd1 = destY + destHeight - 1;
+ yd2 = destY;
+ } else {
+ yd1 = destY;
+ yd2 = destY + destHeight - 1;
+ }
+
+ /* Y preliminary calculations */
+ dyd = yd2 - yd1;
+ if (dyd < 0) dyd = -dyd;
+ dys = ys2 - ys1;
+ if (dys < 0) dys = -dys;
+ dyd2 = dyd << 1;
+ dys2 = dys << 1;
+ syd = (short)((yd2 - yd1) > 0 ? 1 : -1);
+ sys = (short)((ys2 - ys1) > 0 ? 1 : -1);
+ ey = dys2 - dyd;
+ ys = ys1;
+ yd = yd1;
+ /* X preliminary calculations */
+ dxd = xd2 - xd1;
+ if (dxd < 0) dxd = -dxd;
+ dxs = xs2 - xs1;
+ if (dxs < 0) dxs = -dxs;
+ dxd2 = dxd << 1;
+ dxs2 = dxs << 1;
+ sxd = (short)((xd2 - xd1) > 0 ? 3 : -3);
+ sxs = (short)((xs2 - xs1) > 0 ? 3 : -3);
+ xs1 *= 3;
+ xd1 *= 3;
+
+ for (dy = 0; dy <= dyd; dy++) {
+ /* X stretch starts here */
+ ex = dxs2 - dxd;
+ sp = ys * srcStride + xs1;
+ dp = yd * destStride + xd1;
+ r = srcData[sp];
+ g = srcData[sp + 1];
+ b = srcData[sp + 2];
+ for (dx = 0; dx < dxd; dx++) {
+ destData[dp] = r;
+ destData[dp + 1] = g;
+ destData[dp + 2] = b;
+ if (ex >= 0) {
+ while (ex >= 0) {
+ sp += sxs;
+ ex -= dxd2;
+ }
+ r = srcData[sp];
+ g = srcData[sp + 1];
+ b = srcData[sp + 2];
+ }
+ dp += sxd;
+ ex += dxs2;
+ }
+ destData[dp] = r;
+ destData[dp + 1] = g;
+ destData[dp + 2] = b;
+ /* X stretch ends here */
+ if (dy == dyd)
+ break;
+ while (ey >= 0) {
+ ys += sys;
+ ey -= dyd2;
+ }
+ yd += syd;
+ ey += dys2;
+ }
+}
+
+/**
+ * Stretches the source, a 32-bit image, into the destination, a 32-bit image.
+ * The images must have the same red, green, and blue masks.
+ */
+static void stretch32(byte[] srcData, int srcStride, int srcX, int srcY, int srcWidth, int srcHeight, byte[] destData, int destStride, int destX, int destY, int destWidth, int destHeight, boolean flipX, boolean flipY) {
+ int xs1, ys1, xs2, ys2, xd1, yd1, xd2, yd2;
+ int dyd, dys, ey, dy, dyd2, dys2, ys, yd;
+ short syd, sys;
+ int dxd, dxs, ex, dx, dxd2, dxs2;
+ short sxd, sxs;
+ byte r, g, b, a;
+ int sp, dp;
+
+ xs1 = srcX; xs2 = srcX + srcWidth - 1;
+ ys1 = srcY; ys2 = srcY + srcHeight - 1;
+ if (flipX) {
+ xd1 = destX + destWidth - 1;
+ xd2 = destX;
+ } else {
+ xd1 = destX;
+ xd2 = destX + destWidth - 1;
+ }
+ if (flipY) {
+ yd1 = destY + destHeight - 1;
+ yd2 = destY;
+ } else {
+ yd1 = destY;
+ yd2 = destY + destHeight - 1;
+ }
+
+ /* Y preliminary calculations */
+ dyd = yd2 - yd1;
+ if (dyd < 0) dyd = -dyd;
+ dys = ys2 - ys1;
+ if (dys < 0) dys = -dys;
+ dyd2 = dyd << 1;
+ dys2 = dys << 1;
+ syd = (short)((yd2 - yd1) > 0 ? 1 : -1);
+ sys = (short)((ys2 - ys1) > 0 ? 1 : -1);
+ ey = dys2 - dyd;
+ ys = ys1;
+ yd = yd1;
+ /* X preliminary calculations */
+ dxd = xd2 - xd1;
+ if (dxd < 0) dxd = -dxd;
+ dxs = xs2 - xs1;
+ if (dxs < 0) dxs = -dxs;
+ dxd2 = dxd << 1;
+ dxs2 = dxs << 1;
+ sxd = (short)((xd2 - xd1) > 0 ? 4 : -4);
+ sxs = (short)((xs2 - xs1) > 0 ? 4 : -4);
+ xs1 *= 4;
+ xd1 *= 4;
+
+ for (dy = 0; dy <= dyd; dy++) {
+ /* X stretch starts here */
+ ex = dxs2 - dxd;
+ sp = ys * srcStride + xs1;
+ dp = yd * destStride + xd1;
+ r = srcData[sp];
+ g = srcData[sp + 1];
+ b = srcData[sp + 2];
+ a = srcData[sp + 3];
+ for (dx = 0; dx < dxd; dx++) {
+ destData[dp] = r;
+ destData[dp + 1] = g;
+ destData[dp + 2] = b;
+ destData[dp + 3] = a;
+ if (ex >= 0) {
+ while (ex >= 0) {
+ sp += sxs;
+ ex -= dxd2;
+ }
+ r = srcData[sp];
+ g = srcData[sp + 1];
+ b = srcData[sp + 2];
+ a = srcData[sp + 3];
+ }
+ dp += sxd;
+ ex += dxs2;
+ }
+ destData[dp] = r;
+ destData[dp + 1] = g;
+ destData[dp + 2] = b;
+ destData[dp + 3] = a;
+ /* X stretch ends here */
+ if (dy == dyd)
+ break;
+ while (ey >= 0) {
+ ys += sys;
+ ey -= dyd2;
+ }
+ yd += syd;
+ ey += dys2;
+ }
+}
+
+/**
+ * Stretches the source, a 4-bit image, into the destination, a 4-bit image.
+ */
+static void stretch4(byte[] srcData, int srcStride, int srcX, int srcY, int srcWidth, int srcHeight, byte[] destData, int destStride, int destX, int destY, int destWidth, int destHeight, int[] mapping, boolean flipX, boolean flipY) {
+ int xs1, ys1, xs2, ys2, xd1, yd1, xd2, yd2;
+ int dyd, dys, ey, dy, dyd2, dys2, yd, ys;
+ short syd, sys;
+ int dxd, dxs, ex, dx, dxd2, dxs2, xs, xd;
+ short sxd, sxs;
+ byte pixel;
+ int sp, dp;
+
+ xs1 = srcX; xs2 = srcX + srcWidth - 1;
+ ys1 = srcY; ys2 = srcY + srcHeight - 1;
+ if (flipX) {
+ xd1 = destX + destWidth - 1;
+ xd2 = destX;
+ } else {
+ xd1 = destX;
+ xd2 = destX + destWidth - 1;
+ }
+ if (flipY) {
+ yd1 = destY + destHeight - 1;
+ yd2 = destY;
+ } else {
+ yd1 = destY;
+ yd2 = destY + destHeight - 1;
+ }
+
+ /* Y preliminary calculations */
+ dyd = yd2 - yd1;
+ if (dyd < 0) dyd = -dyd;
+ dys = ys2 - ys1;
+ if (dys < 0) dys = -dys;
+ dyd2 = dyd << 1;
+ dys2 = dys << 1;
+ syd = (short)((yd2 - yd1) > 0 ? 1 : -1);
+ sys = (short)((ys2 - ys1) > 0 ? 1 : -1);
+ ey = dys2 - dyd;
+ ys = ys1;
+ yd = yd1;
+ /* X preliminary calculations */
+ dxd = xd2 - xd1;
+ if (dxd < 0) dxd = -dxd;
+ dxs = xs2 - xs1;
+ if (dxs < 0) dxs = -dxs;
+ dxd2 = dxd << 1;
+ dxs2 = dxs << 1;
+ sxd = (short)((xd2 - xd1) > 0 ? 1 : -1);
+ sxs = (short)((xs2 - xs1) > 0 ? 1 : -1);
+
+ for (dy = 0; dy <= dyd; dy++) {
+ /* X stretch starts here */
+ ex = dxs2 - dxd;
+ xs = xs1;
+ xd = xd1;
+ sp = ys * srcStride;
+ dp = yd * destStride;
+ int x = srcData[sp + (xs >> 1)];
+ if ((xs & 1) != 0) {
+ pixel = (byte)((mapping == null) ? (x & 0x0F) : (mapping[x & 0x0F] & 0x0F));
+ } else {
+ pixel = (byte)((mapping == null) ? (x >> 4) : (mapping[x >> 4] & 0x0F));
+ }
+ for (dx = 0; dx < dxd; dx++) {
+ if ((xd & 1) != 0)
+ destData[dp + (xd >> 1)] = (byte)((destData[dp + (xd >> 1)] & 0xF0) | pixel);
+ else
+ destData[dp + (xd >> 1)] = (byte)((destData[dp + (xd >> 1)] & 0x0F) | (pixel << 4));
+ if (ex >= 0) {
+ do {
+ xs += sxs;
+ ex -= dxd2;
+ } while (ex >= 0);
+ x = srcData[sp + (xs >> 1)];
+ if ((xd & 1) != 0) {
+ pixel = (byte)((mapping == null) ? (x & 0x0F) : (mapping[x & 0x0F] & 0x0F));
+ } else {
+ pixel = (byte)((mapping == null) ? ((x >> 4) & 0x0F) : (mapping[x >> 4] & 0x0F));
+ }
+ }
+ xd += sxd;
+ ex += dxs2;
+ }
+ if ((xd & 1) != 0)
+ destData[dp + (xd >> 1)] = (byte)((destData[dp + (xd >> 1)] & 0xF0) | pixel);
+ else
+ destData[dp + (xd >> 1)] = (byte)((destData[dp + (xd >> 1)] & 0x0F) | (pixel << 4));
+ /* X stretch ends here */
+ if (dy == dyd)
+ break;
+ while (ey >= 0) {
+ ys += sys;
+ ey -= dyd2;
+ }
+ yd += syd;
+ ey += dys2;
+ }
+}
+
+/**
+ * Stretches the source, an 8-bit image, into the destination, an 8-bit image.
+ */
+static void stretch8(byte[] srcData, int srcStride, int srcX, int srcY, int srcWidth, int srcHeight, byte[] destData, int destStride, int destX, int destY, int destWidth, int destHeight, int[] mapping, boolean flipX, boolean flipY) {
+ int xs1, ys1, xs2, ys2, xd1, yd1, xd2, yd2;
+ int dyd, dys, ey, dy, dyd2, dys2, yd, ys;
+ short syd, sys;
+ int dxd, dxs, ex, dx, dxd2, dxs2, xs, xd;
+ short sxd, sxs;
+ byte pixel;
+ int sp, dp, x;
+
+ xs1 = srcX; xs2 = srcX + srcWidth - 1;
+ ys1 = srcY; ys2 = srcY + srcHeight - 1;
+ if (flipX) {
+ xd1 = destX + destWidth - 1;
+ xd2 = destX;
+ } else {
+ xd1 = destX;
+ xd2 = destX + destWidth - 1;
+ }
+ if (flipY) {
+ yd1 = destY + destHeight - 1;
+ yd2 = destY;
+ } else {
+ yd1 = destY;
+ yd2 = destY + destHeight - 1;
+ }
+
+ /* Y preliminary calculations */
+ dyd = yd2 - yd1;
+ if (dyd < 0) dyd = -dyd;
+ dys = ys2 - ys1;
+ if (dys < 0) dys = -dys;
+ dyd2 = dyd << 1;
+ dys2 = dys << 1;
+ syd = (short)((yd2 - yd1) > 0 ? 1 : -1);
+ sys = (short)((ys2 - ys1) > 0 ? 1 : -1);
+ ey = dys2 - dyd;
+ ys = ys1;
+ yd = yd1;
+ /* X preliminary calculations */
+ dxd = xd2 - xd1;
+ if (dxd < 0) dxd = -dxd;
+ dxs = xs2 - xs1;
+ if (dxs < 0) dxs = -dxs;
+ dxd2 = dxd << 1;
+ dxs2 = dxs << 1;
+ sxd = (short)((xd2 - xd1) > 0 ? 1 : -1);
+ sxs = (short)((xs2 - xs1) > 0 ? 1 : -1);
+
+ for (dy = 0; dy <= dyd; dy++) {
+ /* X stretch starts here */
+ ex = dxs2 - dxd;
+ xs = xs1;
+ xd = xd1;
+ sp = ys * srcStride;
+ dp = yd * destStride;
+ x = srcData[sp + xs] & 0xFF;
+ pixel = (byte)(mapping == null ? x : mapping[x]);
+ for (dx = 0; dx < dxd; dx++) {
+ destData[dp + xd] = pixel;
+ if (ex >= 0) {
+ do {
+ xs += sxs;
+ ex -= dxd2;
+ } while (ex >= 0);
+ x = srcData[sp + xs] & 0xFF;
+ pixel = (byte)(mapping == null ? x : mapping[x]);
+ }
+ xd += sxd;
+ ex += dxs2;
+ }
+ destData[dp + xd] = pixel;
+ /* X stretch ends here */
+ if (dy == dyd)
+ break;
+ while (ey >= 0) {
+ ys += sys;
+ ey -= dyd2;
+ }
+ yd += syd;
+ ey += dys2;
+ }
+}
+
+}
+
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageLoader.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageLoader.java
new file mode 100755
index 0000000000..c76db0d497
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageLoader.java
@@ -0,0 +1,284 @@
+package org.eclipse.swt.graphics;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2000 All Rights Reserved
+ */
+
+import java.io.*;
+import java.util.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.image.*;
+
+/**
+ * Instances of this class are used to load images from,
+ * and save images to, a file or stream.
+ * <p>
+ * Currently supported image formats are:
+ * </p><ul>
+ * <li>BMP (Windows Bitmap)</li>
+ * <li>ICO (Windows Icon)</li>
+ * <li>JPEG</li>
+ * <li>GIF</li>
+ * <li>PNG</li>
+ * </ul>
+ * <code>ImageLoaders</code> can be used to:
+ * <ul>
+ * <li>load/save single images in all formats</li>
+ * <li>load/save multiple images (GIF/ICO)</li>
+ * <li>load/save animated GIF images</li>
+ * <li>load interlaced GIF/PNG images</li>
+ * <li>load progressive JPEG images</li>
+ * </ul>
+ */
+
+public class ImageLoader {
+
+ /**
+ * the array of ImageData objects in this ImageLoader.
+ * This array is read in when the load method is called,
+ * and it is written out when the save method is called
+ */
+ public ImageData[] data;
+
+ /**
+ * the width of the logical screen on which the images
+ * reside, in pixels (this corresponds to the GIF89a
+ * Logical Screen Width value)
+ */
+ public int logicalScreenWidth;
+
+ /**
+ * the height of the logical screen on which the images
+ * reside, in pixels (this corresponds to the GIF89a
+ * Logical Screen Height value)
+ */
+ public int logicalScreenHeight;
+
+ /**
+ * the background pixel for the logical screen (this
+ * corresponds to the GIF89a Background Color Index value).
+ * The default is -1 which means 'unspecified background'
+ *
+ */
+ public int backgroundPixel;
+
+ /**
+ * the number of times to repeat the display of a sequence
+ * of animated images (this corresponds to the commonly-used
+ * GIF application extension for "NETSCAPE 2.0 01")
+ */
+ public int repeatCount;
+
+ /*
+ * the set of ImageLoader event listeners, created on demand
+ */
+ Vector imageLoaderListeners;
+
+/**
+ * Construct a new empty ImageLoader.
+ */
+public ImageLoader() {
+ reset();
+}
+
+/**
+ * Resets the fields of the ImageLoader, except for the
+ * <code>imageLoaderListeners</code> field.
+ */
+void reset() {
+ data = null;
+ logicalScreenWidth = 0;
+ logicalScreenHeight = 0;
+ backgroundPixel = -1;
+ repeatCount = 1;
+}
+
+/**
+ * Loads an array of <code>ImageData</code> objects from the
+ * specified input stream. Throws an error if either an error
+ * occurs while loading the images, or if the images are not
+ * of a supported type. Returns the loaded image data array.
+ *
+ * @param stream the input stream to load the images from
+ * @return an array of <code>ImageData</code> objects loaded from the specified input stream
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the stream is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_INVALID_IMAGE - if the image file contains invalid data</li>
+ * <li>ERROR_IO - if an input/output error occurs while reading data</li>
+ * </ul>
+ */
+public ImageData[] load(InputStream stream) {
+ if (stream == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ reset();
+ data = FileFormat.load(stream, this);
+ return data;
+}
+
+/**
+ * Loads an array of <code>ImageData</code> objects from the
+ * file with the specified name. Throws an error if either
+ * an error occurs while loading the images, or if the images are
+ * not of a supported type. Returns the loaded image data array.
+ *
+ * @param filename the name of the file to load the images from
+ * @return an array of <code>ImageData</code> objects loaded from the specified file
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the file name is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_INVALID_IMAGE - if the image file contains invalid data</li>
+ * <li>ERROR_IO - if an IO error occurs while reading data</li>
+ * </ul>
+ */
+public ImageData[] load(String filename) {
+ if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ InputStream stream = null;
+ try {
+ stream = new FileInputStream(filename);
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ return load(stream);
+}
+
+/**
+ * Saves the image data in this ImageLoader to the specified stream.
+ * The format parameter can have one of the following values:
+ * <dl>
+ * <dt><code>IMAGE_BMP</code></dt>
+ * <dd>Windows BMP file format, no compression</dd>
+ * <dt><code>IMAGE_BMP_RLE</code></dt>
+ * <dd>Windows BMP file format, RLE compression if appropriate</dd>
+ * <dt><code>IMAGE_GIF</code></dt>
+ * <dd>GIF file format</dd>
+ * <dt><code>IMAGE_ICO</code></dt>
+ * <dd>Windows ICO file format</dd>
+ * <dt><code>IMAGE_JPEG</code></dt>
+ * <dd>JPEG file format</dd>
+ * <dt><code>IMAGE_PNG</code></dt>
+ * <dd>PNG file format</dd>
+ * </dl>
+ *
+ * @param stream the output stream to write the images to
+ * @param format the format to write the images in
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the stream is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_INVALID_IMAGE if the image data contains invalid data</li>
+ * <li>ERROR_IO if an IO error occurs while writing to the stream</li>
+ * </ul>
+ */
+public void save(OutputStream stream, int format) {
+ if (stream == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ FileFormat.save(stream, format, this);
+}
+
+/**
+ * Saves the image data in this ImageLoader to a file with the specified name.
+ * The format parameter can have one of the following values:
+ * <dl>
+ * <dt><code>IMAGE_BMP</code></dt>
+ * <dd>Windows BMP file format, no compression</dd>
+ * <dt><code>IMAGE_BMP_RLE</code></dt>
+ * <dd>Windows BMP file format, RLE compression if appropriate</dd>
+ * <dt><code>IMAGE_GIF</code></dt>
+ * <dd>GIF file format</dd>
+ * <dt><code>IMAGE_ICO</code></dt>
+ * <dd>Windows ICO file format</dd>
+ * <dt><code>IMAGE_JPEG</code></dt>
+ * <dd>JPEG file format</dd>
+ * <dt><code>IMAGE_PNG</code></dt>
+ * <dd>PNG file format</dd>
+ * </dl>
+ *
+ * @param filename the name of the file to write the images to
+ * @param format the format to write the images in
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the file name is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_INVALID_IMAGE if the image data contains invalid data</li>
+ * <li>ERROR_IO if an IO error occurs while writing to the file</li>
+ * </ul>
+ */
+public void save(String filename, int format) {
+ if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ OutputStream stream = null;
+ try {
+ stream = new FileOutputStream(filename);
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ save(stream, format);
+}
+
+/**
+ * Adds a listener to receive image loader events.
+ * <p>
+ * An ImageLoaderListener should be added before invoking
+ * one of the receiver's load methods. The listener's
+ * <code>imageDataLoaded</code> method is called when image
+ * data has been partially loaded, as is supported by interlaced
+ * GIF/PNG or progressive JPEG images.
+ *
+ * @param listener the ImageLoaderListener to add
+ *
+ * @see ImageLoaderListener
+ * @see ImageLoaderEvent
+ */
+public void addImageLoaderListener(ImageLoaderListener listener) {
+ if (imageLoaderListeners == null) {
+ imageLoaderListeners = new Vector();
+ }
+ imageLoaderListeners.addElement(listener);
+}
+
+/**
+ * Removes a listener that was receiving image loader events.
+ *
+ * @param listener the ImageLoaderListener to remove
+ *
+ * @see #addImageLoaderListener
+ */
+public void removeImageLoaderListener(ImageLoaderListener listener) {
+ if (imageLoaderListeners == null) return;
+ imageLoaderListeners.removeElement(listener);
+}
+
+/**
+ * Returns <code>true</code> if the receiver has image loader
+ * listeners, and <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if there are <code>ImageLoaderListener</code>s, and <code>false</code> otherwise
+ *
+ * @see #addImageLoaderListener
+ * @see #removeImageLoaderListener
+ */
+public boolean hasListeners() {
+ return imageLoaderListeners != null && imageLoaderListeners.size() > 0;
+}
+
+/**
+ * Notifies all image loader listeners that an image loader event
+ * has occurred. Pass the specified event object to each listener.
+ *
+ * @param event the <code>ImageLoaderEvent</code> to send to each <code>ImageLoaderListener</code>
+ */
+public void notifyListeners(ImageLoaderEvent event) {
+ if (!hasListeners()) return;
+ int size = imageLoaderListeners.size();
+ for (int i = 0; i < size; i++) {
+ ImageLoaderListener listener = (ImageLoaderListener) imageLoaderListeners.elementAt(i);
+ listener.imageDataLoaded(event);
+ }
+}
+
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageLoaderEvent.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageLoaderEvent.java
new file mode 100755
index 0000000000..737582344c
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageLoaderEvent.java
@@ -0,0 +1,78 @@
+package org.eclipse.swt.graphics;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2000 All Rights Reserved
+ */
+
+import java.util.*;
+
+/**
+ * Instances of this class are sent as a result of the incremental
+ * loading of image data.
+ * <p>
+ * <b>Notes:</b>
+ * </p><ul>
+ * <li>The number of events which will be sent when loading images
+ * is not constant. It varies by image type, and for JPEG images it
+ * varies from image to image.</li>
+ * <li>For image sources which contain multiple images, the
+ * <code>endOfImage</code> flag in the event will be set to true
+ * after each individual image is loaded.</li>
+ * </ul>
+ *
+ * @see ImageLoader
+ * @see ImageLoaderListener
+ */
+
+public class ImageLoaderEvent extends EventObject {
+
+ /**
+ * if the <code>endOfImage</code> flag is false, then this is a
+ * partially complete copy of the current <code>ImageData</code>,
+ * otherwise this is a completely loaded <code>ImageData</code>
+ */
+ public ImageData imageData;
+
+ /**
+ * the zero-based count of image data increments -- this is
+ * equivalent to the number of events that have been generated
+ * while loading a particular image
+ */
+ public int incrementCount;
+
+ /**
+ * If this flag is true, then the current image data has been
+ * completely loaded, otherwise the image data is only partially
+ * loaded, and further ImageLoader events will occur unless an
+ * exception is thrown
+ */
+ public boolean endOfImage;
+
+/**
+ * Constructs a new instance of this class given the event source and
+ * the values to store in its fields.
+ *
+ * @param source the ImageLoader that was loading when the event occurred
+ * @param imageData the image data for the event
+ * @param incrementCount the image data increment for the event
+ * @param endOfImage the end of image flag for the event
+ */
+public ImageLoaderEvent(ImageLoader source, ImageData imageData, int incrementCount, boolean endOfImage) {
+ super(source);
+ this.imageData = imageData;
+ this.incrementCount = incrementCount;
+ this.endOfImage = endOfImage;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the point
+ */
+public String toString () {
+ return "ImageLoaderEvent {source=" + source + " imageData=" + imageData + " incrementCount=" + incrementCount + " endOfImage=" + endOfImage + "}";
+}
+
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageLoaderListener.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageLoaderListener.java
new file mode 100755
index 0000000000..a1ba7f2727
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageLoaderListener.java
@@ -0,0 +1,39 @@
+package org.eclipse.swt.graphics;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2000 All Rights Reserved
+ */
+
+import java.util.EventListener;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the incremental loading of image data.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to an image loader using the
+ * <code>addImageLoaderListener</code> method and removed using
+ * the <code>removeImageLoaderListener</code> method. When
+ * image data is either partially or completely loaded, this
+ * method will be invoked.
+ * </p>
+ *
+ * @see ImageLoader
+ * @see ImageLoaderEvent
+ */
+
+public interface ImageLoaderListener extends EventListener {
+
+/**
+ * Sent when image data is either partially or completely loaded.
+ * <p>
+ * The timing of when this method is called varies depending on
+ * the format of the image being loaded.
+ * </p>
+ *
+ * @param e an event containing information about the image loading operation
+ */
+public void imageDataLoaded(ImageLoaderEvent e);
+
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/PaletteData.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/PaletteData.java
new file mode 100755
index 0000000000..91ef2bb4fe
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/PaletteData.java
@@ -0,0 +1,205 @@
+package org.eclipse.swt.graphics;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import org.eclipse.swt.*;
+
+/**
+ * Instances of this class describe the color data used by an image.
+ * <p>
+ * Depending on the depth of the image, the PaletteData can take one
+ * of two forms, indicated by the isDirect field:
+ * </p>
+ * <dl>
+ * <dt>
+ * <em>isDirect is false</em>
+ * </dt>
+ * <dd>
+ * If isDirect is <code>false</code>, this palette is an indexed
+ * palette which maps pixel values to RGBs. The actual RGB values
+ * may be retrieved by using the getRGBs() method.
+ * </dd>
+ * <dt>
+ * <em>isDirect is true</em>
+ * </dt>
+ * <dd>
+ * If isDirect is <code>true</code>, this palette is a direct color
+ * palette. Instead of containing RGB values, it contains red,
+ * green and blue mask and shift information which indicates how
+ * the color components may be extracted from a given pixel.
+ * This means that the RGB value is actually encoded in the pixel value.
+ * <p>
+ * In this case, the shift data is the number of bits required to shift
+ * the RGB value to the left in order to align the high bit of the
+ * corresponding mask with the high bit of the first byte. This number
+ * may be negative, so care must be taken when shifting. For example,
+ * with a red mask of 0xFF0000, the red shift would be -16. With a red
+ * mask of 0x1F, the red shift would be 3.
+ * </p>
+ * </dd>
+ * </dl>
+ *
+ * @see Image
+ * @see RGB
+ */
+
+public final class PaletteData {
+
+ /**
+ * true if the receiver is a direct palette,
+ * and false otherwise
+ */
+ public boolean isDirect;
+
+ /**
+ * the RGB values for an indexed palette, where the
+ * indices of the array correspond to pixel values
+ */
+ public RGB[] colors;
+
+ /**
+ * the red mask for a direct palette
+ */
+ public int redMask;
+
+ /**
+ * the green mask for a direct palette
+ */
+ public int greenMask;
+
+ /**
+ * the blue mask for a direct palette
+ */
+ public int blueMask;
+
+ /**
+ * the red shift for a direct palette
+ */
+ public int redShift;
+
+ /**
+ * the green shift for a direct palette
+ */
+ public int greenShift;
+
+ /**
+ * the blue shift for a direct palette
+ */
+ public int blueShift;
+
+/**
+ * Constructs a new indexed palette given an array of RGB values.
+ *
+ * @param colors the array of <code>RGB</code>s for the palette
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * </ul>
+ */
+public PaletteData(RGB[] colors) {
+ if (colors == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ this.colors = colors;
+ this.isDirect = false;
+}
+
+/**
+ * Constructs a new direct palette given the red, green and blue masks.
+ *
+ * @param redMask the red mask
+ * @param greenMask the green mask
+ * @param blueMask the blue mask
+ */
+public PaletteData(int redMask, int greenMask, int blueMask) {
+ this.redMask = redMask;
+ this.greenMask = greenMask;
+ this.blueMask = blueMask;
+ this.isDirect = true;
+ this.redShift = shiftForMask(redMask);
+ this.greenShift = shiftForMask(greenMask);
+ this.blueShift = shiftForMask(blueMask);
+}
+
+/**
+ * Returns the pixel value corresponding to the given <code>RBG</code>.
+ *
+ * @return the pixel value for the given RGB
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the RGB is not found in the palette</li>
+ * </ul>
+ */
+public int getPixel(RGB rgb) {
+ if (rgb == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (isDirect) {
+ int pixel = 0;
+ pixel |= (redShift < 0 ? rgb.red << -redShift : rgb.red >>> redShift) & redMask;
+ pixel |= (greenShift < 0 ? rgb.green << -greenShift : rgb.green >>> greenShift) & greenMask;
+ pixel |= (blueShift < 0 ? rgb.blue << -blueShift : rgb.blue >>> blueShift) & blueMask;
+ return pixel;
+ } else {
+ for (int i = 0; i < colors.length; i++) {
+ if (colors[i].equals(rgb)) return i;
+ }
+ /* The RGB did not exist in the palette */
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ return 0;
+ }
+}
+
+/**
+ * Returns an <code>RGB</code> corresponding to the given pixel value.
+ *
+ * @return the RGB value for the given pixel
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the pixel does not exist in the palette</li>
+ * </ul>
+ */
+public RGB getRGB(int pixel) {
+ if (isDirect) {
+ int r = pixel & redMask;
+ r = (redShift < 0) ? r >>> -redShift : r << redShift;
+ int g = pixel & greenMask;
+ g = (greenShift < 0) ? g >>> -greenShift : g << greenShift;
+ int b = pixel & blueMask;
+ b = (blueShift < 0) ? b >>> -blueShift : b << blueShift;
+ return new RGB(r, g, b);
+ } else {
+ if (pixel < 0 || pixel >= colors.length) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ return colors[pixel];
+ }
+}
+
+/**
+ * Returns all the RGB values in the receiver if it is an
+ * indexed palette, or null if it is a direct palette.
+ *
+ * @return the <code>RGB</code>s for the receiver or null
+ */
+public RGB[] getRGBs() {
+ return colors;
+}
+
+/**
+ * Computes the shift value for a given mask.
+ *
+ * @param mask the mask to compute the shift for
+ * @return the shift amount
+ *
+ * @see PaletteData
+ */
+int shiftForMask(int mask) {
+ for (int i = 31; i >= 0; i--) {
+ if (((mask >> i) & 0x1) != 0) return 7 - i;
+ }
+ return 32;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Point.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Point.java
new file mode 100755
index 0000000000..64251fec65
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Point.java
@@ -0,0 +1,93 @@
+package org.eclipse.swt.graphics;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import java.io.Serializable;
+
+/**
+ * Instances of this class represent places on the (x, y)
+ * coordinate plane.
+ * <p>
+ * The coordinate space for rectangles and points is considered
+ * to have increasing values downward and to the right from its
+ * origin making this the normal, computer graphics oriented notion
+ * of (x, y) coordinates rather than the strict mathematical one.
+ * </p>
+ * <p>
+ * Application code does <em>not</em> need to explicitly release the
+ * resources managed by each instance when those instances are no longer
+ * required, and thus no <code>dispose()</code> method is provided.
+ * </p>
+ *
+ * @see Rectangle
+ */
+
+public final class Point implements Serializable {
+
+ /**
+ * the x coordinate of the point
+ */
+ public int x;
+
+ /**
+ * the y coordinate of the point
+ */
+ public int y;
+
+/**
+ * Constructs a new point with the given x and y coordinates.
+ *
+ * @param x the x coordinate of the new point
+ * @param y the y coordinate of the new point
+ */
+public Point (int x, int y) {
+ this.x = x;
+ this.y = y;
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the <em>same</em> object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
+ *
+ * @see #hashCode
+ */
+public boolean equals (Object object) {
+ if (object == this) return true;
+ if (!(object instanceof Point)) return false;
+ Point p = (Point)object;
+ return (p.x == this.x) && (p.y == this.y);
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects which return <code>true</code> when passed to
+ * <code>equals</code> must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+public int hashCode () {
+ return x ^ y;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the point
+ */
+public String toString () {
+ return "Point {" + x + ", " + y + "}";
+}
+
+}
+
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/RGB.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/RGB.java
new file mode 100755
index 0000000000..7437c7c4d7
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/RGB.java
@@ -0,0 +1,108 @@
+package org.eclipse.swt.graphics;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import java.io.Serializable;
+import org.eclipse.swt.*;
+
+/**
+ * Instances of this class are descriptions of colors in
+ * terms of the primary additive color model (red, green and
+ * blue). A color may be described in terms of the relative
+ * intensities of these three primary colors. The brightness
+ * of each color is specified by a value in the range 0 to 255,
+ * where 0 indicates no color (blackness) and 255 indicates
+ * maximum intensity.
+ * <p>
+ * Application code does <em>not</em> need to explicitly release the
+ * resources managed by each instance when those instances are no longer
+ * required, and thus no <code>dispose()</code> method is provided.
+ * </p>
+ *
+ * @see Color
+ */
+
+public final class RGB implements Serializable {
+
+ /**
+ * the red component of the RGB
+ */
+ public int red;
+
+ /**
+ * the green component of the RGB
+ */
+ public int green;
+
+ /**
+ * the blue component of the RGB
+ */
+ public int blue;
+
+/**
+ * Constructs an instance of this class with the given
+ * red, green and blue values.
+ *
+ * @param red the red component of the new instance
+ * @param green the green component of the new instance
+ * @param blue the blue component of the new instance
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the red, green or blue argument is not between 0 and 255</li>
+ * </ul>
+ */
+public RGB(int red, int green, int blue) {
+ if ((red > 255) || (red < 0) ||
+ (green > 255) || (green < 0) ||
+ (blue > 255) || (blue < 0))
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ this.red = red;
+ this.green = green;
+ this.blue = blue;
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the <em>same</em> object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
+ *
+ * @see #hashCode
+ */
+public boolean equals (Object object) {
+ if (object == this) return true;
+ if (!(object instanceof RGB)) return false;
+ RGB rgb = (RGB)object;
+ return (rgb.red == this.red) && (rgb.green == this.green) && (rgb.blue == this.blue);
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects which return <code>true</code> when passed to
+ * <code>equals</code> must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+public int hashCode () {
+ return (blue << 16) | (green << 8) | red;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the <code>RGB</code>
+ */
+public String toString () {
+ return "RGB {" + red + ", " + green + ", " + blue + "}";
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Rectangle.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Rectangle.java
new file mode 100755
index 0000000000..42b2f030cc
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Rectangle.java
@@ -0,0 +1,264 @@
+package org.eclipse.swt.graphics;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import java.io.Serializable;
+import org.eclipse.swt.*;
+
+/**
+ * Instances of this class represent rectangular areas in an
+ * (x, y) coordinate system. The top left corner of the rectangle
+ * is specified by its x and y values, and the extent of the
+ * rectangle is specified by its width and height.
+ * <p>
+ * The coordinate space for rectangles and points is considered
+ * to have increasing values downward and to the right from its
+ * origin making this the normal, computer graphics oriented notion
+ * of (x, y) coordinates rather than the strict mathematical one.
+ * </p>
+ * <p>
+ * Application code does <em>not</em> need to explicitly release the
+ * resources managed by each instance when those instances are no longer
+ * required, and thus no <code>dispose()</code> method is provided.
+ * </p>
+ *
+ * @see Point
+ */
+
+public final class Rectangle implements Serializable {
+
+ /**
+ * the x coordinate of the rectangle
+ */
+ public int x;
+
+ /**
+ * the y coordinate of the rectangle
+ */
+ public int y;
+
+ /**
+ * the width of the rectangle
+ */
+ public int width;
+
+ /**
+ * the height of the rectangle
+ */
+ public int height;
+
+/**
+ * Construct a new instance of this class given the
+ * x, y, width and height values.
+ *
+ * @param x the x coordinate of the origin of the rectangle
+ * @param y the y coordinate of the origin of the rectangle
+ * @param width the width of the rectangle
+ * @param height the height of the rectangle
+ */
+public Rectangle (int x, int y, int width, int height) {
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+}
+
+/**
+ * Destructively replaces the x, y, width and height values
+ * in the receiver with ones which represent the union of the
+ * rectangles specified by the receiver and the given rectangle.
+ * <p>
+ * The union of two rectangles is the smallest single rectangle
+ * that completely covers both of the areas covered by the two
+ * given rectangles.
+ * </p>
+ *
+ * @param rect the rectangle to merge with the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * </ul>
+ */
+public void add (Rectangle rect) {
+ if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ int left = x < rect.x ? x : rect.x;
+ int top = y < rect.y ? y : rect.y;
+ int lhs = x + width;
+ int rhs = rect.x + rect.width;
+ int right = lhs > rhs ? lhs : rhs;
+ lhs = y + height;
+ rhs = rect.y + rect.height;
+ int bottom = lhs > rhs ? lhs : rhs;
+ x = left; y = top; width = right - left; height = bottom - top;
+}
+
+/**
+ * Returns <code>true</code> if the point specified by the
+ * arguments is inside the area specified by the receiver,
+ * and <code>false</code> otherwise.
+ *
+ * @param x the x coordinate of the point to test for containment
+ * @param y the y coordinate of the point to test for containment
+ * @return <code>true</code> if the rectangle contains the point and <code>false</code> otherwise
+ */
+public boolean contains (int x, int y) {
+ return (x >= this.x) && (y >= this.y) && ((x - this.x) < width) && ((y - this.y) < height);
+}
+
+/**
+ * Returns <code>true</code> if the given point is inside the
+ * area specified by the receiver, and <code>false</code>
+ * otherwise.
+ *
+ * @param pt the point to test for containment
+ * @return <code>true</code> if the rectangle contains the point and <code>false</code> otherwise
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * </ul>
+ */
+public boolean contains (Point pt) {
+ if (pt == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ return contains(pt.x, pt.y);
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the <em>same</em> object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
+ *
+ * @see #hashCode
+ */
+public boolean equals (Object object) {
+ if (object == this) return true;
+ if (!(object instanceof Rectangle)) return false;
+ Rectangle r = (Rectangle)object;
+ return (r.x == this.x) && (r.y == this.y) && (r.width == this.width) && (r.height == this.height);
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects which return <code>true</code> when passed to
+ * <code>equals</code> must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+public int hashCode () {
+ return x ^ y ^ width ^ height;
+}
+
+/**
+ * Returns a new rectangle which represents the intersection
+ * of the receiver and the given rectangle.
+ * <p>
+ * The intersection of two rectangles is the rectangle that
+ * covers the area which is contained within both rectangles.
+ * </p>
+ *
+ * @param rect the rectangle to intersect with the receiver
+ * @return the intersection of the receiver and the argument
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * </ul>
+ */
+public Rectangle intersection (Rectangle rect) {
+ if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (this == rect) return new Rectangle (x, y, width, height);
+ int left = x > rect.x ? x : rect.x;
+ int top = y > rect.y ? y : rect.y;
+ int lhs = x + width;
+ int rhs = rect.x + rect.width;
+ int right = lhs < rhs ? lhs : rhs;
+ lhs = y + height;
+ rhs = rect.y + rect.height;
+ int bottom = lhs < rhs ? lhs : rhs;
+ return new Rectangle (left, top, right - left, bottom - top);
+}
+
+/**
+ * Returns <code>true</code> if the given rectangle intersects
+ * with the receiver and <code>false</code> otherwise.
+ * <p>
+ * Two rectangles intersect if the area of the rectangle
+ * representing their intersection is not empty.
+ * </p>
+ *
+ * @param rect the rectangle to test for intersection
+ * @return <code>true</code> if the rectangle intersects with the receiver, and <code>false</code> otherwise
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * </ul>
+ *
+ * @see #intersection
+ * @see #isEmpty
+ */
+public boolean intersects (Rectangle rect) {
+ if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ return (rect == this) || (rect.x < x + width) && (rect.y < y + height) &&
+ (rect.x + rect.width > x) && (rect.y + rect.height > y);
+}
+
+/**
+ * Returns <code>true</code> if the receiver does not cover any
+ * area in the (x, y) coordinate plane, and <code>false</code> if
+ * the receiver does cover some area in the plane.
+ * <p>
+ * A rectangle is considered to <em>cover area</em> in the
+ * (x, y) coordinate plane if both its width and height are
+ * non-zero.
+ * </p>
+ *
+ * @return <code>true</code> if the receiver is empty, and <code>false</code> otherwise
+ */
+public boolean isEmpty () {
+ return (width <= 0) || (height <= 0);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the rectangle
+ */
+public String toString () {
+ return "Rectangle {" + x + ", " + y + ", " + width + ", " + height + "}";
+}
+
+/**
+ * Returns a new rectangle which represents the union of
+ * the receiver and the given rectangle.
+ *
+ * @param rect the rectangle to perform union with
+ * @return the union of the receiver and the argument
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * </ul>
+ *
+ * @see #add
+ */
+public Rectangle union (Rectangle rect) {
+ if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ int left = x < rect.x ? x : rect.x;
+ int top = y < rect.y ? y : rect.y;
+ int lhs = x + width;
+ int rhs = rect.x + rect.width;
+ int right = lhs > rhs ? lhs : rhs;
+ lhs = y + height;
+ rhs = rect.y + rect.height;
+ int bottom = lhs > rhs ? lhs : rhs;
+ return new Rectangle (left, top, right - left, bottom - top);
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/package.html b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/package.html
new file mode 100755
index 0000000000..c6a867e380
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/package.html
@@ -0,0 +1,17 @@
+ <html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="Author" content="IBM">
+ <title>Package-level Javadoc</title>
+</head>
+<body>
+SWT graphics classes.
+<h2>
+Package Specification</h2>
+This package provides the classes which implement points, rectangles,
+regions, colors, cursors, fonts, graphics contexts (that is, <code>GC</code>s)
+where most of the primitive drawing operations are implemented, and
+images including both the code for displaying them and the public API for
+loading/saving them.
+</body>
+</html>
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/Callback.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/Callback.java
new file mode 100755
index 0000000000..3dc9ef89d6
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/Callback.java
@@ -0,0 +1,270 @@
+package org.eclipse.swt.internal;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import org.eclipse.swt.*;
+
+/**
+ * Instances of this class represent entry points into Java
+ * which can be invoked from operating system level callback
+ * routines.
+ * <p>
+ * IMPORTANT: A callback is only valid when invoked on the
+ * thread which created it. The results are undefined (and
+ * typically bad) when a callback is passed out to the
+ * operating system (or other code) in such a way that the
+ * callback is called from a different thread.
+ */
+
+public class Callback {
+
+ Object object;
+ String method, signature;
+ int argCount, address;
+ boolean isStatic, isArrayBased;
+
+ /* SWT Version - Mmmm (M=major, mmm=minor) */
+
+ /**
+ * SWT Major version number (must be >= 0)
+ */
+ public static int MAJOR_VERSION = 0;
+
+ /**
+ * SWT Minor version number (must be in the range 0..999)
+ */
+ public static int MINOR_VERSION = 105;
+
+ /**
+ * SWT revision number (must be >= 0)
+ */
+ public static int REVISION = 0;
+
+ /* Load the SWT library */
+ static {
+ loadLibrary ("swt");
+ }
+
+/**
+ * Constructs a new instance of this class given an object
+ * to send the message to, a string naming the method to
+ * invoke and an argument count. Note that, if the object
+ * is an instance of <code>Class</code> it is assumed that
+ * the method is a static method on that class.
+ *
+ * @param object the object to send the message to
+ * @param method the name of the method to invoke
+ * @param argCount the number of arguments that the method takes
+ */
+public Callback (Object object, String method, int argCount) {
+ this (object, method, argCount, false);
+}
+
+/**
+ * Constructs a new instance of this class given an object
+ * to send the message to, a string naming the method to
+ * invoke, an argument count and a flag indicating whether
+ * or not the arguments will be passed in an array. Note
+ * that, if the object is an instance of <code>Class</code>
+ * it is assumed that the method is a static method on that
+ * class.
+ *
+ * @param object the object to send the message to
+ * @param method the name of the method to invoke
+ * @param argCount the number of arguments that the method takes
+ * @param isArrayBased <code>true</code> if the arguments should be passed in an array and false otherwise
+ */
+public Callback (Object object, String method, int argCount, boolean isArrayBased) {
+
+ /* Set the callback fields */
+ this.object = object;
+ this.method = method;
+ this.argCount = argCount;
+ isStatic = object instanceof Class;
+ this.isArrayBased = isArrayBased;
+
+ /* Inline the common cases */
+ if (isArrayBased) {
+ signature = "([I)I";
+ } else {
+ switch (argCount) {
+ case 0: signature = "()I"; break;
+ case 1: signature = "(I)I"; break;
+ case 2: signature = "(II)I"; break;
+ case 3: signature = "(III)I"; break;
+ case 4: signature = "(IIII)I"; break;
+ default:
+ signature = "(";
+ for (int i=0; i<argCount; i++) signature += "I";
+ signature += ")I";
+ }
+ }
+
+ /* Bind the address */
+ address = bind (this);
+}
+
+/**
+ * Allocates the native level resources associated with the
+ * callback. This method is only invoked from within the
+ * constructor for the argument.
+ *
+ * @param callback the callback to bind
+ */
+static native synchronized int bind (Callback callback);
+
+/**
+ * Releases the native level resources associated with the callback,
+ * and removes all references between the callback and
+ * other objects. This helps to prevent (bad) application code
+ * from accidentally holding onto extraneous garbage.
+ */
+public void dispose () {
+ if (object == null) return;
+ unbind (this);
+ object = method = signature = null;
+ address = 0;
+}
+
+/**
+ * Returns the address of a block of machine code which will
+ * invoke the callback represented by the receiver.
+ *
+ * @return the callback address
+ */
+public int getAddress () {
+ return address;
+}
+
+/**
+ * Returns the SWT version as an integer in the standard format
+ * <em>Mmmm</em> where <em>M</em> is the major version number
+ * and <em>mmm</em> is the minor version number.
+ *
+ * @return the version of the currently running SWT
+ */
+public static int getVersion () {
+ return MAJOR_VERSION * 1000 + MINOR_VERSION;
+}
+
+/**
+ * Returns the SWT platform name.
+ *
+ * @return the platform name of the currently running SWT
+ */
+public static native String getPlatform ();
+
+/**
+ * Returns the SWT revision number as an integer. Revision changes
+ * occur as a result of non-API breaking bug fixes.
+ *
+ * @return the revision number of the currently running SWT
+ */
+public static int getRevision () {
+ return REVISION;
+}
+
+/**
+ * Indicates whether or not callbacks which are triggered at the
+ * native level should cause the messages described by the matching
+ * <code>Callback</code> objects to be invoked. This method is used
+ * to safely shut down SWT when it is run within environments
+ * which can generate spurious events.
+ * <p>
+ * Note: This should not be called by application code.
+ * </p>
+ *
+ * @param ignore true if callbacks should not be invoked
+ */
+public static final native synchronized void setEnabled (boolean enable);
+
+/**
+ * Returns whether or not callbacks which are triggered at the
+ * native level should cause the messages described by the matching
+ * <code>Callback</code> objects to be invoked. This method is used
+ * to safely shut down SWT when it is run within environments
+ * which can generate spurious events.
+ * <p>
+ * Note: This should not be called by application code.
+ * </p>
+ *
+ * @return true if callbacks should not be invoked
+ */
+public static final native synchronized boolean getEnabled ();
+
+/**
+ * This might be called directly from native code in environments
+ * which can generate spurious events. Check before removing it.
+ *
+ * @deprecated
+ *
+ * @param ignore true if callbacks should not be invoked
+ */
+static final void ignoreCallbacks (boolean ignore) {
+ setEnabled(!ignore);
+}
+
+/*
+ * Loads the SWT shared library that matches the version
+ * of the Java code which is currently running.
+ */
+public static void loadLibrary () {
+ loadLibrary ("swt");
+}
+
+/**
+ * Loads the shared library that matches the version of the
+ * Java code which is currently running. SWT shared libraries
+ * follow an encoding scheme where the major, minor and revision
+ * numbers are embedded in the library name and this along with
+ * <code>name</code> is used to load the library. If this fails,
+ * <code>name</code> is used in another attempt to load the library,
+ * this time ignoring the SWT version encoding scheme.
+ *
+ * @param name the name of the library to load
+ */
+public static void loadLibrary (String name) {
+ String newName = name + MAJOR_VERSION;
+
+ /* Force 3 digits in minor version number */
+ if (MINOR_VERSION < 10) {
+ newName += "00";
+ } else {
+ if (MINOR_VERSION < 100) newName += "0";
+ }
+ newName += MINOR_VERSION;
+
+ /* No "r" until first revision */
+ if (REVISION > 0) newName += "r" + REVISION;
+ try {
+ System.loadLibrary (newName);
+ } catch (UnsatisfiedLinkError e) {
+ try {
+ System.loadLibrary (name);
+ } catch (UnsatisfiedLinkError e2) {
+ throw e;
+ }
+ }
+}
+
+/**
+ * Immediately wipes out all native level state associated
+ * with <em>all</em> callbacks.
+ * <p>
+ * <b>WARNING:</b> This operation is <em>extremely</em> dangerous,
+ * and should never be performed by application code.
+ * </p>
+ */
+public static final native synchronized void reset ();
+
+/**
+ * Releases the native level resources associated with the callback.
+ *
+ * @see #dispose
+ */
+static final native synchronized void unbind (Callback callback);
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/FileFormat.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/FileFormat.java
new file mode 100755
index 0000000000..1bf2ae1d80
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/FileFormat.java
@@ -0,0 +1,108 @@
+package org.eclipse.swt.internal.image;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+/* Imports */
+import java.io.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+/* Class Definition */
+public abstract class FileFormat {
+ LEDataInputStream inputStream;
+ LEDataOutputStream outputStream;
+ ImageLoader loader;
+byte[] bitInvertData(byte[] data, int startIndex, int endIndex) {
+ // Destructively bit invert data in the given byte array.
+ for (int i = startIndex; i < endIndex; i++) {
+ data[i] = (byte)(255 - data[i - startIndex]);
+ }
+ return data;
+}
+
+abstract ImageData[] loadFromByteStream();
+
+public ImageData[] loadFromStream(LEDataInputStream stream) {
+ try {
+ inputStream = stream;
+ return loadFromByteStream();
+ } catch (Exception e) {
+ SWT.error(SWT.ERROR_IO, e);
+ return null;
+ }
+}
+public static ImageData[] load(InputStream is, ImageLoader loader) {
+ FileFormat fileFormat = null;
+ LEDataInputStream stream = new LEDataInputStream(is);
+ if (GIFFileFormat.isGIFFile(stream)) {
+ fileFormat = new GIFFileFormat();
+ } else if (WinBMPFileFormat.isBMPFile(stream)) {
+ fileFormat = new WinBMPFileFormat();
+ } else if (WinICOFileFormat.isICOFile(stream)) {
+ fileFormat = new WinICOFileFormat();
+ } else if (JPEGFileFormat.isJPEGFile(stream)) {
+ fileFormat = new JPEGFileFormat();
+ } else if (PNGFileFormat.isPNGFile(stream)) {
+ fileFormat = new PNGFileFormat();
+ } else {
+ SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
+ }
+ fileFormat.loader = loader;
+ return fileFormat.loadFromStream(stream);
+}
+public static void save(OutputStream os, int format, ImageLoader loader) {
+ /* We do not currently support writing multi-image files,
+ * so we use the first image data in the loader's array. */
+ ImageData data = loader.data[0];
+ LEDataOutputStream stream = new LEDataOutputStream(os);
+ switch (format) {
+ case SWT.IMAGE_BMP:
+ WinBMPFileFormat f = new WinBMPFileFormat();
+ f.unloadIntoStream(data, stream);
+ break;
+ case SWT.IMAGE_BMP_RLE:
+ f = new WinBMPFileFormat();
+ if (data.depth == 8)
+ f.compression = 1;
+ if (data.depth == 4)
+ f.compression = 2;
+ f.unloadIntoStream(data, stream);
+ break;
+ case SWT.IMAGE_GIF:
+ GIFFileFormat g = new GIFFileFormat();
+ g.unloadIntoStream(data, stream);
+ break;
+ case SWT.IMAGE_ICO:
+ WinICOFileFormat i = new WinICOFileFormat();
+ i.unloadIntoStream(data, stream);
+ break;
+ case SWT.IMAGE_JPEG:
+ JPEGFileFormat j = new JPEGFileFormat();
+ j.unloadIntoStream(data, stream);
+ break;
+ case SWT.IMAGE_PNG:
+ PNGFileFormat p = new PNGFileFormat();
+ p.unloadIntoStream(data, stream);
+ break;
+ default:
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+}
+
+abstract void unloadIntoByteStream(ImageData image);
+
+public void unloadIntoStream(ImageData image, LEDataOutputStream stream) {
+ try {
+ outputStream = stream;
+ unloadIntoByteStream(image);
+ outputStream.close();
+ } catch (Exception e) {
+ try {outputStream.close();} catch (Exception f) {}
+ SWT.error(SWT.ERROR_IO, e);
+ }
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/GIFFileFormat.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/GIFFileFormat.java
new file mode 100755
index 0000000000..5951beb747
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/GIFFileFormat.java
@@ -0,0 +1,522 @@
+package org.eclipse.swt.internal.image;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import java.io.*;
+
+final class GIFFileFormat extends FileFormat {
+ String signature, version;
+ boolean sorted;
+ int screenWidth, screenHeight, backgroundPixel, aspect, bitsPerPixel;
+ boolean userInput = false;
+ int disposalMethod = 0;
+ int delayTime = 0;
+ int transparentPixel = -1;
+ int repeatCount = 1;
+
+ static final int GIF_APPLICATION_EXTENSION_BLOCK_ID = 0xFF;
+ static final int GIF_GRAPHICS_CONTROL_BLOCK_ID = 0xF9;
+ static final int GIF_PLAIN_TEXT_BLOCK_ID = 0x01;
+ static final int GIF_COMMENT_BLOCK_ID = 0xFE;
+ static final int GIF_EXTENSION_BLOCK_ID = 0x21;
+ static final int GIF_IMAGE_BLOCK_ID = 0x2C;
+ static final int GIF_TRAILER_ID = 0x3B;
+
+ /**
+ * Return whether or not the specified input stream
+ * represents a GIF file.
+ */
+ public static boolean isGIFFile(LEDataInputStream stream) {
+ try {
+ byte[] signature = new byte[3];
+ stream.read(signature);
+ stream.unread(signature);
+ return new String(signature).equals("GIF");
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ /**
+ * Answer a palette containing numGrays
+ * shades of gray, ranging from black to white.
+ */
+ static PaletteData grayRamp(int numGrays) {
+ int n = numGrays - 1;
+ RGB[] colors = new RGB[numGrays];
+ for (int i = 0; i < numGrays; i++) {
+ int intensity = (byte)((i * 3) * 256 / n);
+ colors[i] = new RGB(intensity, intensity, intensity);
+ }
+ return new PaletteData(colors);
+ }
+
+ /**
+ * Load the GIF image(s) stored in the input stream.
+ * Return an array of ImageData representing the image(s).
+ */
+ ImageData[] loadFromByteStream() {
+ byte[] signatureBytes = new byte[3];
+ byte[] versionBytes = new byte[3];
+ byte[] block = new byte[7];
+ try {
+ inputStream.read(signatureBytes);
+ signature = new String(signatureBytes);
+ if (!signature.equals("GIF"))
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+
+ inputStream.read(versionBytes);
+ version = new String(versionBytes);
+
+ inputStream.read(block);
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ screenWidth = (block[0] & 0xFF) | ((block[1] & 0xFF) << 8);
+ loader.logicalScreenWidth = screenWidth;
+ screenHeight = (block[2] & 0xFF) | ((block[3] & 0xFF) << 8);
+ loader.logicalScreenHeight = screenHeight;
+ byte bitField = block[4];
+ backgroundPixel = block[5] & 0xFF;
+ aspect = block[6] & 0xFF;
+ bitsPerPixel = ((bitField >> 4) & 0x07) + 1;
+ int depth = (bitField & 0x7) + 1;
+ PaletteData palette = null;
+ if ((bitField & 0x80) != 0) {
+ // Global palette.
+ sorted = (bitField & 0x8) != 0;
+ palette = readPalette(1 << depth);
+ } else {
+ // No global palette.
+ sorted = false;
+ backgroundPixel = -1;
+ depth = bitsPerPixel;
+ }
+ loader.backgroundPixel = backgroundPixel;
+
+ getExtensions();
+ int id = readID();
+ ImageData[] images = new ImageData[0];
+ while (id == GIF_IMAGE_BLOCK_ID) {
+ ImageData image = readImageBlock(depth, palette);
+ if (loader.hasListeners()) {
+ loader.notifyListeners(new ImageLoaderEvent(loader, image, 3, true));
+ }
+ ImageData[] oldImages = images;
+ images = new ImageData[oldImages.length + 1];
+ System.arraycopy(oldImages, 0, images, 0, oldImages.length);
+ images[images.length - 1] = image;
+ try {
+ /* Read the 0-byte terminator at the end of the image. */
+ id = inputStream.read();
+ if (id > 0) {
+ /* We read the terminator earlier. */
+ inputStream.unread(new byte[] {(byte)id});
+ }
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ getExtensions();
+ id = readID();
+ }
+ return images;
+ }
+
+ /**
+ * Read and return the next block or extension identifier from the file.
+ */
+ int readID() {
+ try {
+ return inputStream.read();
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ return -1;
+ }
+
+ /**
+ * Read extensions until an image descriptor appears.
+ * In the future, if we care about the extensions, they
+ * should be properly grouped with the image data before
+ * which they appeared. Right now, the interesting parts
+ * of some extensions are kept, but the rest is discarded.
+ * Throw an error if an error occurs.
+ */
+ void getExtensions() {
+ int id = readID();
+ while (id != GIF_IMAGE_BLOCK_ID && id != GIF_TRAILER_ID && id > 0) {
+ if (id == GIF_EXTENSION_BLOCK_ID) {
+ readExtension();
+ } else {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ }
+ id = readID();
+ }
+ if (id == GIF_IMAGE_BLOCK_ID) {
+ try {
+ inputStream.unread(new byte[] {(byte)id});
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ }
+ }
+
+ /**
+ * Read a control extension.
+ * Return the extension block data.
+ */
+ byte[] readExtension() {
+ int extensionID = readID();
+ if (extensionID == GIF_COMMENT_BLOCK_ID)
+ return readCommentExtension();
+ if (extensionID == GIF_PLAIN_TEXT_BLOCK_ID)
+ return readPlainTextExtension();
+ if (extensionID == GIF_GRAPHICS_CONTROL_BLOCK_ID)
+ return readGraphicsControlExtension();
+ if (extensionID == GIF_APPLICATION_EXTENSION_BLOCK_ID)
+ return readApplicationExtension();
+ // Otherwise, we don't recognize the block. If the
+ // field size is correct, we can just skip over
+ // the block contents.
+ try {
+ int extSize = inputStream.read();
+ if (extSize < 0) {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ }
+ byte[] ext = new byte[extSize];
+ inputStream.read(ext, 0, extSize);
+ return ext;
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ return null;
+ }
+ }
+
+ /**
+ * We have just read the Comment extension identifier
+ * from the input stream. Read in the rest of the comment
+ * and return it. GIF comment blocks are variable size.
+ */
+ byte[] readCommentExtension() {
+ try {
+ byte[] comment = new byte[0];
+ byte[] block = new byte[255];
+ int size = inputStream.read();
+ while ((size > 0) && (inputStream.read(block, 0, size) != -1)) {
+ byte[] oldComment = comment;
+ comment = new byte[oldComment.length + size];
+ System.arraycopy(oldComment, 0, comment, 0, oldComment.length);
+ System.arraycopy(block, 0, comment, oldComment.length, size);
+ size = inputStream.read();
+ }
+ return comment;
+ } catch (Exception e) {
+ SWT.error(SWT.ERROR_IO, e);
+ return null;
+ }
+ }
+
+ /**
+ * We have just read the PlainText extension identifier
+ * from the input stream. Read in the plain text info and text,
+ * and return the text. GIF plain text blocks are variable size.
+ */
+ byte[] readPlainTextExtension() {
+ try {
+ // Read size of block = 0x0C.
+ inputStream.read();
+ // Read the text information (x, y, width, height, colors).
+ byte[] info = new byte[12];
+ inputStream.read(info);
+ // Read the text.
+ byte[] text = new byte[0];
+ byte[] block = new byte[255];
+ int size = inputStream.read();
+ while ((size > 0) && (inputStream.read(block, 0, size) != -1)) {
+ byte[] oldText = text;
+ text = new byte[oldText.length + size];
+ System.arraycopy(oldText, 0, text, 0, oldText.length);
+ System.arraycopy(block, 0, text, oldText.length, size);
+ size = inputStream.read();
+ }
+ return text;
+ } catch (Exception e) {
+ SWT.error(SWT.ERROR_IO, e);
+ return null;
+ }
+ }
+
+ /**
+ * We have just read the GraphicsControl extension identifier
+ * from the input stream. Read in the control information, store
+ * it, and return it.
+ */
+ byte[] readGraphicsControlExtension() {
+ try {
+ // Read size of block = 0x04.
+ inputStream.read();
+ // Read the control block.
+ byte[] controlBlock = new byte[4];
+ inputStream.read(controlBlock);
+ byte bitField = controlBlock[0];
+ // Store the user input field.
+ userInput = (bitField & 0x02) != 0;
+ // Store the disposal method.
+ disposalMethod = (bitField >> 2) & 0x07;
+ // Store the delay time.
+ delayTime = (controlBlock[1] & 0xFF) | ((controlBlock[2] & 0xFF) << 8);
+ // Store the transparent color.
+ if ((bitField & 0x01) != 0)
+ transparentPixel = controlBlock[3] & 0xFF;
+ else
+ transparentPixel = -1;
+ // Read block terminator.
+ inputStream.read();
+ return controlBlock;
+ } catch (Exception e) {
+ SWT.error(SWT.ERROR_IO, e);
+ return null;
+ }
+ }
+
+ /**
+ * We have just read the Application extension identifier
+ * from the input stream. Read in the rest of the extension,
+ * look for and store 'number of repeats', and return the data.
+ */
+ byte[] readApplicationExtension() {
+ try {
+ // Read size of block = 0x0B.
+ inputStream.read();
+ // Read application identifier.
+ byte[] applicationBytes = new byte[8];
+ inputStream.read(applicationBytes);
+ String application = new String(applicationBytes);
+ // Read authentication code.
+ byte[] authenticationBytes = new byte[3];
+ inputStream.read(authenticationBytes);
+ String authentication = new String(authenticationBytes);
+ // Read application data.
+ byte[] data = new byte[0];
+ byte[] block = new byte[255];
+ int size = inputStream.read();
+ while ((size > 0) && (inputStream.read(block, 0, size) != -1)) {
+ byte[] oldData = data;
+ data = new byte[oldData.length + size];
+ System.arraycopy(oldData, 0, data, 0, oldData.length);
+ System.arraycopy(block, 0, data, oldData.length, size);
+ size = inputStream.read();
+ }
+ // Look for the NETSCAPE 'repeat count' field for an animated GIF.
+ if (application.equals("NETSCAPE") && authentication.equals("2.0") && data[0] == 01) {
+ repeatCount = (data[1] & 0xFF) | ((data[2] & 0xFF) << 8);
+ loader.repeatCount = repeatCount;
+ }
+ return data;
+ } catch (Exception e) {
+ SWT.error(SWT.ERROR_IO, e);
+ return null;
+ }
+ }
+
+ /**
+ * Return a DeviceIndependentImage representing the
+ * image block at the current position in the input stream.
+ * Throw an error if an error occurs.
+ */
+ ImageData readImageBlock(int defaultDepth, PaletteData defaultPalette) {
+ int depth;
+ PaletteData palette;
+ byte[] block = new byte[9];
+ try {
+ inputStream.read(block);
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ int left = (block[0] & 0xFF) | ((block[1] & 0xFF) << 8);
+ int top = (block[2] & 0xFF) | ((block[3] & 0xFF) << 8);
+ int width = (block[4] & 0xFF) | ((block[5] & 0xFF) << 8);
+ int height = (block[6] & 0xFF) | ((block[7] & 0xFF) << 8);
+ byte bitField = block[8];
+ boolean interlaced = (bitField & 0x40) != 0;
+ boolean sorted = (bitField & 0x20) != 0;
+ if ((bitField & 0x80) != 0) {
+ // Local palette.
+ depth = (bitField & 0x7) + 1;
+ palette = readPalette(1 << depth);
+ } else {
+ // No local palette.
+ depth = defaultDepth;
+ palette = defaultPalette;
+ }
+ // Promote depth to next highest supported value.
+ if (!(depth == 1 || depth == 4 || depth == 8)) {
+ if (depth < 4)
+ depth = 4;
+ else
+ depth = 8;
+ }
+ if (palette == null) {
+ palette = grayRamp(1 << depth);
+ }
+ int initialCodeSize = -1;
+ try {
+ initialCodeSize = inputStream.read();
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ if (initialCodeSize < 0) {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ }
+ ImageData image = ImageData.internal_new(
+ width,
+ height,
+ depth,
+ palette,
+ 4,
+ null,
+ 0,
+ null,
+ null,
+ -1,
+ transparentPixel,
+ SWT.IMAGE_GIF,
+ left,
+ top,
+ disposalMethod,
+ delayTime);
+ LZWCodec codec = new LZWCodec();
+ codec.decode(inputStream, loader, image, interlaced, initialCodeSize);
+ return image;
+ }
+
+ /**
+ * Read a palette from the input stream.
+ */
+ PaletteData readPalette(int numColors) {
+ byte[] bytes = new byte[numColors * 3];
+ try {
+ if (inputStream.read(bytes) != bytes.length)
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ RGB[] colors = new RGB[numColors];
+ for (int i = 0; i < numColors; i++)
+ colors[i] = new RGB(bytes[i*3] & 0xFF,
+ bytes[i*3+1] & 0xFF, bytes[i*3+2] & 0xFF);
+ return new PaletteData(colors);
+ }
+
+ /**
+ * Write the specified device independent image
+ * to the output stream.
+ */
+ void unloadIntoByteStream(ImageData image) {
+ if (!((image.depth == 1) || (image.depth == 4) || (image.depth == 8))) {
+ SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+ }
+ byte bitField = (byte)((0x80 & 0xF8 & 0xF7 & 0x8F) + (image.depth - 1) + ((image.depth - 1) * 16));
+ try {
+ outputStream.write(new byte[] { (byte)'G', (byte)'I', (byte)'F' });
+ outputStream.write(new byte[] { (byte)'8', (byte)'9', (byte)'a' });
+ outputStream.writeShort((short)image.width);
+ outputStream.writeShort((short)image.height);
+ outputStream.writeByte(bitField);
+ outputStream.writeByte((byte)0);
+ outputStream.writeByte((byte)0);
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ writePalette(image.palette, image.depth);
+ if (image.transparentPixel != -1 || image.disposalMethod != 0 || image.delayTime != 0) {
+ writeGraphicsControlBlock(image);
+ }
+ writeImageBlock(image);
+ }
+
+ /**
+ * Write out a GraphicsControlBlock to describe
+ * the specified device independent image.
+ */
+ void writeGraphicsControlBlock(ImageData image) {
+ try {
+ outputStream.write(GIF_EXTENSION_BLOCK_ID);
+ outputStream.write(GIF_GRAPHICS_CONTROL_BLOCK_ID);
+ outputStream.write(0x04); // size of block
+ byte[] gcBlock = new byte[4];
+ gcBlock[0] = (byte)0xFD;
+ gcBlock[1] = 0;
+ gcBlock[2] = 0;
+ gcBlock[3] = 0;
+ if (image.transparentPixel == -1) {
+ gcBlock[0] = (byte)(gcBlock[0] & 0xFE);
+ } else {
+ gcBlock[0] = (byte)(gcBlock[0] | 0x01);
+ gcBlock[3] = (byte)image.transparentPixel;
+ }
+ if (image.disposalMethod != 0) {
+ gcBlock[0] = (byte)(gcBlock[0] | ((image.disposalMethod & 0x07) << 2));
+ }
+ if (image.delayTime != 0) {
+ gcBlock[1] = (byte)(image.delayTime & 0xFF);
+ gcBlock[2] = (byte)((image.delayTime >> 8) & 0xFF);
+ }
+ outputStream.write(gcBlock);
+ outputStream.write(0); // block terminator
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ }
+
+ /**
+ * Write the specified device independent image
+ * to the current position in the output stream.
+ */
+ void writeImageBlock(ImageData image) {
+ try {
+ outputStream.write(GIF_IMAGE_BLOCK_ID);
+ byte[] block = new byte[9];
+ block[0] = (byte)(image.x & 0xFF);
+ block[1] = (byte)((image.x >> 8) & 0xFF);
+ block[2] = (byte)(image.y & 0xFF);
+ block[3] = (byte)((image.y >> 8) & 0xFF);
+ block[4] = (byte)(image.width & 0xFF);
+ block[5] = (byte)((image.width >> 8) & 0xFF);
+ block[6] = (byte)(image.height & 0xFF);
+ block[7] = (byte)((image.height >> 8) & 0xFF);
+ block[8] = 0; // no interlace, no sort, no local palette
+ outputStream.write(block);
+ outputStream.write(image.depth);
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ new LZWCodec().encode(outputStream, image);
+ }
+
+ /**
+ * Write the specified palette to the output stream.
+ */
+ void writePalette(PaletteData palette, int depth) {
+ byte[] bytes = new byte[(1 << depth) * 3];
+ int offset = 0;
+ for (int i = 0; i < palette.colors.length; i++) {
+ RGB color = palette.colors[i];
+ bytes[offset] = (byte)color.red;
+ bytes[offset + 1] = (byte)color.green;
+ bytes[offset + 2] = (byte)color.blue;
+ offset += 3;;
+ }
+ try {
+ outputStream.write(bytes);
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ }
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGAppn.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGAppn.java
new file mode 100755
index 0000000000..f211bfd3ca
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGAppn.java
@@ -0,0 +1,24 @@
+package org.eclipse.swt.internal.image;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.eclipse.swt.*;
+
+final class JPEGAppn extends JPEGVariableSizeSegment {
+
+ public JPEGAppn(byte[] reference) {
+ super(reference);
+ }
+
+ public JPEGAppn(LEDataInputStream byteStream) {
+ super(byteStream);
+ }
+
+ public boolean verify() {
+ int marker = getSegmentMarker();
+ return marker >= JPEGFileFormat.APP0 && marker <= JPEGFileFormat.APP15;
+ }
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGArithmeticConditioningTable.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGArithmeticConditioningTable.java
new file mode 100755
index 0000000000..689ba2c5a8
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGArithmeticConditioningTable.java
@@ -0,0 +1,17 @@
+package org.eclipse.swt.internal.image;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp 2000
+ */
+
+final class JPEGArithmeticConditioningTable extends JPEGVariableSizeSegment {
+
+ public JPEGArithmeticConditioningTable(LEDataInputStream byteStream) {
+ super(byteStream);
+ }
+
+ public int signature() {
+ return JPEGFileFormat.DAC;
+ }
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGComment.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGComment.java
new file mode 100755
index 0000000000..7c2e186df0
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGComment.java
@@ -0,0 +1,21 @@
+package org.eclipse.swt.internal.image;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp 2000
+ */
+
+final class JPEGComment extends JPEGVariableSizeSegment {
+
+ public JPEGComment(byte[] reference) {
+ super(reference);
+ }
+
+ public JPEGComment(LEDataInputStream byteStream) {
+ super(byteStream);
+ }
+
+ public int signature() {
+ return JPEGFileFormat.COM;
+ }
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGEndOfImage.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGEndOfImage.java
new file mode 100755
index 0000000000..2937a7cbe2
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGEndOfImage.java
@@ -0,0 +1,25 @@
+package org.eclipse.swt.internal.image;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp 2000
+ */
+
+final class JPEGEndOfImage extends JPEGFixedSizeSegment {
+
+ public JPEGEndOfImage() {
+ super();
+ }
+
+ public JPEGEndOfImage(byte[] reference) {
+ super(reference);
+ }
+
+ public int signature() {
+ return JPEGFileFormat.EOI;
+ }
+
+ public int fixedSize() {
+ return 2;
+ }
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGFileFormat.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGFileFormat.java
new file mode 100755
index 0000000000..6650760172
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGFileFormat.java
@@ -0,0 +1,1891 @@
+package org.eclipse.swt.internal.image;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+/* Imports */
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import java.io.*;
+
+/* Class Definition */
+final class JPEGFileFormat extends FileFormat {
+ int restartInterval;
+ JPEGFrameHeader frameHeader;
+ int imageWidth, imageHeight;
+ int interleavedMcuCols, interleavedMcuRows;
+ int maxV, maxH;
+ boolean progressive;
+ int samplePrecision;
+ int nComponents;
+ int[][] frameComponents;
+ byte[][] imageComponents;
+ int[] dataUnit;
+ int[][][] dataUnits;
+ int[] precedingDCs;
+ JPEGScanHeader scanHeader;
+ byte[] dataBuffer;
+ int currentBitCount;
+ int bufferCurrentPosition;
+ int restartsToGo;
+ int nextRestartNumber;
+ JPEGArithmeticConditioningTable arithmeticTables;
+ JPEGHuffmanTable[] acHuffmanTables;
+ JPEGHuffmanTable[] dcHuffmanTables;
+ int[][] quantizationTables;
+ int currentByte;
+ int decoderQFactor;
+ int encoderQFactor = 75;
+ int eobrun = 0;
+ /* JPEGConstants */
+ public static final int DCTSIZE = 8;
+ public static final int DCTSIZESQR = 64;
+ /* JPEGFixedPointConstants */
+ public static final int FIX_0_899976223 = 7373;
+ public static final int FIX_1_961570560 = 16069;
+ public static final int FIX_2_053119869 = 16819;
+ public static final int FIX_0_298631336 = 2446;
+ public static final int FIX_1_847759065 = 15137;
+ public static final int FIX_1_175875602 = 9633;
+ public static final int FIX_3_072711026 = 25172;
+ public static final int FIX_0_765366865 = 6270;
+ public static final int FIX_2_562915447 = 20995;
+ public static final int FIX_0_541196100 = 4433;
+ public static final int FIX_0_390180644 = 3196;
+ public static final int FIX_1_501321110 = 12299;
+ /* JPEGMarkerCodes */
+ public static final int APP0 = 0xFFE0;
+ public static final int APP15 = 0xFFEF;
+ public static final int COM = 0xFFFE;
+ public static final int DAC = 0xFFCC;
+ public static final int DHP = 0xFFDE;
+ public static final int DHT = 0xFFC4;
+ public static final int DNL = 0xFFDC;
+ public static final int DRI = 0xFFDD;
+ public static final int DQT = 0xFFDB;
+ public static final int EOI = 0xFFD9;
+ public static final int EXP = 0xFFDF;
+ public static final int JPG = 0xFFC8;
+ public static final int JPG0 = 0xFFF0;
+ public static final int JPG13 = 0xFFFD;
+ public static final int RST0 = 0xFFD0;
+ public static final int RST1 = 0xFFD1;
+ public static final int RST2 = 0xFFD2;
+ public static final int RST3 = 0xFFD3;
+ public static final int RST4 = 0xFFD4;
+ public static final int RST5 = 0xFFD5;
+ public static final int RST6 = 0xFFD6;
+ public static final int RST7 = 0xFFD7;
+ public static final int SOF0 = 0xFFC0;
+ public static final int SOF1 = 0xFFC1;
+ public static final int SOF2 = 0xFFC2;
+ public static final int SOF3 = 0xFFC3;
+ public static final int SOF5 = 0xFFC5;
+ public static final int SOF6 = 0xFFC6;
+ public static final int SOF7 = 0xFFC7;
+ public static final int SOF9 = 0xFFC9;
+ public static final int SOF10 = 0xFFCA;
+ public static final int SOF11 = 0xFFCB;
+ public static final int SOF13 = 0xFFCD;
+ public static final int SOF14 = 0xFFCE;
+ public static final int SOF15 = 0xFFCF;
+ public static final int SOI = 0xFFD8;
+ public static final int SOS = 0xFFDA;
+ public static final int TEM = 0xFF01;
+ /* JPEGFrameComponentParameterConstants */
+ public static final int TQI = 0;
+ public static final int HI = 1;
+ public static final int VI = 2;
+ public static final int CW = 3;
+ public static final int CH = 4;
+ /* JPEGScanComponentParameterConstants */
+ public static final int DC = 0;
+ public static final int AC = 1;
+
+ public static final int[] ExtendTest = {
+ 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048,
+ 4096, 8192, 16384, 32768, 65536, 131072, 262144
+ };
+ public static final int[] ExtendOffset = new int[] {
+ 0, -1, -3, -7, -15, -31, -63, -127, -255, -511, -1023, -2047,
+ -4095, -8191, -16383, -32767, -65535, -131071, -262143
+ };
+ public static final int[] ZigZag8x8 = {
+ 0, 1, 8, 16, 9, 2, 3, 10,
+ 17, 24, 32, 25, 18, 11, 4, 5,
+ 12, 19, 26, 33, 40, 48, 41, 34,
+ 27, 20, 13, 6, 7, 14, 21, 28,
+ 35, 42, 49, 56, 57, 50, 43, 36,
+ 29, 22, 15, 23, 30, 37, 44, 51,
+ 58, 59, 52, 45, 38, 31, 39, 46,
+ 53, 60, 61, 54, 47, 55, 62, 63
+ };
+ public static int[] CrRTable, CbBTable, CrGTable, CbGTable;
+ public static int[] RYTable, GYTable, BYTable,
+ RCbTable, GCbTable, BCbTable, RCrTable, GCrTable, BCrTable, NBitsTable;
+ static {
+ initialize();
+ }
+void compress(ImageData image, byte[] dataYComp, byte[] dataCbComp, byte[] dataCrComp) {
+ int srcWidth = image.width;
+ int srcHeight = image.height;
+ int vhFactor = maxV * maxH;
+ int[] frameComponent;
+ byte[][] imageComponents = new byte[nComponents][];
+ for (int i = 0; i < nComponents; i++) {
+ frameComponent = frameComponents[i];
+ imageComponents[i] = new byte[frameComponent[CW] * frameComponent[CH]];
+ }
+ frameComponent = frameComponents[0];
+ for (int yPos = 0; yPos < srcHeight; yPos++) {
+ int srcOfs = yPos * srcWidth;
+ int dstOfs = yPos * frameComponent[CW];
+ System.arraycopy(dataYComp, srcOfs, imageComponents[0], dstOfs, srcWidth);
+ }
+ frameComponent = frameComponents[1];
+ for (int yPos = 0; yPos < srcHeight / maxV; yPos++) {
+ int destRowIndex = yPos * frameComponent[CW];
+ for (int xPos = 0; xPos < srcWidth / maxH; xPos++) {
+ int sum = 0;
+ for (int iv = 0; iv < maxV; iv++) {
+ int srcIndex = (yPos * maxV + iv) * srcWidth + (xPos * maxH);
+ for (int ih = 0; ih < maxH; ih++) {
+ sum += dataCbComp[srcIndex + ih] & 0xFF;
+ }
+ }
+ imageComponents[1][destRowIndex + xPos] = (byte)(sum / vhFactor);
+ }
+ }
+ frameComponent = frameComponents[2];
+ for (int yPos = 0; yPos < srcHeight / maxV; yPos++) {
+ int destRowIndex = yPos * frameComponent[CW];
+ for (int xPos = 0; xPos < srcWidth / maxH; xPos++) {
+ int sum = 0;
+ for (int iv = 0; iv < maxV; iv++) {
+ int srcIndex = (yPos * maxV + iv) * srcWidth + (xPos * maxH);
+ for (int ih = 0; ih < maxH; ih++) {
+ sum += dataCrComp[srcIndex + ih] & 0xFF;
+ }
+ }
+ imageComponents[2][destRowIndex + xPos] = (byte)(sum / vhFactor);
+ }
+ }
+ for (int iComp = 0; iComp < nComponents; iComp++) {
+ byte[] imageComponent = imageComponents[iComp];
+ frameComponent = frameComponents[iComp];
+ int hFactor = frameComponent[HI];
+ int vFactor = frameComponent[VI];
+ int componentWidth = frameComponent[CW];
+ int componentHeight = frameComponent[CH];
+ int compressedWidth = srcWidth / (maxH / hFactor);
+ int compressedHeight = srcHeight / (maxV / vFactor);
+ if (compressedWidth < componentWidth) {
+ int delta = componentWidth - compressedWidth;
+ for (int yPos = 0; yPos < compressedHeight; yPos++) {
+ int dstOfs = ((yPos + 1) * componentWidth - delta);
+ int dataValue = imageComponent[dstOfs - 1] & 0xFF;
+ for (int i = 0; i < delta; i++) {
+ imageComponent[dstOfs + i] = (byte)dataValue;
+ }
+ }
+ }
+ if (compressedHeight < componentHeight) {
+ int srcOfs = (compressedHeight - 1) * componentWidth;
+ for (int yPos = compressedHeight; yPos <= componentHeight; yPos++) {
+ int dstOfs = (yPos - 1) * componentWidth;
+ System.arraycopy(imageComponent, srcOfs, imageComponent, dstOfs, componentWidth);
+ }
+ }
+ }
+}
+void convert4BitRGBToYCbCr(ImageData image) {
+ RGB[] rgbs = image.getRGBs();
+ int paletteSize = rgbs.length;
+ byte[] yComp = new byte[paletteSize];
+ byte[] cbComp = new byte[paletteSize];
+ byte[] crComp = new byte[paletteSize];
+ int srcWidth = image.width;
+ int srcHeight = image.height;
+ for (int i = 0; i < paletteSize; i++) {
+ RGB color = rgbs[i];
+ int r = color.red;
+ int g = color.green;
+ int b = color.blue;
+ int n = RYTable[r] + GYTable[g] + BYTable[b];
+ yComp[i] = (byte)(n / 65536);
+ if ((n < 0) && (n % 65536 != 0)) yComp[i]--;
+ n = RCbTable[r] + GCbTable[g] + BCbTable[b];
+ cbComp[i] = (byte)(n / 65536);
+ if ((n < 0) && (n % 65536 != 0)) cbComp[i]--;
+ n = RCrTable[r] + GCrTable[g] + BCrTable[b];
+ crComp[i] = (byte)(n / 65536);
+ if ((n < 0) && (n % 65536 != 0)) crComp[i]--;
+ }
+ int bSize = srcWidth * srcHeight;
+ byte[] dataYComp = new byte[bSize];
+ byte[] dataCbComp = new byte[bSize];
+ byte[] dataCrComp = new byte[bSize];
+ byte[] origData = image.data;
+ for (int yPos = 0; yPos < srcHeight; yPos++) {
+ for (int xPos = 0; xPos < srcWidth / 2; xPos++) {
+ int srcIndex = yPos * (srcWidth / 2) + xPos;
+ int dstIndex = yPos * srcWidth + (xPos * 2);
+ int value2 = origData[srcIndex] & 0xFF;
+ int value1 = value2 / 16;
+ value2 = value2 % 16;
+ dataYComp[dstIndex] = yComp[value1];
+ dataCbComp[dstIndex] = cbComp[value1];
+ dataCrComp[dstIndex] = crComp[value1];
+ dataYComp[dstIndex + 1] = yComp[value2];
+ dataCbComp[dstIndex + 1] = cbComp[value2];
+ dataCrComp[dstIndex + 1] = crComp[value2];
+ }
+ }
+ compress(image, dataYComp, dataCbComp, dataCrComp);
+}
+void convert8BitRGBToYCbCr(ImageData image) {
+ RGB[] rgbs = image.getRGBs();
+ int paletteSize = rgbs.length;
+ byte[] yComp = new byte[paletteSize];
+ byte[] cbComp = new byte[paletteSize];
+ byte[] crComp = new byte[paletteSize];
+ int srcWidth = image.width;
+ int srcHeight = image.height;
+ for (int i = 0; i < paletteSize; i++) {
+ RGB color = rgbs[i];
+ int r = color.red;
+ int g = color.green;
+ int b = color.blue;
+ int n = RYTable[r] + GYTable[g] + BYTable[b];
+ yComp[i] = (byte)(n / 65536);
+ if ((n < 0) && (n % 65536 != 0)) yComp[i]--;
+ n = RCbTable[r] + GCbTable[g] + BCbTable[b];
+ cbComp[i] = (byte)(n / 65536);
+ if ((n < 0) && (n % 65536 != 0)) cbComp[i]--;
+ n = RCrTable[r] + GCrTable[g] + BCrTable[b];
+ crComp[i] = (byte)(n / 65536);
+ if ((n < 0) && (n % 65536 != 0)) crComp[i]--;
+ }
+ int dstWidth = image.width;
+ int dstHeight = srcHeight;
+ int stride = (srcWidth + 3) / 4 * 4;
+ int bSize = dstWidth * dstHeight;
+ byte[] dataYComp = new byte[bSize];
+ byte[] dataCbComp = new byte[bSize];
+ byte[] dataCrComp = new byte[bSize];
+ byte[] origData = image.data;
+ for (int yPos = 0; yPos < srcHeight; yPos++) {
+ int srcRowIndex = yPos * stride;
+ int dstRowIndex = yPos * dstWidth;
+ for (int xPos = 0; xPos < srcWidth; xPos++) {
+ int value = origData[srcRowIndex + xPos] & 0xFF;
+ int dstIndex = dstRowIndex + xPos;
+ dataYComp[dstIndex] = yComp[value];
+ dataCbComp[dstIndex] = cbComp[value];
+ dataCrComp[dstIndex] = crComp[value];
+ }
+ }
+ compress(image, dataYComp, dataCbComp, dataCrComp);
+}
+byte[] convertCMYKToRGB() {
+ /* Unsupported CMYK format. Answer an empty byte array. */
+ return new byte[0];
+}
+void convertImageToYCbCr(ImageData image) {
+ switch (image.depth) {
+ case 4:
+ convert4BitRGBToYCbCr(image);
+ return;
+ case 8:
+ convert8BitRGBToYCbCr(image);
+ return;
+ case 16:
+ case 24:
+ convertMultiRGBToYCbCr(image);
+ return;
+ default:
+ SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+ }
+ return;
+}
+void convertMultiRGBToYCbCr(ImageData image) {
+ int srcWidth = image.width;
+ int srcHeight = image.height;
+ int bSize = srcWidth * srcHeight;
+ byte[] dataYComp = new byte[bSize];
+ byte[] dataCbComp = new byte[bSize];
+ byte[] dataCrComp = new byte[bSize];
+ byte[] origData = image.data;
+ PaletteData palette = image.palette;
+ int[] buffer = new int[srcWidth];
+ if (palette.isDirect) {
+ int redMask = palette.redMask;
+ int greenMask = palette.greenMask;
+ int blueMask = palette.blueMask;
+ int redShift = palette.redShift;
+ int greenShift = palette.greenShift;
+ int blueShift = palette.blueShift;
+ for (int yPos = 0; yPos < srcHeight; yPos++) {
+ image.getPixels(0, yPos, srcWidth, buffer, 0);
+ int dstRowIndex = yPos * srcWidth;
+ for (int xPos = 0; xPos < srcWidth; xPos++) {
+ int pixel = buffer[xPos];
+ int dstDataIndex = dstRowIndex + xPos;
+ int r = pixel & redMask;
+ r = (redShift < 0) ? r >> -redShift : r << redShift;
+ int g = pixel & greenMask;
+ g = (greenShift < 0) ? g >> -greenShift : g << greenShift;
+ int b = pixel & blueMask;
+ b = (blueShift < 0) ? b >> -blueShift : b << blueShift;
+ dataYComp[dstDataIndex] = (byte)((RYTable[r] + GYTable[g] + BYTable[b]) / 65536);
+ dataCbComp[dstDataIndex] = (byte)((RCbTable[r] + GCbTable[g] + BCbTable[b]) / 65536);
+ dataCrComp[dstDataIndex] = (byte)((RCrTable[r] + GCrTable[g] + BCrTable[b]) / 65536);
+ }
+ }
+ } else {
+ for (int yPos = 0; yPos < srcHeight; yPos++) {
+ image.getPixels(0, yPos, srcWidth, buffer, 0);
+ int dstRowIndex = yPos * srcWidth;
+ for (int xPos = 0; xPos < srcWidth; xPos++) {
+ int pixel = buffer[xPos];
+ int dstDataIndex = dstRowIndex + xPos;
+ RGB rgb = palette.getRGB(pixel);
+ int r = rgb.red;
+ int g = rgb.green;
+ int b = rgb.blue;
+ dataYComp[dstDataIndex] = (byte)((RYTable[r] + GYTable[g] + BYTable[b]) / 65536);
+ dataCbComp[dstDataIndex] = (byte)((RCbTable[r] + GCbTable[g] + BCbTable[b]) / 65536);
+ dataCrComp[dstDataIndex] = (byte)((RCrTable[r] + GCrTable[g] + BCrTable[b]) / 65536);
+ }
+ }
+ }
+ compress(image, dataYComp, dataCbComp, dataCrComp);
+}
+byte[] convertYToRGB() {
+ int compWidth = frameHeader.componentParameters[0][3];
+ int bytesPerLine = (((imageWidth * 8 + 7) / 8) + 3) / 4 * 4;
+ byte[] data = new byte[bytesPerLine * imageHeight];
+ byte[] yComp = imageComponents[0];
+ int destIndex = 0;
+ for (int i = 0; i < imageHeight; i++) {
+ int srcIndex = i * compWidth;
+ for (int j = 0; j < bytesPerLine; j++) {
+ int y = yComp[srcIndex] & 0xFF;
+ if (y < 0) {
+ y = 0;
+ } else {
+ if (y > 255) y = 255;
+ }
+ if (j >= imageWidth) {
+ y = 0;
+ }
+ data[destIndex] = (byte)y;
+ srcIndex++;
+ destIndex++;
+ }
+ }
+ return data;
+}
+byte[] convertYCbCrToRGB() {
+ /**
+ * Convert existing image components into an RGB format.
+ * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
+ * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
+ * The conversion equations to be implemented are therefore
+ * R = Y + 1.40200 * Cr
+ * G = Y - 0.34414 * Cb - 0.71414 * Cr
+ * B = Y + 1.77200 * Cb
+ * where Cb and Cr represent the incoming values less MAXJSAMPLE/2.
+ * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
+ *
+ * To avoid floating-point arithmetic, we represent the fractional constants
+ * as integers scaled up by 2^16 (about 4 digits precision); we have to divide
+ * the products by 2^16, with appropriate rounding, to get the correct answer.
+ * Notice that Y, being an integral input, does not contribute any fraction
+ * so it need not participate in the rounding.
+ *
+ * For even more speed, we avoid doing any multiplications in the inner loop
+ * by precalculating the constants times Cb and Cr for all possible values.
+ * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
+ * for 12-bit samples it is still acceptable. It's not very reasonable for
+ * 16-bit samples, but if you want lossless storage you shouldn't be changing
+ * colorspace anyway.
+ * The Cr=>R and Cb=>B values can be rounded to integers in advance; the
+ * values for the G calculation are left scaled up, since we must add them
+ * together before rounding.
+ */
+ int bSize = imageWidth * imageHeight * nComponents;
+ byte[] rgbData = new byte[bSize];
+ int destIndex = 0;
+ expandImageComponents();
+ byte[] yComp = imageComponents[0];
+ byte[] cbComp = imageComponents[1];
+ byte[] crComp = imageComponents[2];
+ int compWidth = frameHeader.componentParameters[0][3];
+ for (int v = 0; v < imageHeight; v++) {
+ int srcIndex = v * compWidth;
+ for (int i = 0; i < imageWidth; i++) {
+ int y = yComp[srcIndex] & 0xFF;
+ int cb = cbComp[srcIndex] & 0xFF;
+ int cr = crComp[srcIndex] & 0xFF;
+ int r = y + CrRTable[cr];
+ int g = y + ((CbGTable[cb] + CrGTable[cr]) / 65536);
+ int b = y + CbBTable[cb];
+ if (r < 0) {
+ r = 0;
+ } else {
+ if (r > 255) r = 255;
+ }
+ if (g < 0) {
+ g = 0;
+ } else {
+ if (g > 255) g = 255;
+ }
+ if (b < 0) {
+ b = 0;
+ } else {
+ if (b > 255) b = 255;
+ }
+ rgbData[destIndex] = (byte)b;
+ rgbData[destIndex + 1] = (byte)g;
+ rgbData[destIndex + 2] = (byte)r;
+ destIndex += 3;
+ srcIndex++;
+ }
+ }
+ return rgbData;
+}
+byte[] convertYIQToRGB() {
+ /* Unsupported CMYK format. Answer an empty byte array. */
+ return new byte[0];
+}
+void decodeACCoefficients(int[] dataUnit, int iComp) {
+ int[] sParams = scanHeader.componentParameters[iComp];
+ JPEGHuffmanTable acTable = acHuffmanTables[sParams[AC]];
+ int k = 1;
+ while (k < 64) {
+ int rs = decodeUsingTable(acTable);
+ int r = rs >> 4;
+ int s = rs & 0xF;
+ if (s == 0) {
+ if (r == 15) {
+ k += 16;
+ } else {
+ break;
+ }
+ } else {
+ k += r;
+ int bits = receive(s);
+ dataUnit[ZigZag8x8[k]] = extendBy(bits, s);
+ k++;
+ }
+ }
+}
+void decodeACFirstCoefficients(int[] dataUnit, int iComp, int start, int end, int approxBit) {
+ if (eobrun > 0) {
+ eobrun--;
+ return;
+ }
+ int[] sParams = scanHeader.componentParameters[iComp];
+ JPEGHuffmanTable acTable = acHuffmanTables[sParams[AC]];
+ int k = start;
+ while (k <= end) {
+ int rs = decodeUsingTable(acTable);
+ int r = rs >> 4;
+ int s = rs & 0xF;
+ if (s == 0) {
+ if (r == 15) {
+ k += 16;
+ } else {
+ eobrun = (1 << r) + receive(r) - 1;
+ break;
+ }
+ } else {
+ k += r;
+ int bits = receive(s);
+ dataUnit[ZigZag8x8[k]] = extendBy(bits, s) << approxBit;
+ k++;
+ }
+ }
+}
+void decodeACRefineCoefficients(int[] dataUnit, int iComp, int start, int end, int approxBit) {
+ int[] sParams = scanHeader.componentParameters[iComp];
+ JPEGHuffmanTable acTable = acHuffmanTables[sParams[AC]];
+ int k = start;
+ while (k <= end) {
+ if (eobrun > 0) {
+ while (k <= end) {
+ int zzIndex = ZigZag8x8[k];
+ if (dataUnit[zzIndex] != 0) {
+ dataUnit[zzIndex] = refineAC(dataUnit[zzIndex], approxBit);
+ }
+ k++;
+ }
+ eobrun--;
+ } else {
+ int rs = decodeUsingTable(acTable);
+ int r = rs >> 4;
+ int s = rs & 0xF;
+ if (s == 0) {
+ if (r == 15) {
+ int zeros = 0;
+ while (zeros < 16 && k <= end) {
+ int zzIndex = ZigZag8x8[k];
+ if (dataUnit[zzIndex] != 0) {
+ dataUnit[zzIndex] = refineAC(dataUnit[zzIndex], approxBit);
+ } else {
+ zeros++;
+ }
+ k++;
+ }
+ } else {
+ eobrun = (1 << r) + receive(r);
+ }
+ } else {
+ int bit = receive(s);
+ int zeros = 0;
+ int zzIndex = ZigZag8x8[k];
+ while ((zeros < r || dataUnit[zzIndex] != 0) && k <= end) {
+ if (dataUnit[zzIndex] != 0) {
+ dataUnit[zzIndex] = refineAC(dataUnit[zzIndex], approxBit);
+ } else {
+ zeros++;
+ }
+ k++;
+ zzIndex = ZigZag8x8[k];
+ }
+ if (bit != 0) {
+ dataUnit[zzIndex] = 1 << approxBit;
+ } else {
+ dataUnit[zzIndex] = -1 << approxBit;
+ }
+ k++;
+ }
+ }
+ }
+}
+int refineAC(int ac, int approxBit) {
+ if (ac > 0) {
+ int bit = nextBit();
+ if (bit != 0) {
+ ac = ac + (1 << approxBit);
+ }
+ } else if (ac < 0) {
+ int bit = nextBit();
+ if (bit != 0) {
+ ac = ac + (-1 << approxBit);
+ }
+ }
+ return ac;
+}
+void decodeDCCoefficient(int[] dataUnit, int iComp, boolean first, int approxBit) {
+ int[] sParams = scanHeader.componentParameters[iComp];
+ JPEGHuffmanTable dcTable = dcHuffmanTables[sParams[DC]];
+ int lastDC = 0;
+ if (progressive && !first) {
+ int bit = nextBit();
+ lastDC = dataUnit[0] + (bit << approxBit);
+ } else {
+ lastDC = precedingDCs[iComp];
+ int nBits = decodeUsingTable(dcTable);
+ if (nBits != 0) {
+ int bits = receive(nBits);
+ int diff = extendBy(bits, nBits);
+ lastDC = lastDC + diff;
+ precedingDCs[iComp] = lastDC;
+ }
+ if (progressive) {
+ lastDC = lastDC << approxBit;
+ }
+ }
+ dataUnit[0] = lastDC;
+}
+void dequantize(int[] dataUnit, int iComp) {
+ int[] qTable = quantizationTables[frameComponents[iComp][TQI]];
+ for (int i = 0; i < dataUnit.length; i++) {
+ int zzIndex = ZigZag8x8[i];
+ dataUnit[zzIndex] = dataUnit[zzIndex] * qTable[i];
+ }
+}
+byte[] decodeImageComponents() {
+ int[] compIds = new int[nComponents];
+ int compIdsIndex = 0;
+ for (int i = 0; i < nComponents; i++) {
+ compIds[compIdsIndex] = i + 1;
+ compIdsIndex++;
+ }
+ if ((compIds.length == 3) &&
+ (compIds[0] == 1) &&
+ (compIds[1] == 2) &&
+ (compIds[2] == 3)) {
+ return convertYCbCrToRGB();
+ }
+ if ((compIds.length == 3) &&
+ (compIds[0] == 1) &&
+ (compIds[1] == 4) &&
+ (compIds[2] == 5)) {
+ return convertYIQToRGB();
+ }
+ if (compIds.length == 4) {
+ return convertCMYKToRGB();
+ }
+ return convertYToRGB();
+}
+void decodeMCUAtXAndY(int xmcu, int ymcu, int nComponentsInScan, boolean first, int start, int end, int approxBit) {
+ for (int iComp = 0; iComp < nComponentsInScan; iComp++) {
+ int scanComponent = iComp;
+ while (scanHeader.componentParameters[scanComponent] == null) {
+ scanComponent++;
+ }
+ int[] frameComponent = frameComponents[scanComponent];
+ int hi = frameComponent[HI];
+ int vi = frameComponent[VI];
+ if (nComponentsInScan == 1) {
+ hi = 1;
+ vi = 1;
+ }
+ int compWidth = frameComponent[CW];
+ for (int ivi = 0; ivi < vi; ivi++) {
+ for (int ihi = 0; ihi < hi; ihi++) {
+ if (progressive) {
+ // Progressive: First scan - create a new data unit.
+ // Subsequent scans - refine the existing data unit.
+ int index = (ymcu * vi + ivi) * compWidth + xmcu * hi + ihi;
+ dataUnit = dataUnits[scanComponent][index];
+ if (dataUnit == null) {
+ dataUnit = new int[64];
+ dataUnits[scanComponent][index] = dataUnit;
+ }
+ } else {
+ // Sequential: Clear and reuse the data unit buffer.
+ for (int i = 0; i < dataUnit.length; i++) {
+ dataUnit[i] = 0;
+ }
+ }
+ if (!progressive || scanHeader.isDCProgressiveScan()) {
+ decodeDCCoefficient(dataUnit, scanComponent, first, approxBit);
+ }
+ if (!progressive) {
+ decodeACCoefficients(dataUnit, scanComponent);
+ } else {
+ if (scanHeader.isACProgressiveScan()) {
+ if (first) {
+ decodeACFirstCoefficients(dataUnit, scanComponent, start, end, approxBit);
+ } else {
+ decodeACRefineCoefficients(dataUnit, scanComponent, start, end, approxBit);
+ }
+ }
+ if (loader.hasListeners()) {
+ // Dequantization, IDCT, up-sampling and color conversion
+ // are done on a copy of the coefficient data in order to
+ // display the image incrementally.
+ int[] temp = dataUnit;
+ dataUnit = new int[64];
+ System.arraycopy(temp, 0, dataUnit, 0, 64);
+ }
+ }
+ if (!progressive || (progressive && loader.hasListeners())) {
+ dequantize(dataUnit, scanComponent);
+ inverseDCT(dataUnit);
+ storeData(dataUnit, scanComponent, xmcu, ymcu, hi, ihi, vi, ivi);
+ }
+ }
+ }
+ }
+}
+void decodeScan() {
+ if (progressive && !scanHeader.verifyProgressiveScan()) {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ }
+ int nComponentsInScan = scanHeader.getNumberOfImageComponents();
+ int mcuRowsInScan = interleavedMcuRows;
+ int mcusPerRow = interleavedMcuCols;
+ if (nComponentsInScan == 1) {
+ // Non-interleaved.
+ int iComp = 0;
+ while (scanHeader.componentParameters[iComp] == null) {
+ iComp++;
+ }
+ int[] frameComponent = frameComponents[iComp];
+ int hi = frameComponent[HI];
+ int vi = frameComponent[VI];
+ int mcuWidth = DCTSIZE * maxH / hi;
+ int mcuHeight = DCTSIZE * maxV / vi;
+ mcusPerRow = (imageWidth + mcuWidth - 1) / mcuWidth;
+ mcuRowsInScan = (imageHeight + mcuHeight - 1) / mcuHeight;
+ }
+ boolean first = scanHeader.isFirstScan();
+ int start = scanHeader.getStartOfSpectralSelection();
+ int end = scanHeader.getEndOfSpectralSelection();
+ int approxBit = scanHeader.getApproxBitPositionLow();
+ restartsToGo = restartInterval;
+ nextRestartNumber = 0;
+ for (int ymcu = 0; ymcu < mcuRowsInScan; ymcu++) {
+ for (int xmcu = 0; xmcu < mcusPerRow; xmcu++) {
+ if (restartInterval != 0) {
+ if (restartsToGo == 0) processRestartInterval();
+ restartsToGo--;
+ }
+ decodeMCUAtXAndY(xmcu, ymcu, nComponentsInScan, first, start, end, approxBit);
+ }
+ }
+}
+int decodeUsingTable(JPEGHuffmanTable huffmanTable) {
+ int i = 0;
+ int[] maxCodes = huffmanTable.getDhMaxCodes();
+ int[] minCodes = huffmanTable.getDhMinCodes();
+ int[] valPtrs = huffmanTable.getDhValPtrs();
+ int[] huffVals = huffmanTable.getDhValues();
+ int code = nextBit();
+ while (code > maxCodes[i]) {
+ code = code * 2 + nextBit();
+ i++;
+ }
+ int j = valPtrs[i];
+ j = j + code - minCodes[i];
+ return huffVals[j];
+}
+void emit(int huffCode, int nBits) {
+ if (nBits == 0) {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ }
+ int[] power2m1 = new int[] {
+ 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191,
+ 16383, 32767, 65535, 131125
+ };
+ int code = (huffCode & power2m1[nBits - 1]) << (24 - nBits - currentBitCount);
+ byte[] codeBuffer = new byte[4];
+ codeBuffer[0] = (byte)(code % 256);
+ codeBuffer[1] = (byte)((code / 256) % 256);
+ codeBuffer[2] = (byte)((code / 65536) % 256);
+ codeBuffer[3] = (byte)((code / 16777216) % 256);
+ int abs = nBits - (8 - currentBitCount);
+ if (abs < 0) abs = -abs;
+ if ((abs / 8) > 0) {
+ currentByte += codeBuffer[2];
+ emitByte((byte)currentByte);
+ emitByte((byte)codeBuffer[1]);
+ currentByte = codeBuffer[0];
+ currentBitCount += nBits - 16;
+ } else {
+ currentBitCount += nBits;
+ if (currentBitCount >= 8) {
+ currentByte += codeBuffer[2];
+ emitByte((byte)currentByte);
+ currentByte = codeBuffer[1];
+ currentBitCount -= 8;
+ } else {
+ currentByte += codeBuffer[2];
+ }
+ }
+}
+void emitByte(byte byteValue) {
+ if (bufferCurrentPosition >= 512) {
+ resetOutputBuffer();
+ }
+ dataBuffer[bufferCurrentPosition] = byteValue;
+ bufferCurrentPosition++;
+ if (byteValue == -1) {
+ emitByte((byte)0);
+ }
+}
+void encodeACCoefficients(int[] dataUnit, int iComp) {
+ int[] sParams = scanHeader.componentParameters[iComp];
+ JPEGHuffmanTable acTable = acHuffmanTables[sParams[AC]];
+ int[] ehCodes = acTable.ehCodes;
+ byte[] ehSizes = acTable.ehCodeLengths;
+ int r = 0;
+ int k = 1;
+ while (k < 64) {
+ k++;
+ int acValue = dataUnit[ZigZag8x8[k - 1]];
+ if (acValue == 0) {
+ if (k == 64) {
+ emit(ehCodes[0], ehSizes[0] & 0xFF);
+ } else {
+ r++;
+ }
+ } else {
+ while (r > 15) {
+ emit(ehCodes[0xF0], ehSizes[0xF0] & 0xFF);
+ r -= 16;
+ }
+ if (acValue < 0) {
+ int absACValue = acValue;
+ if (absACValue < 0) absACValue = -absACValue;
+ int nBits = NBitsTable[absACValue];
+ int rs = r * 16 + nBits;
+ emit(ehCodes[rs], ehSizes[rs] & 0xFF);
+ emit(0xFFFFFF - absACValue, nBits);
+ } else {
+ int nBits = NBitsTable[acValue];
+ int rs = r * 16 + nBits;
+ emit(ehCodes[rs], ehSizes[rs] & 0xFF);
+ emit(acValue, nBits);
+ }
+ r = 0;
+ }
+ }
+}
+void encodeDCCoefficients(int[] dataUnit, int iComp) {
+ int[] sParams = scanHeader.componentParameters[iComp];
+ JPEGHuffmanTable dcTable = dcHuffmanTables[sParams[DC]];
+ int lastDC = precedingDCs[iComp];
+ int dcValue = dataUnit[0];
+ int diff = dcValue - lastDC;
+ precedingDCs[iComp] = dcValue;
+ if (diff < 0) {
+ int absDiff = 0 - diff;
+ int nBits = NBitsTable[absDiff];
+ emit(dcTable.ehCodes[nBits], dcTable.ehCodeLengths[nBits]);
+ emit(0xFFFFFF - absDiff, nBits);
+ } else {
+ int nBits = NBitsTable[diff];
+ emit(dcTable.ehCodes[nBits], dcTable.ehCodeLengths[nBits]);
+ if (nBits != 0) {
+ emit(diff, nBits);
+ }
+ }
+}
+void encodeMCUAtXAndY(int xmcu, int ymcu) {
+ int nComponentsInScan = scanHeader.getNumberOfImageComponents();
+ dataUnit = new int[64];
+ for (int iComp = 0; iComp < nComponentsInScan; iComp++) {
+ int[] frameComponent = frameComponents[iComp];
+ int hi = frameComponent[HI];
+ int vi = frameComponent[VI];
+ for (int ivi = 0; ivi < vi; ivi++) {
+ for (int ihi = 0; ihi < hi; ihi++) {
+ extractData(dataUnit, iComp, xmcu, ymcu, ihi, ivi);
+ forwardDCT(dataUnit);
+ quantizeData(dataUnit, iComp);
+ encodeDCCoefficients(dataUnit, iComp);
+ encodeACCoefficients(dataUnit, iComp);
+ }
+ }
+ }
+}
+void encodeScan() {
+ for (int ymcu = 0; ymcu < interleavedMcuRows; ymcu++) {
+ for (int xmcu = 0; xmcu < interleavedMcuCols; xmcu++) {
+ encodeMCUAtXAndY(xmcu, ymcu);
+ }
+ }
+ if (currentBitCount != 0) {
+ emitByte((byte)currentByte);
+ }
+ resetOutputBuffer();
+}
+void expandImageComponents() {
+ for (int iComp = 0; iComp < nComponents; iComp++) {
+ int[] frameComponent = frameComponents[iComp];
+ int hi = frameComponent[HI];
+ int vi = frameComponent[VI];
+ int upH = maxH / hi;
+ int upV = maxV / vi;
+ if ((upH * upV) > 1) {
+ byte[] component = imageComponents[iComp];
+ int compWidth = frameComponent[CW];
+ int compHeight = frameComponent[CH];
+ int upCompWidth = compWidth * upH;
+ int upCompHeight = compHeight * upV;
+ RGB[] rgbs = new RGB[] {
+ new RGB(0,0,0),
+ new RGB(0x80,0,0),
+ new RGB(0,0x80,0),
+ new RGB(0x80,0x80,0),
+ new RGB(0,0,0x80),
+ new RGB(0x80,0,0x80),
+ new RGB(0,0x80,0x80),
+ new RGB(0xC0,0xC0,0xC0),
+ new RGB(0x80,0x80,0x80),
+ new RGB(0xFF,0,0),
+ new RGB(0,0xFF,0),
+ new RGB(0xFF,0xFF,0),
+ new RGB(0,0,0xFF),
+ new RGB(0xFF,0,0xFF),
+ new RGB(0,0xFF,0xFF),
+ new RGB(0xFF,0xFF,0xFF),
+ };
+ ImageData src = new ImageData(compWidth, compHeight, 8, new PaletteData(rgbs), 4, component);
+ ImageData dest = src.scaledTo(upCompWidth, upCompHeight);
+ imageComponents[iComp] = dest.data;
+ }
+ }
+}
+int extendBy(int diff, int t) {
+ if (diff < ExtendTest[t]) {
+ return diff + ExtendOffset[t];
+ } else {
+ return diff;
+ }
+}
+void extractData(int[] dataUnit, int iComp, int xmcu, int ymcu, int ihi, int ivi) {
+ byte[] compImage = imageComponents[iComp];
+ int[] frameComponent = frameComponents[iComp];
+ int hi = frameComponent[HI];
+ int vi = frameComponent[VI];
+ int compWidth = frameComponent[CW];
+ int srcIndex = ((ymcu * vi + ivi) * compWidth * DCTSIZE) + ((xmcu * hi + ihi) * DCTSIZE);
+ int destIndex = 0;
+ for (int i = 0; i < DCTSIZE; i++) {
+ for (int col = 0; col < DCTSIZE; col++) {
+ dataUnit[destIndex] = (compImage[srcIndex + col] & 0xFF) - 128;
+ destIndex++;
+ }
+ srcIndex += compWidth;
+ }
+}
+void forwardDCT(int[] dataUnit) {
+ for (int row = 0; row < 8; row++) {
+ int rIndex = row * DCTSIZE;
+ int tmp0 = dataUnit[rIndex] + dataUnit[rIndex + 7];
+ int tmp7 = dataUnit[rIndex] - dataUnit[rIndex + 7];
+ int tmp1 = dataUnit[rIndex + 1] + dataUnit[rIndex + 6];
+ int tmp6 = dataUnit[rIndex + 1] - dataUnit[rIndex + 6];
+ int tmp2 = dataUnit[rIndex + 2] + dataUnit[rIndex + 5];
+ int tmp5 = dataUnit[rIndex + 2] - dataUnit[rIndex + 5];
+ int tmp3 = dataUnit[rIndex + 3] + dataUnit[rIndex + 4];
+ int tmp4 = dataUnit[rIndex + 3] - dataUnit[rIndex + 4];
+
+ /**
+ * Even part per LL&M figure 1 --- note that published figure
+ * is faulty; rotator 'sqrt(2)*c1' should be 'sqrt(2)*c6'.
+ */
+ int tmp10 = tmp0 + tmp3;
+ int tmp13 = tmp0 - tmp3;
+ int tmp11 = tmp1 + tmp2;
+ int tmp12 = tmp1 - tmp2;
+
+ dataUnit[rIndex] = (tmp10 + tmp11) * 4;
+ dataUnit[rIndex + 4] = (tmp10 - tmp11) * 4;
+
+ int z1 = (tmp12 + tmp13) * FIX_0_541196100;
+ int scaleFactor1 = ExtendTest[11];
+ int scaleFactor2 = ExtendTest[12];
+ int n = z1 + (tmp13 * FIX_0_765366865) + scaleFactor1;
+ dataUnit[rIndex + 2] = n / scaleFactor2;
+ if ((n < 0) && (n % scaleFactor2 != 0)) dataUnit[rIndex + 2]--;
+ n = z1 + (tmp12 * (0 - FIX_1_847759065)) + scaleFactor1;
+ dataUnit[rIndex + 6] = n / scaleFactor2;
+ if ((n < 0) && (n % scaleFactor2 != 0)) dataUnit[rIndex + 6]--;
+
+ /**
+ * Odd part per figure 8 --- note paper omits factor of sqrt(2).
+ * cK represents cos(K*pi/16).
+ * i0..i3 in the paper are tmp4..tmp7 here.
+ */
+ z1 = tmp4 + tmp7;
+ int z2 = tmp5 + tmp6;
+ int z3 = tmp4 + tmp6;
+ int z4 = tmp5 + tmp7;
+ int z5 = (z3 + z4) * FIX_1_175875602; // sqrt(2) * c3
+
+ tmp4 = tmp4 * FIX_0_298631336; // sqrt(2) * (-c1+c3+c5-c7)
+ tmp5 = tmp5 * FIX_2_053119869; // sqrt(2) * ( c1+c3-c5+c7)
+ tmp6 = tmp6 * FIX_3_072711026; // sqrt(2) * ( c1+c3+c5-c7)
+ tmp7 = tmp7 * FIX_1_501321110; // sqrt(2) * ( c1+c3-c5-c7)
+ z1 = z1 * (0 - FIX_0_899976223); // sqrt(2) * (c7-c3)
+ z2 = z2 * (0 - FIX_2_562915447); // sqrt(2) * (-c1-c3)
+ z3 = z3 * (0 - FIX_1_961570560); // sqrt(2) * (-c3-c5)
+ z4 = z4 * (0 - FIX_0_390180644); // sqrt(2) * (c5-c3)
+
+ z3 = z3 + z5;
+ z4 = z4 + z5;
+
+ n = tmp4 + z1 + z3 + scaleFactor1;
+ dataUnit[rIndex + 7] = n / scaleFactor2;
+ if ((n < 0) && (n % scaleFactor2 != 0)) dataUnit[rIndex + 7]--;
+ n = tmp5 + z2 + z4 + scaleFactor1;
+ dataUnit[rIndex + 5] = n / scaleFactor2;
+ if ((n < 0) && (n % scaleFactor2 != 0)) dataUnit[rIndex + 5]--;
+ n = tmp6 + z2 + z3 + scaleFactor1;
+ dataUnit[rIndex + 3] = n / scaleFactor2;
+ if ((n < 0) && (n % scaleFactor2 != 0)) dataUnit[rIndex + 3]--;
+ n = tmp7 + z1 + z4 + scaleFactor1;
+ dataUnit[rIndex + 1] = n / scaleFactor2;
+ if ((n < 0) && (n % scaleFactor2 != 0)) dataUnit[rIndex + 1]--;
+ }
+
+ /**
+ * Pass 2: process columns.
+ * Note that we must descale the results by a factor of 8 == 2**3,
+ * and also undo the PASS1_BITS scaling.
+ */
+ for (int col = 0; col < 8; col++) {
+ int c0 = col;
+ int c1 = col + 8;
+ int c2 = col + 16;
+ int c3 = col + 24;
+ int c4 = col + 32;
+ int c5 = col + 40;
+ int c6 = col + 48;
+ int c7 = col + 56;
+ int tmp0 = dataUnit[c0] + dataUnit[c7];
+ int tmp7 = dataUnit[c0] - dataUnit[c7];
+ int tmp1 = dataUnit[c1] + dataUnit[c6];
+ int tmp6 = dataUnit[c1] - dataUnit[c6];
+ int tmp2 = dataUnit[c2] + dataUnit[c5];
+ int tmp5 = dataUnit[c2] - dataUnit[c5];
+ int tmp3 = dataUnit[c3] + dataUnit[c4];
+ int tmp4 = dataUnit[c3] - dataUnit[c4];
+
+ /**
+ * Even part per LL&M figure 1 --- note that published figure
+ * is faulty; rotator 'sqrt(2)*c1' should be 'sqrt(2)*c6'.
+ */
+ int tmp10 = tmp0 + tmp3;
+ int tmp13 = tmp0 - tmp3;
+ int tmp11 = tmp1 + tmp2;
+ int tmp12 = tmp1 - tmp2;
+
+ int scaleFactor1 = ExtendTest[5];
+ int scaleFactor2 = ExtendTest[6];
+ int n = tmp10 + tmp11 + scaleFactor1;
+ dataUnit[c0] = n / scaleFactor2;
+ if ((n < 0) && (n % scaleFactor2 != 0)) dataUnit[c0]--;
+ n = tmp10 - tmp11 + scaleFactor1;
+ dataUnit[c4] = n / scaleFactor2;
+ if ((n < 0) && (n % scaleFactor2 != 0)) dataUnit[c4]--;
+
+ int z1 = (tmp12 + tmp13) * FIX_0_541196100;
+ scaleFactor1 = ExtendTest[18];
+ scaleFactor2 = ExtendTest[19];
+ n = z1 + (tmp13 * FIX_0_765366865) + scaleFactor1;
+ dataUnit[c2] = n / scaleFactor2;
+ if ((n < 0) && (n % scaleFactor2 != 0)) dataUnit[c2]--;
+ n = z1 + (tmp12 * (0 - FIX_1_847759065)) + scaleFactor1;
+ dataUnit[c6] = n / scaleFactor2;
+ if ((n < 0) && (n % scaleFactor2 != 0)) dataUnit[c6]--;
+
+ /**
+ * Odd part per figure 8 --- note paper omits factor of sqrt(2).
+ * cK represents cos(K*pi/16).
+ * i0..i3 in the paper are tmp4..tmp7 here.
+ */
+ z1 = tmp4 + tmp7;
+ int z2 = tmp5 + tmp6;
+ int z3 = tmp4 + tmp6;
+ int z4 = tmp5 + tmp7;
+ int z5 = (z3 + z4) * FIX_1_175875602; // sqrt(2) * c3
+
+ tmp4 = tmp4 * FIX_0_298631336; // sqrt(2) * (-c1+c3+c5-c7)
+ tmp5 = tmp5 * FIX_2_053119869; // sqrt(2) * ( c1+c3-c5+c7)
+ tmp6 = tmp6 * FIX_3_072711026; // sqrt(2) * ( c1+c3+c5-c7)
+ tmp7 = tmp7 * FIX_1_501321110; // sqrt(2) * ( c1+c3-c5-c7)
+ z1 = z1 * (0 - FIX_0_899976223); // sqrt(2) * (c7-c3)
+ z2 = z2 * (0 - FIX_2_562915447); // sqrt(2) * (-c1-c3)
+ z3 = z3 * (0 - FIX_1_961570560); // sqrt(2) * (-c3-c5)
+ z4 = z4 * (0 - FIX_0_390180644); // sqrt(2) * (c5-c3)
+
+ z3 = z3 + z5;
+ z4 = z4 + z5;
+
+ n = tmp4 + z1 + z3 + scaleFactor1;
+ dataUnit[c7] = n / scaleFactor2;
+ if ((n < 0) && (n % scaleFactor2 != 0)) dataUnit[c7]--;
+ n = tmp5 + z2 + z4 + scaleFactor1;
+ dataUnit[c5] = n / scaleFactor2;
+ if ((n < 0) && (n % scaleFactor2 != 0)) dataUnit[c5]--;
+ n = tmp6 + z2 + z3 + scaleFactor1;
+ dataUnit[c3] = n / scaleFactor2;
+ if ((n < 0) && (n % scaleFactor2 != 0)) dataUnit[c3]--;
+ n = tmp7 + z1 + z4 + scaleFactor1;
+ dataUnit[c1] = n / scaleFactor2;
+ if ((n < 0) && (n % scaleFactor2 != 0)) dataUnit[c1]--;
+ }
+}
+void getAPP0() {
+ JPEGAppn appn = new JPEGAppn(inputStream);
+ if (!appn.verify()) {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ }
+}
+void getCOM() {
+ new JPEGComment(inputStream);
+}
+void getDAC() {
+ JPEGArithmeticConditioningTable dac = new JPEGArithmeticConditioningTable(inputStream);
+ arithmeticTables = dac;
+}
+void getDHT() {
+ JPEGHuffmanTable dht = new JPEGHuffmanTable(inputStream);
+ if (!dht.verify()) {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ }
+ if (acHuffmanTables == null) {
+ acHuffmanTables = new JPEGHuffmanTable[4];
+ }
+ if (dcHuffmanTables == null) {
+ dcHuffmanTables = new JPEGHuffmanTable[4];
+ }
+ JPEGHuffmanTable[] dhtTables = dht.getAllTables();
+ for (int i = 0; i < dhtTables.length; i++) {
+ JPEGHuffmanTable dhtTable = dhtTables[i];
+ if (dhtTable.getTableClass() == 0) {
+ dcHuffmanTables[dhtTable.getTableIdentifier()] = dhtTable;
+ } else {
+ acHuffmanTables[dhtTable.getTableIdentifier()] = dhtTable;
+ }
+ }
+}
+void getDNL() {
+ new JPEGRestartInterval(inputStream);
+}
+void getDQT() {
+ JPEGQuantizationTable dqt = new JPEGQuantizationTable(inputStream);
+ int[][] currentTables = quantizationTables;
+ if (currentTables == null) {
+ currentTables = new int[4][];
+ }
+ int[] dqtTablesKeys = dqt.getQuantizationTablesKeys();
+ int[][] dqtTablesValues = dqt.getQuantizationTablesValues();
+ for (int i = 0; i < dqtTablesKeys.length; i++) {
+ int index = dqtTablesKeys[i];
+ currentTables[index] = dqtTablesValues[i];
+ }
+ quantizationTables = currentTables;
+}
+void getDRI() {
+ JPEGRestartInterval dri = new JPEGRestartInterval(inputStream);
+ if (!dri.verify()) {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ }
+ restartInterval = dri.getRestartInterval();
+}
+static void initialize() {
+ initializeRGBYCbCrTables();
+ initializeYCbCrRGBTables();
+ initializeBitCountTable();
+}
+static void initializeBitCountTable() {
+ int nBits = 1;
+ int count = 0;
+ int power2 = 2;
+ NBitsTable = new int[2048];
+ NBitsTable[0] = 0;
+ for (int i = 1; i < NBitsTable.length; i++) {
+ if (!(i < power2)) {
+ nBits++;
+ power2 *= 2;
+ }
+ NBitsTable[i] = nBits;
+ }
+}
+static void initializeRGBYCbCrTables() {
+ RYTable = new int[256];
+ GYTable = new int[256];
+ BYTable = new int[256];
+ RCbTable = new int[256];
+ GCbTable = new int[256];
+ BCbTable = new int[256];
+ RCrTable = BCbTable;
+ GCrTable = new int[256];
+ BCrTable = new int[256];
+ for (int i = 0; i < 256; i++) {
+ RYTable[i] = i * 19595;
+ GYTable[i] = i * 38470;
+ BYTable[i] = i * 7471 + 32768;
+ RCbTable[i] = i * -11059;
+ GCbTable[i] = i * -21709;
+ BCbTable[i] = i * 32768 + 8388608;
+ GCrTable[i] = i * -27439;
+ BCrTable[i] = i * -5329;
+ }
+}
+static void initializeYCbCrRGBTables() {
+ CrRTable = new int[256];
+ CbBTable = new int[256];
+ CrGTable = new int[256];
+ CbGTable = new int[256];
+ for (int i = 0; i < 256; i++) {
+ int x2 = 2 * i - 255;
+ CrRTable[i] = (45941 * x2 + 32768) / 65536;
+ CbBTable[i] = (58065 * x2 + 32768) / 65536;
+ CrGTable[i] = -23401 * x2;
+ CbGTable[i] = -11277 * x2 + 32768;
+ }
+}
+void inverseDCT(int[] dataUnit) {
+ for (int row = 0; row < 8; row++) {
+ int rIndex = row * DCTSIZE;
+ /**
+ * Due to quantization, we will usually find that many of the input
+ * coefficients are zero, especially the AC terms. We can exploit this
+ * by short-circuiting the IDCT calculation for any row in which all
+ * the AC terms are zero. In that case each output is equal to the
+ * DC coefficient (with scale factor as needed).
+ * With typical images and quantization tables, half or more of the
+ * row DCT calculations can be simplified this way.
+ */
+ if (isZeroInRow(dataUnit, rIndex)) {
+ int dcVal = dataUnit[rIndex] * 4;
+ for (int i = rIndex; i < rIndex + 8; i++) {
+ dataUnit[i] = dcVal;
+ }
+ } else {
+ /**
+ * Even part: reverse the even part of the forward DCT.
+ * The rotator is sqrt(2)*c(-6).
+ */
+ int z2 = dataUnit[rIndex + 2];
+ int z3 = dataUnit[rIndex + 6];
+ int z1 = (z2 + z3) * FIX_0_541196100;
+ int tmp2 = z1 + (z3 * (0 - FIX_1_847759065));
+ int tmp3 = z1 + (z2 * FIX_0_765366865);
+ int tmp0 = (dataUnit[rIndex] + dataUnit[rIndex + 4]) * 8192;
+ int tmp1 = (dataUnit[rIndex] - dataUnit[rIndex + 4]) * 8192;
+ int tmp10 = tmp0 + tmp3;
+ int tmp13 = tmp0 - tmp3;
+ int tmp11 = tmp1 + tmp2;
+ int tmp12 = tmp1 - tmp2;
+ /**
+ * Odd part per figure 8; the matrix is unitary and hence its
+ * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
+ */
+ tmp0 = dataUnit[rIndex + 7];
+ tmp1 = dataUnit[rIndex + 5];
+ tmp2 = dataUnit[rIndex + 3];
+ tmp3 = dataUnit[rIndex + 1];
+ z1 = tmp0 + tmp3;
+ z2 = tmp1 + tmp2;
+ z3 = tmp0 + tmp2;
+ int z4 = tmp1 + tmp3;
+ int z5 = (z3 + z4)* FIX_1_175875602; /* sqrt(2) * c3 */
+
+ tmp0 = tmp0 * FIX_0_298631336; /* sqrt(2) * (-c1+c3+c5-c7) */
+ tmp1 = tmp1 * FIX_2_053119869; /* sqrt(2) * ( c1+c3-c5+c7) */
+ tmp2 = tmp2 * FIX_3_072711026; /* sqrt(2) * ( c1+c3+c5-c7) */
+ tmp3 = tmp3 * FIX_1_501321110; /* sqrt(2) * ( c1+c3-c5-c7) */
+ z1 = z1 * (0 - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
+ z2 = z2 * (0 - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
+ z3 = z3 * (0 - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
+ z4 = z4 * (0 - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
+
+ z3 = z3 + z5;
+ z4 = z4 + z5;
+ tmp0 = tmp0 + z1 + z3;
+ tmp1 = tmp1 + z2 + z4;
+ tmp2 = tmp2 + z2 + z3;
+ tmp3 = tmp3 + z1 + z4;
+
+ int descaleFactor1 = ExtendTest[11];
+ int descaleFactor2 = ExtendTest[12];
+ dataUnit[rIndex] = (tmp10 + tmp3 + descaleFactor1) / descaleFactor2;
+ dataUnit[rIndex + 7] = (tmp10 - tmp3 + descaleFactor1) / descaleFactor2;
+ dataUnit[rIndex + 1] = (tmp11 + tmp2 + descaleFactor1) / descaleFactor2;
+ dataUnit[rIndex + 6] = (tmp11 - tmp2 + descaleFactor1) / descaleFactor2;
+ dataUnit[rIndex + 2] = (tmp12 + tmp1 + descaleFactor1) / descaleFactor2;
+ dataUnit[rIndex + 5] = (tmp12 - tmp1 + descaleFactor1) / descaleFactor2;
+ dataUnit[rIndex + 3] = (tmp13 + tmp0 + descaleFactor1) / descaleFactor2;
+ dataUnit[rIndex + 4] = (tmp13 - tmp0 + descaleFactor1) / descaleFactor2;
+ }
+ }
+ /**
+ * Pass 2: process columns.
+ * Note that we must descale the results by a factor of 8 == 2**3,
+ * and also undo the PASS1_BITS scaling.
+ */
+ for (int col = 0; col < 8; col++) {
+ int c0 = col;
+ int c1 = col + 8;
+ int c2 = col + 16;
+ int c3 = col + 24;
+ int c4 = col + 32;
+ int c5 = col + 40;
+ int c6 = col + 48;
+ int c7 = col + 56;
+ if (isZeroInColumn(dataUnit, col)) {
+ int dcVal = (dataUnit[c0] + 16) / 32;
+ dataUnit[c0] = dcVal;
+ dataUnit[c1] = dcVal;
+ dataUnit[c2] = dcVal;
+ dataUnit[c3] = dcVal;
+ dataUnit[c4] = dcVal;
+ dataUnit[c5] = dcVal;
+ dataUnit[c6] = dcVal;
+ dataUnit[c7] = dcVal;
+ } else {
+ /**
+ * Even part: reverse the even part of the forward DCT.
+ * The rotator is sqrt(2)*c(-6).
+ */
+ int z2 = dataUnit[c2];
+ int z3 = dataUnit[c6];
+ int z1 = (z2 + z3) * FIX_0_541196100;
+ int tmp2 = z1 + (z3 * (0 - FIX_1_847759065));
+ int tmp3 = z1 + (z2 * FIX_0_765366865);
+ int tmp0 = (dataUnit[c0] + dataUnit[c4]) * 8192;
+ int tmp1 = (dataUnit[c0] - dataUnit[c4]) * 8192;
+ int tmp10 = tmp0 + tmp3;
+ int tmp13 = tmp0 - tmp3;
+ int tmp11 = tmp1 + tmp2;
+ int tmp12 = tmp1 - tmp2;
+ /**
+ * Odd part per figure 8; the matrix is unitary and hence its
+ * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
+ */
+ tmp0 = dataUnit[c7];;
+ tmp1 = dataUnit[c5];
+ tmp2 = dataUnit[c3];
+ tmp3 = dataUnit[c1];
+ z1 = tmp0 + tmp3;
+ z2 = tmp1 + tmp2;
+ z3 = tmp0 + tmp2;
+ int z4 = tmp1 + tmp3;
+ int z5 = (z3 + z4) * FIX_1_175875602; /* sqrt(2) * c3 */
+
+ tmp0 = tmp0 * FIX_0_298631336; /* sqrt(2) * (-c1+c3+c5-c7) */
+ tmp1 = tmp1 * FIX_2_053119869; /* sqrt(2) * ( c1+c3-c5+c7) */
+ tmp2 = tmp2 * FIX_3_072711026; /* sqrt(2) * ( c1+c3+c5-c7) */
+ tmp3 = tmp3 * FIX_1_501321110; /* sqrt(2) * ( c1+c3-c5-c7) */
+ z1 = z1 * (0 - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
+ z2 = z2 * (0 - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
+ z3 = z3 * (0 - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
+ z4 = z4 * (0 - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
+
+ z3 = z3 + z5;
+ z4 = z4 + z5;
+
+ tmp0 = tmp0 + z1 + z3;
+ tmp1 = tmp1 + z2 + z4;
+ tmp2 = tmp2 + z2 + z3;
+ tmp3 = tmp3 + z1 + z4;
+
+ /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
+ int descaleFactor1 = ExtendTest[18];
+ int descaleFactor2 = ExtendTest[19];
+ dataUnit[c0] = (tmp10 + tmp3 + descaleFactor1) / descaleFactor2;
+ dataUnit[c7] = (tmp10 - tmp3 + descaleFactor1) / descaleFactor2;
+ dataUnit[c1] = (tmp11 + tmp2 + descaleFactor1) / descaleFactor2;
+ dataUnit[c6] = (tmp11 - tmp2 + descaleFactor1) / descaleFactor2;
+ dataUnit[c2] = (tmp12 + tmp1 + descaleFactor1) / descaleFactor2;
+ dataUnit[c5] = (tmp12 - tmp1 + descaleFactor1) / descaleFactor2;
+ dataUnit[c3] = (tmp13 + tmp0 + descaleFactor1) / descaleFactor2;
+ dataUnit[c4] = (tmp13 - tmp0 + descaleFactor1) / descaleFactor2;
+ }
+ }
+}
+public static boolean isJPEGFile(LEDataInputStream stream) {
+ try {
+ JPEGStartOfImage soi = new JPEGStartOfImage(stream);
+ byte[] header = new byte[16];
+ stream.read(header);
+ JPEGAppn appn = new JPEGAppn(header);
+ stream.unread(appn.reference);
+ stream.unread(soi.reference);
+ return soi.verify() && appn.verify();
+ // && appn.getSegmentMarker() == APP0; doesn't have to be app0
+ } catch (Exception e) {
+ return false;
+ }
+}
+boolean isZeroInColumn(int[] dataUnit, int col) {
+ return (dataUnit[col + 8] + dataUnit[col + 16] +
+ dataUnit[col + 24] + dataUnit[col + 32] +
+ dataUnit[col + 40] + dataUnit[col + 48] +
+ dataUnit[col + 56]) == 0;
+}
+boolean isZeroInRow(int[] dataUnit, int rIndex) {
+ return (dataUnit[rIndex + 1] + dataUnit[rIndex + 2] +
+ dataUnit[rIndex + 3] + dataUnit[rIndex + 4] +
+ dataUnit[rIndex + 5] + dataUnit[rIndex + 6] +
+ dataUnit[rIndex + 7]) == 0;
+}
+ImageData[] loadFromByteStream() {
+ JPEGStartOfImage soi = new JPEGStartOfImage(inputStream);
+ if (!soi.verify()) SWT.error(SWT.ERROR_INVALID_IMAGE);
+ restartInterval = 0;
+
+ /* Process the tables preceding the frame header. */
+ processTables();
+
+ /* Start of Frame. */
+ frameHeader = new JPEGFrameHeader(inputStream);
+ if (!frameHeader.verify()) SWT.error(SWT.ERROR_INVALID_IMAGE);
+ imageWidth = frameHeader.getSamplesPerLine();
+ imageHeight = frameHeader.getNumberOfLines();
+ maxH = frameHeader.getMaxHFactor();
+ maxV = frameHeader.getMaxVFactor();
+ int mcuWidth = maxH * DCTSIZE;
+ int mcuHeight = maxV * DCTSIZE;
+ interleavedMcuCols = (imageWidth + mcuWidth - 1) / mcuWidth;
+ interleavedMcuRows = (imageHeight + mcuHeight - 1) / mcuHeight;
+ progressive = frameHeader.isProgressive();
+ samplePrecision = frameHeader.getSamplePrecision();
+ nComponents = frameHeader.getNumberOfImageComponents();
+ frameComponents = frameHeader.componentParameters;
+ imageComponents = new byte[nComponents][];
+ if (progressive) {
+ // Progressive jpeg: need to keep all of the data units.
+ dataUnits = new int[nComponents][][];
+ } else {
+ // Sequential jpeg: only need one data unit.
+ dataUnit = new int[8 * 8];
+ }
+ for (int i = 0; i < nComponents; i++) {
+ int[] frameComponent = frameComponents[i];
+ int bufferSize = frameComponent[CW] * frameComponent[CH];
+ imageComponents[i] = new byte[bufferSize];
+ if (progressive) {
+ dataUnits[i] = new int[bufferSize][];
+ }
+ }
+
+ /* Process the tables preceding the scan header. */
+ processTables();
+
+ /* Start of Scan. */
+ scanHeader = new JPEGScanHeader(inputStream);
+ if (!scanHeader.verify()) SWT.error(SWT.ERROR_INVALID_IMAGE);
+
+ /* Process scan(s) and further tables until EOI. */
+ int progressiveScanCount = 0;
+ boolean done = false;
+ while(!done) {
+ resetInputBuffer();
+ precedingDCs = new int[4];
+ decodeScan();
+ if (progressive && loader.hasListeners()) {
+ ImageData imageData = createImageData();
+ loader.notifyListeners(new ImageLoaderEvent(loader, imageData, progressiveScanCount, false));
+ progressiveScanCount++;
+ }
+
+ /* Unread any buffered data before looking for tables again. */
+ int delta = 512 - bufferCurrentPosition - 1;
+ if (delta > 0) {
+ byte[] unreadBuffer = new byte[delta];
+ System.arraycopy(dataBuffer, bufferCurrentPosition + 1, unreadBuffer, 0, delta);
+ try {
+ inputStream.unread(unreadBuffer);
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ }
+
+ /* Process the tables preceding the next scan header. */
+ JPEGSegment jpegSegment = processTables();
+ if (jpegSegment == null || jpegSegment.getSegmentMarker() == EOI) {
+ done = true;
+ } else {
+ scanHeader = new JPEGScanHeader(inputStream);
+ if (!scanHeader.verify()) SWT.error(SWT.ERROR_INVALID_IMAGE);
+ }
+ }
+
+ if (progressive) {
+ for (int ymcu = 0; ymcu < interleavedMcuRows; ymcu++) {
+ for (int xmcu = 0; xmcu < interleavedMcuCols; xmcu++) {
+ for (int iComp = 0; iComp < nComponents; iComp++) {
+ int[] frameComponent = frameComponents[iComp];
+ int hi = frameComponent[HI];
+ int vi = frameComponent[VI];
+ int compWidth = frameComponent[CW];
+ for (int ivi = 0; ivi < vi; ivi++) {
+ for (int ihi = 0; ihi < hi; ihi++) {
+ int index = (ymcu * vi + ivi) * compWidth + xmcu * hi + ihi;
+ dataUnit = dataUnits[iComp][index];
+ dequantize(dataUnit, iComp);
+ inverseDCT(dataUnit);
+ storeData(dataUnit, iComp, xmcu, ymcu, hi, ihi, vi, ivi);
+ }
+ }
+ }
+ }
+ }
+ }
+ ImageData imageData = createImageData();
+ if (progressive && loader.hasListeners()) {
+ loader.notifyListeners(new ImageLoaderEvent(loader, imageData, progressiveScanCount, true));
+ }
+ return new ImageData[] {imageData};
+}
+ImageData createImageData() {
+ return ImageData.internal_new(
+ imageWidth,
+ imageHeight,
+ nComponents * samplePrecision,
+ setUpPalette(),
+ nComponents == 1 ? 4 : 1,
+ decodeImageComponents(),
+ 0,
+ null,
+ null,
+ -1,
+ -1,
+ SWT.IMAGE_JPEG,
+ 0,
+ 0,
+ 0,
+ 0);
+}
+int nextBit() {
+ if (currentBitCount != 0) {
+ currentBitCount--;
+ currentByte *= 2;
+ if (currentByte > 255) {
+ currentByte -= 256;
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ bufferCurrentPosition++;
+ if (bufferCurrentPosition >= 512) {
+ resetInputBuffer();
+ bufferCurrentPosition = 0;
+ }
+ currentByte = dataBuffer[bufferCurrentPosition] & 0xFF;
+ currentBitCount = 8;
+ byte nextByte;
+ if (bufferCurrentPosition == 511) {
+ resetInputBuffer();
+ currentBitCount = 8;
+ nextByte = dataBuffer[0];
+ } else {
+ nextByte = dataBuffer[bufferCurrentPosition + 1];
+ }
+ if (currentByte == 0xFF) {
+ if (nextByte == 0) {
+ bufferCurrentPosition ++;
+ currentBitCount--;
+ currentByte *= 2;
+ if (currentByte > 255) {
+ currentByte -= 256;
+ return 1;
+ } else {
+ return 0;
+ }
+ } else {
+ if ((nextByte & 0xFF) + 0xFF00 == DNL) {
+ getDNL();
+ return 0;
+ } else {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ return 0;
+ }
+ }
+ } else {
+ currentBitCount--;
+ currentByte *= 2;
+ if (currentByte > 255) {
+ currentByte -= 256;
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+}
+void processRestartInterval() {
+ do {
+ bufferCurrentPosition++;
+ if (bufferCurrentPosition > 511) {
+ resetInputBuffer();
+ bufferCurrentPosition = 0;
+ }
+ currentByte = dataBuffer[bufferCurrentPosition] & 0xFF;
+ } while (currentByte != 0xFF);
+ while (currentByte == 0xFF) {
+ bufferCurrentPosition++;
+ if (bufferCurrentPosition > 511) {
+ resetInputBuffer();
+ bufferCurrentPosition = 0;
+ }
+ currentByte = dataBuffer[bufferCurrentPosition] & 0xFF;
+ }
+ if (currentByte != ((RST0 + nextRestartNumber) % 256)) {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ }
+ bufferCurrentPosition++;
+ if (bufferCurrentPosition > 511) {
+ resetInputBuffer();
+ bufferCurrentPosition = 0;
+ }
+ currentByte = dataBuffer[bufferCurrentPosition] & 0xFF;
+ currentBitCount = 8;
+ restartsToGo = restartInterval;
+ nextRestartNumber = (nextRestartNumber + 1) % 8;
+ precedingDCs = new int[4];
+ eobrun = 0;
+}
+/* Process all markers until a frame header, scan header, or EOI is found. */
+JPEGSegment processTables() {
+ while (true) {
+ JPEGSegment jpegSegment = seekUnspecifiedMarker(inputStream);
+ if (jpegSegment == null) return null;
+ JPEGFrameHeader sof = new JPEGFrameHeader(jpegSegment.reference);
+ if (sof.verify()) {
+ return jpegSegment;
+ }
+ int marker = jpegSegment.getSegmentMarker();
+ switch (marker) {
+ case SOI: // there should only be one SOI per file
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ case EOI:
+ case SOS:
+ return jpegSegment;
+ case DQT:
+ getDQT();
+ break;
+ case DHT:
+ getDHT();
+ break;
+ case DAC:
+ getDAC();
+ break;
+ case DRI:
+ getDRI();
+ break;
+ case APP0:
+ getAPP0();
+ break;
+ case COM:
+ getCOM();
+ break;
+ default:
+ skipSegmentFrom(inputStream);
+
+ }
+ }
+}
+void quantizeData(int[] dataUnit, int iComp) {
+ int[] qTable = quantizationTables[frameComponents[iComp][TQI]];
+ for (int i = 0; i < dataUnit.length; i++) {
+ int zzIndex = ZigZag8x8[i];
+ int data = dataUnit[zzIndex];
+ int absData = data < 0 ? 0 - data : data;
+ int qValue = qTable[i];
+ int q2 = qValue / 2;
+ absData += q2;
+ if (absData < qValue) {
+ dataUnit[zzIndex] = 0;
+ } else {
+ absData /= qValue;
+ if (data >= 0) {
+ dataUnit[zzIndex] = absData;
+ } else {
+ dataUnit[zzIndex] = 0 - absData;
+ }
+ }
+ }
+}
+int receive(int nBits) {
+ int v = 0;
+ for (int i = 0; i < nBits; i++) {
+ v = v * 2 + nextBit();
+ }
+ return v;
+}
+void resetInputBuffer() {
+ if (dataBuffer == null) {
+ dataBuffer = new byte[512];
+ }
+ try {
+ inputStream.read(dataBuffer);
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ currentBitCount = 0;
+ bufferCurrentPosition = -1;
+}
+void resetOutputBuffer() {
+ if (dataBuffer == null) {
+ dataBuffer = new byte[512];
+ } else {
+ try {
+ outputStream.write(dataBuffer, 0, bufferCurrentPosition);
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ }
+ bufferCurrentPosition = 0;
+}
+static JPEGSegment seekUnspecifiedMarker(LEDataInputStream byteStream) {
+ byte[] byteArray = new byte[2];
+ try {
+ while (true) {
+ if (byteStream.read(byteArray, 0, 1) != 1) return null;
+ if (byteArray[0] == (byte) 0xFF) {
+ if (byteStream.read(byteArray, 1, 1) != 1) return null;
+ if (byteArray[1] != (byte) 0xFF && byteArray[1] != 0) {
+ byteStream.unread(byteArray);
+ return new JPEGSegment(byteArray);
+ }
+ }
+ }
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ return null;
+}
+PaletteData setUpPalette() {
+ if (nComponents == 1) {
+ RGB[] entries = new RGB[256];
+ for (int i = 0; i < 256; i++) {
+ entries[i] = new RGB(i, i, i);
+ }
+ return new PaletteData(entries);
+ }
+ return new PaletteData(0xFF, 0xFF00, 0xFF0000);
+}
+static void skipSegmentFrom(LEDataInputStream byteStream) {
+ try {
+ byte[] byteArray = new byte[4];
+ JPEGSegment jpegSegment = new JPEGSegment(byteArray);
+
+ if (byteStream.read(byteArray) != byteArray.length) {
+ throw new SWTError(SWT.ERROR_INVALID_IMAGE);
+ }
+ if (!(byteArray[0] == -1 && byteArray[1] != 0 && byteArray[1] != -1)) {
+ throw new SWTError(SWT.ERROR_INVALID_IMAGE);
+ }
+ int delta = jpegSegment.getSegmentLength() - 2;
+ byteStream.skip(delta);
+ } catch (Exception e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+}
+void storeData(int[] dataUnit, int iComp, int xmcu, int ymcu, int hi, int ihi, int vi, int ivi) {
+ byte[] compImage = imageComponents[iComp];
+ int[] frameComponent = frameComponents[iComp];
+ int compWidth = frameComponent[CW];
+ int destIndex = ((ymcu * vi + ivi) * compWidth * DCTSIZE) + ((xmcu * hi + ihi) * DCTSIZE);
+ int srcIndex = 0;
+ for (int i = 0; i < DCTSIZE; i++) {
+ for (int col = 0; col < DCTSIZE; col++) {
+ int x = dataUnit[srcIndex] + 128;
+ if (x < 0) {
+ x = 0;
+ } else {
+ if (x > 255) x = 255;
+ }
+ compImage[destIndex + col] = (byte)x;
+ srcIndex++;
+ }
+ destIndex += compWidth;
+ }
+}
+void unloadIntoByteStream(ImageData image) {
+ if (!new JPEGStartOfImage().writeToStream(outputStream)) {
+ SWT.error(SWT.ERROR_IO);
+ }
+ JPEGAppn appn = new JPEGAppn(new byte[] {(byte)0xFF, (byte)0xE0, 0, 0x10, 0x4A, 0x46, 0x49, 0x46, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0});
+ if (!appn.writeToStream(outputStream)) {
+ SWT.error(SWT.ERROR_IO);
+ }
+ quantizationTables = new int[4][];
+ JPEGQuantizationTable chromDQT = JPEGQuantizationTable.defaultChrominanceTable();
+ chromDQT.scaleBy(encoderQFactor);
+ int[] jpegDQTKeys = chromDQT.getQuantizationTablesKeys();
+ int[][] jpegDQTValues = chromDQT.getQuantizationTablesValues();
+ for (int i = 0; i < jpegDQTKeys.length; i++) {
+ quantizationTables[jpegDQTKeys[i]] = jpegDQTValues[i];
+ }
+ JPEGQuantizationTable lumDQT = JPEGQuantizationTable.defaultLuminanceTable();
+ lumDQT.scaleBy(encoderQFactor);
+ jpegDQTKeys = lumDQT.getQuantizationTablesKeys();
+ jpegDQTValues = lumDQT.getQuantizationTablesValues();
+ for (int i = 0; i < jpegDQTKeys.length; i++) {
+ quantizationTables[jpegDQTKeys[i]] = jpegDQTValues[i];
+ }
+ if (!lumDQT.writeToStream(outputStream)) {
+ SWT.error(SWT.ERROR_IO);
+ }
+ if (!chromDQT.writeToStream(outputStream)) {
+ SWT.error(SWT.ERROR_IO);
+ }
+ int frameLength, scanLength, precision;
+ int[][] frameParams, scanParams;
+ if (image.depth == 1) {
+ frameLength = 11;
+ frameParams = new int[1][];
+ frameParams[0] = new int[] {1, 1, 1, 0, 0};
+ scanParams = new int[1][];
+ scanParams[0] = new int[] {0, 0};
+ scanLength = 8;
+ nComponents = 1;
+ precision = 1;
+ } else {
+ frameLength = 17;
+ frameParams = new int[3][];
+ frameParams[0] = new int[] {0, 2, 2, 0, 0};
+ frameParams[1] = new int[] {1, 1, 1, 0, 0};
+ frameParams[2] = new int[] {1, 1, 1, 0, 0};
+ scanParams = new int[3][];
+ scanParams[0] = new int[] {0, 0};
+ scanParams[1] = new int[] {1, 1};
+ scanParams[2] = new int[] {1, 1};
+ scanLength = 12;
+ nComponents = 3;
+ precision = 8;
+ }
+ imageWidth = image.width;
+ imageHeight = image.height;
+ frameHeader = new JPEGFrameHeader(new byte[19]);
+ frameHeader.setSegmentMarker(SOF0);
+ frameHeader.setSegmentLength(frameLength);
+ frameHeader.setSamplePrecision(precision);
+ frameHeader.setSamplesPerLine(imageWidth);
+ frameHeader.setNumberOfLines(imageHeight);
+ frameHeader.setNumberOfImageComponents(nComponents);
+ frameHeader.componentParameters = frameParams;
+ frameHeader.initializeContents();
+ if (!frameHeader.writeToStream(outputStream)) {
+ SWT.error(SWT.ERROR_IO);
+ }
+ frameComponents = frameParams;
+ maxH = frameHeader.getMaxHFactor();
+ maxV = frameHeader.getMaxVFactor();
+ int mcuWidth = maxH * DCTSIZE;
+ int mcuHeight = maxV * DCTSIZE;
+ interleavedMcuCols = (imageWidth + mcuWidth - 1) / mcuWidth;
+ interleavedMcuRows = (imageHeight + mcuHeight - 1) / mcuHeight;
+ JPEGHuffmanTable[] acHuffmanTables = new JPEGHuffmanTable[4];
+ JPEGHuffmanTable[] dcHuffmanTables = new JPEGHuffmanTable[4];
+ JPEGHuffmanTable[] dhtTables = new JPEGHuffmanTable[] {
+ JPEGHuffmanTable.getDefaultDCLuminanceTable(),
+ JPEGHuffmanTable.getDefaultDCChrominanceTable(),
+ JPEGHuffmanTable.getDefaultACLuminanceTable(),
+ JPEGHuffmanTable.getDefaultACChrominanceTable()
+ };
+ for (int i = 0; i < dhtTables.length; i++) {
+ JPEGHuffmanTable dhtTable = dhtTables[i];
+ if (!dhtTable.writeToStream(outputStream)) {
+ SWT.error(SWT.ERROR_IO);
+ }
+ JPEGHuffmanTable[] allTables = dhtTable.getAllTables();
+ for (int j = 0; j < allTables.length; j++) {
+ JPEGHuffmanTable huffmanTable = allTables[j];
+ if (huffmanTable.getTableClass() == 0) {
+ dcHuffmanTables[huffmanTable.getTableIdentifier()] = huffmanTable;
+ } else {
+ acHuffmanTables[huffmanTable.getTableIdentifier()] = huffmanTable;
+ }
+ }
+ }
+ precedingDCs = new int[4];
+ scanHeader = new JPEGScanHeader(new byte[14]);
+ scanHeader.setSegmentMarker(SOS);
+ scanHeader.setSegmentLength(scanLength);
+ scanHeader.setNumberOfImageComponents(nComponents);
+ scanHeader.setStartOfSpectralSelection(0);
+ scanHeader.setEndOfSpectralSelection(63);
+ scanHeader.componentParameters = scanParams;
+ scanHeader.initializeContents();
+ if (!scanHeader.writeToStream(outputStream)) {
+ SWT.error(SWT.ERROR_IO);
+ }
+ convertImageToYCbCr(image);
+ resetOutputBuffer();
+ currentByte = 0;
+ currentBitCount = 0;
+ encodeScan();
+ if (!new JPEGEndOfImage().writeToStream(outputStream)) {
+ SWT.error(SWT.ERROR_IO);
+ }
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGFixedSizeSegment.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGFixedSizeSegment.java
new file mode 100755
index 0000000000..9bf9191e51
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGFixedSizeSegment.java
@@ -0,0 +1,38 @@
+package org.eclipse.swt.internal.image;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.eclipse.swt.*;
+
+abstract class JPEGFixedSizeSegment extends JPEGSegment {
+
+ public JPEGFixedSizeSegment() {
+ reference = new byte[fixedSize()];
+ setSegmentMarker(signature());
+ }
+
+ public JPEGFixedSizeSegment(byte[] reference) {
+ super(reference);
+ }
+
+ public JPEGFixedSizeSegment(LEDataInputStream byteStream) {
+ reference = new byte[fixedSize()];
+ try {
+ byteStream.read(reference);
+ } catch (Exception e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ }
+
+ abstract public int fixedSize();
+
+ public int getSegmentLength() {
+ return fixedSize() - 2;
+ }
+
+ public void setSegmentLength(int length) {
+ }
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGFrameHeader.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGFrameHeader.java
new file mode 100755
index 0000000000..be2cf6c6d3
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGFrameHeader.java
@@ -0,0 +1,203 @@
+package org.eclipse.swt.internal.image;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.eclipse.swt.*;
+
+final class JPEGFrameHeader extends JPEGVariableSizeSegment {
+ int maxVFactor;
+ int maxHFactor;
+ public int[][] componentParameters;
+
+ public JPEGFrameHeader(byte[] reference) {
+ super(reference);
+ }
+
+ public JPEGFrameHeader(LEDataInputStream byteStream) {
+ super(byteStream);
+ initializeComponentParameters();
+ }
+
+ public int getSamplePrecision() {
+ return reference[4] & 0xFF;
+ }
+
+ public int getNumberOfLines() {
+ return (reference[5] & 0xFF) << 8 | (reference[6] & 0xFF);
+ }
+
+ public int getSamplesPerLine() {
+ return (reference[7] & 0xFF) << 8 | (reference[8] & 0xFF);
+ }
+
+ public int getNumberOfImageComponents() {
+ return reference[9] & 0xFF;
+ }
+
+ public void setSamplePrecision(int precision) {
+ reference[4] = (byte)(precision & 0xFF);
+ }
+
+ public void setNumberOfLines(int anInteger) {
+ reference[5] = (byte)((anInteger & 0xFF00) >> 8);
+ reference[6] = (byte)(anInteger & 0xFF);
+ }
+
+ public void setSamplesPerLine(int samples) {
+ reference[7] = (byte)((samples & 0xFF00) >> 8);
+ reference[8] = (byte)(samples & 0xFF);
+ }
+
+ public void setNumberOfImageComponents(int anInteger) {
+ reference[9] = (byte)(anInteger & 0xFF);
+ }
+
+ public int getMaxHFactor() {
+ return maxHFactor;
+ }
+
+ public int getMaxVFactor() {
+ return maxVFactor;
+ }
+
+ public void setMaxHFactor(int anInteger) {
+ maxHFactor = anInteger;
+ }
+
+ public void setMaxVFactor(int anInteger) {
+ maxVFactor = anInteger;
+ }
+
+ void initializeComponentParameters() {
+ int nf = getNumberOfImageComponents();
+ int[][] compSpecParams = new int[0][];
+ int hmax = 1;
+ int vmax = 1;
+ for (int i = 0; i < nf; i++) {
+ int ofs = i * 3 + 10;
+ int ci = reference[ofs] & 0xFF;
+ int hi = (reference[ofs + 1] & 0xFF) / 16;
+ int vi = (reference[ofs + 1] & 0xFF) % 16;
+ int tqi = reference[ofs + 2] & 0xFF;
+ if (hi > hmax) {
+ hmax = hi;
+ }
+ if (vi > vmax) {
+ vmax = vi;
+ }
+ int[] compParam = new int[5];
+ compParam[0] = tqi;
+ compParam[1] = hi;
+ compParam[2] = vi;
+ if (compSpecParams.length < ci) {
+ int[][] newParams = new int[ci][];
+ System.arraycopy(compSpecParams, 0, newParams, 0, compSpecParams.length);
+ compSpecParams = newParams;
+ }
+ compSpecParams[ci - 1] = compParam;
+ }
+ int x = getSamplesPerLine();
+ int y = getNumberOfLines();
+ int[] multiples = new int[] { 8, 16, 24, 32 };
+ for (int i = 0; i < compSpecParams.length; i++) {
+ int[] compParam = compSpecParams[i];
+ int hi = compParam[1];
+ int vi = compParam[2];
+ int compWidth = (x * hi + hmax - 1) / hmax;
+ int compHeight = (y * vi + vmax - 1) / vmax;
+ int dsWidth = roundUpToMultiple(compWidth, multiples[hi - 1]);
+ int dsHeight = roundUpToMultiple(compHeight, multiples[vi - 1]);
+ compParam[3] = dsWidth;
+ compParam[4] = dsHeight;
+ }
+ setMaxHFactor(hmax);
+ setMaxVFactor(vmax);
+ componentParameters = compSpecParams;
+ }
+
+ public void initializeContents() {
+ int nf = getNumberOfImageComponents();
+ if (nf == 0 || nf != componentParameters.length) {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ }
+ int hmax = 0;
+ int vmax = 0;
+ int[][] compSpecParams = componentParameters;
+ for (int i = 0; i < nf; i++) {
+ int ofs = i * 3 + 10;
+ int[] compParam = compSpecParams[i];
+ int hi = compParam[1];
+ int vi = compParam[2];
+ if (hi * vi > 4) {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ }
+ reference[ofs] = (byte)(i + 1);
+ reference[ofs + 1] = (byte)(hi * 16 + vi);
+ reference[ofs + 2] = (byte)(compParam[0]);
+ if (hi > hmax) hmax = hi;
+ if (vi > vmax) vmax = vi;
+ }
+ int x = getSamplesPerLine();
+ int y = getNumberOfLines();
+ int[] multiples = new int[] {8, 16, 24, 32};
+ for (int i = 0; i < compSpecParams.length; i++) {
+ int[] compParam = compSpecParams[i];
+ int hi = compParam[1];
+ int vi = compParam[2];
+ int compWidth = (x * hi + hmax - 1) / hmax;
+ int compHeight = (y * vi + vmax - 1) / vmax;
+ int dsWidth = roundUpToMultiple(compWidth, multiples[hi - 1]);
+ int dsHeight = roundUpToMultiple(compHeight, multiples[vi - 1]);
+ compParam[3] = dsWidth;
+ compParam[4] = dsHeight;
+ }
+ setMaxHFactor(hmax);
+ setMaxVFactor(vmax);
+ }
+
+ int roundUpToMultiple(int anInteger, int mInteger) {
+ int a = anInteger + mInteger - 1;
+ return a - (a % mInteger);
+ }
+
+ /*
+ * Verify the information contained in the receiver is correct.
+ * Answer true if the header contains a valid marker. Otherwise,
+ * answer false. Valid Start Of Frame markers are:
+ * SOF_0 - Baseline DCT, Huffman coding
+ * SOF_1 - Extended sequential DCT, Huffman coding
+ * SOF_2 - Progressive DCT, Huffman coding
+ * SOF_3 - Lossless (sequential), Huffman coding
+ * SOF_5 - Differential sequential, Huffman coding
+ * SOF_6 - Differential progressive, Huffman coding
+ * SOF_7 - Differential lossless, Huffman coding
+ * SOF_9 - Extended sequential DCT, arithmetic coding
+ * SOF_10 - Progressive DCT, arithmetic coding
+ * SOF_11 - Lossless (sequential), arithmetic coding
+ * SOF_13 - Differential sequential, arithmetic coding
+ * SOF_14 - Differential progressive, arithmetic coding
+ * SOF_15 - Differential lossless, arithmetic coding
+ */
+ public boolean verify() {
+ int marker = getSegmentMarker();
+ return (marker >= JPEGFileFormat.SOF0 && marker <= JPEGFileFormat.SOF3) ||
+ (marker >= JPEGFileFormat.SOF5 && marker <= JPEGFileFormat.SOF7) ||
+ (marker >= JPEGFileFormat.SOF9 && marker <= JPEGFileFormat.SOF11) ||
+ (marker >= JPEGFileFormat.SOF13 && marker <= JPEGFileFormat.SOF15);
+ }
+
+ public boolean isProgressive() {
+ int marker = getSegmentMarker();
+ return marker == JPEGFileFormat.SOF2
+ || marker == JPEGFileFormat.SOF6
+ || marker == JPEGFileFormat.SOF10
+ || marker == JPEGFileFormat.SOF14;
+ }
+
+ public boolean isArithmeticCoding() {
+ return getSegmentMarker() >= JPEGFileFormat.SOF9;
+ }
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGHuffmanTable.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGHuffmanTable.java
new file mode 100755
index 0000000000..fc50d691e9
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGHuffmanTable.java
@@ -0,0 +1,262 @@
+package org.eclipse.swt.internal.image;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp 2000
+ */
+
+/**
+ * JPEGHuffmanTable class actually represents two types of object:
+ * 1) A DHT (Define Huffman Tables) segment, which may represent
+ * as many as 4 Huffman tables. In this case, the tables are
+ * stored in the allTables array.
+ * 2) A single Huffman table. In this case, the allTables array
+ * will be null.
+ * The 'reference' field is stored in both types of object, but
+ * 'initialize' is only called if the object represents a DHT.
+ */
+final class JPEGHuffmanTable extends JPEGVariableSizeSegment {
+ JPEGHuffmanTable[] allTables;
+ int tableClass;
+ int tableIdentifier;
+ int[] dhCodes;
+ int[] dhCodeLengths;
+ int[] dhMaxCodes;
+ int[] dhMinCodes;
+ int[] dhValPtrs;
+ int[] dhValues;
+ int[] ehCodes;
+ byte[] ehCodeLengths;
+ static byte[] DCLuminanceTable = {
+ (byte)255, (byte)196, 0, 31, 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
+ };
+ static byte[] DCChrominanceTable = {
+ (byte)255, (byte)196, 0, 31, 1, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
+ };
+ static byte[] ACLuminanceTable = {
+ (byte)255, (byte)196, 0, (byte)181, 16, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 125,
+ 1, 2, 3, 0, 4, 17, 5, 18, 33, 49, 65, 6, 19, 81, 97, 7, 34, 113, 20,
+ 50, (byte)129, (byte)145, (byte)161, 8, 35, 66, (byte)177, (byte)193, 21, 82, (byte)209, (byte)240, 36, 51, 98,
+ 114, (byte)130, 9, 10, 22, 23, 24, 25, 26, 37, 38, 39, 40, 41, 42, 52, 53,
+ 54, 55, 56, 57, 58, 67, 68, 69, 70, 71, 72, 73, 74, 83, 84, 85, 86, 87,
+ 88, 89, 90, 99, 100, 101, 102, 103, 104, 105, 106, 115, 116, 117, 118,
+ 119, 120, 121, 122, (byte)131, (byte)132, (byte)133, (byte)134, (byte)135, (byte)136, (byte)137, (byte)138, (byte)146, (byte)147, (byte)148,
+ (byte)149, (byte)150, (byte)151, (byte)152, (byte)153, (byte)154, (byte)162, (byte)163, (byte)164, (byte)165, (byte)166, (byte)167, (byte)168, (byte)169, (byte)170,
+ (byte)178, (byte)179, (byte)180, (byte)181, (byte)182, (byte)183, (byte)184, (byte)185, (byte)186, (byte)194, (byte)195, (byte)196, (byte)197, (byte)198, (byte)199,
+ (byte)200, (byte)201, (byte)202, (byte)210, (byte)211, (byte)212, (byte)213, (byte)214, (byte)215, (byte)216, (byte)217, (byte)218, (byte)225, (byte)226, (byte)227,
+ (byte)228, (byte)229, (byte)230, (byte)231, (byte)232, (byte)233, (byte)234, (byte)241, (byte)242, (byte)243, (byte)244, (byte)245, (byte)246, (byte)247, (byte)248,
+ (byte)249, (byte)250
+ };
+ static byte[] ACChrominanceTable = {
+ (byte)255, (byte)196, 0, (byte)181, 17, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0,
+ 1, 2, 119, 0, 1, 2, 3, 17, 4, 5, 33, 49, 6, 18, 65, 81, 7, 97, 113, 19, 34,
+ 50, (byte)129, 8, 20, 66, (byte)145, (byte)161, (byte)177, (byte)193, 9, 35,
+ 51, 82, (byte)240, 21, 98, 114, (byte)209, 10, 22, 36, 52, (byte)225, 37,
+ (byte)241, 23, 24, 25, 26, 38, 39, 40, 41, 42, 53, 54, 55, 56, 57, 58, 67,
+ 68, 69, 70, 71, 72, 73, 74, 83, 84, 85, 86, 87, 88, 89, 90, 99, 100, 101, 102,
+ 103, 104, 105, 106, 115, 116, 117, 118, 119, 120, 121, 122, (byte)130,
+ (byte)131, (byte)132, (byte)133, (byte)134, (byte)135, (byte)136, (byte)137,
+ (byte)138, (byte)146, (byte)147, (byte)148, (byte)149, (byte)150, (byte)151,
+ (byte)152, (byte)153, (byte)154, (byte)162, (byte)163, (byte)164, (byte)165,
+ (byte)166, (byte)167, (byte)168, (byte)169, (byte)170, (byte)178, (byte)179,
+ (byte)180, (byte)181, (byte)182, (byte)183, (byte)184, (byte)185, (byte)186,
+ (byte)194, (byte)195, (byte)196, (byte)197, (byte)198, (byte)199, (byte)200,
+ (byte)201, (byte)202, (byte)210, (byte)211, (byte)212, (byte)213, (byte)214,
+ (byte)215, (byte)216, (byte)217, (byte)218, (byte)226, (byte)227, (byte)228,
+ (byte)229, (byte)230, (byte)231, (byte)232, (byte)233, (byte)234, (byte)242,
+ (byte)243, (byte)244, (byte)245, (byte)246, (byte)247, (byte)248, (byte)249,
+ (byte)250
+ };
+
+public JPEGHuffmanTable(byte[] reference) {
+ super(reference);
+}
+
+public JPEGHuffmanTable(LEDataInputStream byteStream) {
+ super(byteStream);
+ initialize();
+}
+
+public JPEGHuffmanTable[] getAllTables() {
+ return allTables;
+}
+
+public static JPEGHuffmanTable getDefaultACChrominanceTable() {
+ JPEGHuffmanTable result = new JPEGHuffmanTable(ACChrominanceTable);
+ result.initialize();
+ return result;
+}
+
+public static JPEGHuffmanTable getDefaultACLuminanceTable() {
+ JPEGHuffmanTable result = new JPEGHuffmanTable(ACLuminanceTable);
+ result.initialize();
+ return result;
+}
+
+public static JPEGHuffmanTable getDefaultDCChrominanceTable() {
+ JPEGHuffmanTable result = new JPEGHuffmanTable(DCChrominanceTable);
+ result.initialize();
+ return result;
+}
+
+public static JPEGHuffmanTable getDefaultDCLuminanceTable() {
+ JPEGHuffmanTable result = new JPEGHuffmanTable(DCLuminanceTable);
+ result.initialize();
+ return result;
+}
+
+public int[] getDhMaxCodes() {
+ return dhMaxCodes;
+}
+
+public int[] getDhMinCodes() {
+ return dhMinCodes;
+}
+
+public int[] getDhValPtrs() {
+ return dhValPtrs;
+}
+
+public int[] getDhValues() {
+ return dhValues;
+}
+
+public int getTableClass() {
+ return tableClass;
+}
+
+public int getTableIdentifier() {
+ return tableIdentifier;
+}
+
+void initialize() {
+ int totalLength = getSegmentLength() - 2;
+ int ofs = 4;
+ int[] bits = new int[16];
+ JPEGHuffmanTable[] huffTables = new JPEGHuffmanTable[8]; // maximum is 4 AC + 4 DC
+ int huffTableCount = 0;
+ while (totalLength > 0) {
+ int tc = (reference[ofs] & 0xFF) / 16; // table class: AC (1) or DC (0)
+ int tid = (reference[ofs] & 0xFF) % 16; // table id: 0-1 baseline, 0-3 prog/ext
+ ofs++;
+
+ /* Read the 16 count bytes and add them together to get the table size. */
+ int count = 0;
+ for (int i = 0; i < bits.length; i++) {
+ int bCount = reference[ofs + i] & 0xFF;
+ bits[i] = bCount;
+ count += bCount;
+ }
+ ofs += 16;
+ totalLength -= 17;
+
+ /* Read the table. */
+ int[] huffVals = new int[count];
+ for (int i = 0; i < count; i++) {
+ huffVals[i] = reference[ofs + i] & 0xFF;
+ }
+ ofs += count;
+ totalLength -= count;
+
+ /* Calculate the lengths. */
+ int[] huffCodeLengths = new int[50]; // start with 50 and increment as needed
+ int huffCodeLengthsIndex = 0;
+ for (int i = 0; i < 16; i++) {
+ for (int j = 0; j < bits[i]; j++) {
+ if (huffCodeLengthsIndex >= huffCodeLengths.length) {
+ int[] newHuffCodeLengths = new int[huffCodeLengths.length + 50];
+ System.arraycopy(huffCodeLengths, 0, newHuffCodeLengths, 0, huffCodeLengths.length);
+ huffCodeLengths = newHuffCodeLengths;
+ }
+ huffCodeLengths[huffCodeLengthsIndex] = i + 1;
+ huffCodeLengthsIndex++;
+ }
+ }
+
+ /* Truncate huffCodeLengths to the correct size. */
+ if (huffCodeLengthsIndex < huffCodeLengths.length) {
+ int[] newHuffCodeLengths = new int[huffCodeLengthsIndex];
+ System.arraycopy(huffCodeLengths, 0, newHuffCodeLengths, 0, huffCodeLengthsIndex);
+ huffCodeLengths = newHuffCodeLengths;
+ }
+
+ /* Calculate the Huffman codes. */
+ int[] huffCodes = new int[50]; // start with 50 and increment as needed
+ int huffCodesIndex = 0;
+ int k = 1;
+ int code = 0;
+ int si = huffCodeLengths[0];
+ int p = 0;
+ while (p < huffCodeLengthsIndex) {
+ while ((p < huffCodeLengthsIndex) && (huffCodeLengths[p] == si)) {
+ if (huffCodesIndex >= huffCodes.length) {
+ int[] newHuffCodes = new int[huffCodes.length + 50];
+ System.arraycopy(huffCodes, 0, newHuffCodes, 0, huffCodes.length);
+ huffCodes = newHuffCodes;
+ }
+ huffCodes[huffCodesIndex] = code;
+ huffCodesIndex++;
+ code++;
+ p++;
+ }
+ code *= 2;
+ si++;
+ }
+
+ /* Truncate huffCodes to the correct size. */
+ if (huffCodesIndex < huffCodes.length) {
+ int[] newHuffCodes = new int[huffCodesIndex];
+ System.arraycopy(huffCodes, 0, newHuffCodes, 0, huffCodesIndex);
+ huffCodes = newHuffCodes;
+ }
+
+ /* Calculate the maximum and minimum codes */
+ k = 0;
+ int[] maxCodes = new int[16];
+ int[] minCodes = new int[16];
+ int[] valPtrs = new int[16];
+ for (int i = 0; i < 16; i++) {
+ int bSize = bits[i];
+ if (bSize == 0) {
+ maxCodes[i] = -1;
+ } else {
+ valPtrs[i] = k;
+ minCodes[i] = huffCodes[k];
+ k += bSize;
+ maxCodes[i] = huffCodes[k - 1];
+ }
+ }
+
+ /* Calculate the eHuffman codes and lengths. */
+ int[] eHuffCodes = new int[256];
+ byte[] eHuffSize = new byte[256];
+ for (int i = 0; i < huffCodesIndex; i++) {
+ eHuffCodes[huffVals[i]] = huffCodes[i];
+ eHuffSize[huffVals[i]] = (byte)huffCodeLengths[i];
+ }
+
+ /* Create the new JPEGHuffmanTable and add it to the allTables array. */
+ JPEGHuffmanTable dhtTable = new JPEGHuffmanTable(reference);
+ dhtTable.tableClass = tc;
+ dhtTable.tableIdentifier = tid;
+ dhtTable.dhValues = huffVals;
+ dhtTable.dhCodes = huffCodes;
+ dhtTable.dhCodeLengths = huffCodeLengths;
+ dhtTable.dhMinCodes = minCodes;
+ dhtTable.dhMaxCodes = maxCodes;
+ dhtTable.dhValPtrs = valPtrs;
+ dhtTable.ehCodes = eHuffCodes;
+ dhtTable.ehCodeLengths = eHuffSize;
+ huffTables[huffTableCount] = dhtTable;
+ huffTableCount++;
+ }
+ allTables = new JPEGHuffmanTable[huffTableCount];
+ System.arraycopy(huffTables, 0, allTables, 0, huffTableCount);
+}
+
+public int signature() {
+ return JPEGFileFormat.DHT;
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGQuantizationTable.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGQuantizationTable.java
new file mode 100755
index 0000000000..47405a44c6
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGQuantizationTable.java
@@ -0,0 +1,159 @@
+package org.eclipse.swt.internal.image;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp 2000
+ */
+
+final class JPEGQuantizationTable extends JPEGVariableSizeSegment {
+ public static byte[] DefaultLuminanceQTable = {
+ (byte)255, (byte)219, 0, 67, 0,
+ 16, 11, 10, 16, 24, 40, 51, 61,
+ 12, 12, 14, 19, 26, 58, 60, 55,
+ 14, 13, 16, 24, 40, 57, 69, 56,
+ 14, 17, 22, 29, 51, 87, 80, 62,
+ 18, 22, 37, 56, 68, 109, 103, 77,
+ 24, 35, 55, 64, 81, 104, 113, 92,
+ 49, 64, 78, 87, 103, 121, 120, 101,
+ 72, 92, 95, 98, 112, 100, 103, 99
+ };
+ public static byte[] DefaultChrominanceQTable = {
+ (byte)255, (byte)219, 0, 67, 1,
+ 17, 18, 24, 47, 99, 99, 99, 99,
+ 18, 21, 26, 66, 99, 99, 99, 99,
+ 24, 26, 56, 99, 99, 99, 99, 99,
+ 47, 66, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99
+ };
+
+public JPEGQuantizationTable(byte[] reference) {
+ super(reference);
+}
+
+public JPEGQuantizationTable(LEDataInputStream byteStream) {
+ super(byteStream);
+}
+
+public static JPEGQuantizationTable defaultChrominanceTable() {
+ byte[] data = new byte[DefaultChrominanceQTable.length];
+ System.arraycopy(DefaultChrominanceQTable, 0, data, 0, data.length);
+ return new JPEGQuantizationTable(data);
+}
+
+public static JPEGQuantizationTable defaultLuminanceTable() {
+ byte[] data = new byte[DefaultLuminanceQTable.length];
+ System.arraycopy(DefaultLuminanceQTable, 0, data, 0, data.length);
+ return new JPEGQuantizationTable(data);
+}
+
+public int[] getQuantizationTablesKeys() {
+ int[] keys = new int[4];
+ int keysIndex = 0;
+ int totalLength = getSegmentLength() - 2;
+ int ofs = 4;
+ while (totalLength > 64) {
+ int tq = (reference[ofs] & 0xFF) % 16;
+ int pq = (reference[ofs] & 0xFF) / 16;
+ if (pq == 0) {
+ ofs += 65;
+ totalLength -= 65;
+ } else {
+ ofs += 129;
+ totalLength -= 129;
+ }
+ if (keysIndex >= keys.length) {
+ int[] newKeys = new int[keys.length + 4];
+ System.arraycopy(keys, 0, newKeys, 0, keys.length);
+ keys = newKeys;
+ }
+ keys[keysIndex] = tq;
+ keysIndex++;
+ }
+ int[] newKeys = new int[keysIndex];
+ System.arraycopy(keys, 0, newKeys, 0, keysIndex);
+ return newKeys;
+}
+
+public int[][] getQuantizationTablesValues() {
+ int[][] values = new int[4][];
+ int valuesIndex = 0;
+ int totalLength = getSegmentLength() - 2;
+ int ofs = 4;
+ while (totalLength > 64) {
+ int[] qk = new int[64];
+ int pq = (reference[ofs] & 0xFF) / 16;
+ if (pq == 0) {
+ for (int i = 0; i < qk.length; i++) {
+ qk[i] = reference[ofs + i + 1];
+ }
+ ofs += 65;
+ totalLength -= 65;
+ } else {
+ for (int i = 0; i < qk.length; i++) {
+ int idx = (i - 1) * 2 ;
+ qk[i] = (reference[ofs + idx + 1] & 0xFF) * 256 + (reference[ofs + idx + 2] & 0xFF);
+ }
+ ofs += 129;
+ totalLength -= 129;
+ }
+ if (valuesIndex >= values.length) {
+ int[][] newValues = new int[values.length + 4][];
+ System.arraycopy(values, 0, newValues, 0, values.length);
+ values = newValues;
+ }
+ values[valuesIndex] = qk;
+ valuesIndex++;
+ }
+ int[][] newValues = new int[valuesIndex][];
+ System.arraycopy(values, 0, newValues, 0, valuesIndex);
+ return newValues;
+}
+
+public void scaleBy(int qualityFactor) {
+ int qFactor = qualityFactor;
+ if (qFactor <= 0) {
+ qFactor = 1;
+ }
+ if (qFactor > 100) {
+ qFactor = 100;
+ }
+ if (qFactor < 50) {
+ qFactor = 5000 / qFactor;
+ } else {
+ qFactor = 200 - (qFactor * 2);
+ }
+ int totalLength = getSegmentLength() - 2;
+ int ofs = 4;
+ while (totalLength > 64) {
+ int tq = (reference[ofs] & 0xFF) % 16;
+ int pq = (reference[ofs] & 0xFF) / 16;
+ if (pq == 0) {
+ for (int i = ofs + 1; i <= ofs + 64; i++) {
+ int temp = ((reference[i] & 0xFF) * qFactor + 50) / 100;
+ if (temp <= 0) temp = 1;
+ if (temp > 255) temp = 255;
+ reference[i] = (byte)temp;
+ }
+ ofs += 65;
+ totalLength -= 65;
+ } else {
+ for (int i = ofs + 1; i <= ofs + 128; i += 2) {
+ int temp = (((reference[i] & 0xFF) * 256 + (reference[i + 1] & 0xFF)) * qFactor + 50) / 100;
+ if (temp <= 0) temp = 1;
+ if (temp > 32767) temp = 32767;
+ reference[i] = (byte)(temp / 256);
+ reference[i + 1] = (byte)(temp % 256);
+ }
+ ofs += 129;
+ totalLength -= 129;
+ }
+ }
+}
+
+public int signature() {
+ return JPEGFileFormat.DQT;
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGRestartInterval.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGRestartInterval.java
new file mode 100755
index 0000000000..242d5d924d
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGRestartInterval.java
@@ -0,0 +1,25 @@
+package org.eclipse.swt.internal.image;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp 2000
+ */
+
+final class JPEGRestartInterval extends JPEGFixedSizeSegment {
+
+ public JPEGRestartInterval(LEDataInputStream byteStream) {
+ super(byteStream);
+ }
+
+ public int signature() {
+ return JPEGFileFormat.DRI;
+ }
+
+ public int getRestartInterval() {
+ return ((reference[4] & 0xFF) << 8 | (reference[5] & 0xFF));
+ }
+
+ public int fixedSize() {
+ return 6;
+ }
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGScanHeader.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGScanHeader.java
new file mode 100755
index 0000000000..4e087fb951
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGScanHeader.java
@@ -0,0 +1,117 @@
+package org.eclipse.swt.internal.image;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.eclipse.swt.*;
+
+final class JPEGScanHeader extends JPEGVariableSizeSegment {
+ public int[][] componentParameters;
+
+public JPEGScanHeader(byte[] reference) {
+ super(reference);
+}
+
+public JPEGScanHeader(LEDataInputStream byteStream) {
+ super(byteStream);
+ initializeComponentParameters();
+}
+
+public int getApproxBitPositionHigh() {
+ return (reference[(2 * getNumberOfImageComponents()) + 7] & 0xFF) / 16;
+}
+
+public int getApproxBitPositionLow() {
+ return (reference[(2 * getNumberOfImageComponents()) + 7] & 0xFF) % 16;
+}
+
+public int getEndOfSpectralSelection() {
+ return (reference[(2 * getNumberOfImageComponents()) + 6] & 0xFF);
+}
+
+public int getNumberOfImageComponents() {
+ return (reference[4] & 0xFF);
+}
+
+public int getStartOfSpectralSelection() {
+ return (reference[(2 * getNumberOfImageComponents()) + 5] & 0xFF);
+}
+
+/* Used when decoding. */
+void initializeComponentParameters() {
+ int compCount = getNumberOfImageComponents();
+ componentParameters = new int[0][];
+ for (int i = 0; i < compCount; i++) {
+ int ofs = 5 + i * 2;
+ int cid = reference[ofs] & 0xFF;
+ int dc = (reference[ofs + 1] & 0xFF) / 16;
+ int ac = (reference[ofs + 1] & 0xFF) % 16;
+ if (componentParameters.length < cid) {
+ int[][] newParams = new int[cid][];
+ System.arraycopy(componentParameters, 0, newParams, 0, componentParameters.length);
+ componentParameters = newParams;
+ }
+ componentParameters[cid - 1] = new int[] { dc, ac };
+ }
+}
+
+/* Used when encoding. */
+public void initializeContents() {
+ int compCount = getNumberOfImageComponents();
+ int[][] compSpecParams = componentParameters;
+ if (compCount == 0 || compCount != compSpecParams.length) {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ }
+ for (int i = 0; i < compCount; i++) {
+ int ofs = i * 2 + 5;
+ int[] compParams = compSpecParams[i];
+ reference[ofs] = (byte)(i + 1);
+ reference[ofs + 1] = (byte)(compParams[0] * 16 + compParams[1]);
+ }
+}
+
+public void setEndOfSpectralSelection(int anInteger) {
+ reference[(2 * getNumberOfImageComponents()) + 6] = (byte)anInteger;
+}
+
+public void setNumberOfImageComponents(int anInteger) {
+ reference[4] = (byte)(anInteger & 0xFF);
+}
+
+public void setStartOfSpectralSelection(int anInteger) {
+ reference[(2 * getNumberOfImageComponents()) + 5] = (byte)anInteger;
+}
+
+public int signature() {
+ return JPEGFileFormat.SOS;
+}
+
+public boolean verifyProgressiveScan() {
+ int start = getStartOfSpectralSelection();
+ int end = getEndOfSpectralSelection();
+ int low = getApproxBitPositionLow();
+ int high = getApproxBitPositionHigh();
+ int count = getNumberOfImageComponents();
+ if ((start == 0 && end == 00) || (start <= end && end <= 63)) {
+ if (low <= 13 && high <= 13 && (high == 0 || high == low + 1)) {
+ return start == 0 || (start > 0 && count == 1);
+ }
+ }
+ return false;
+}
+
+public boolean isACProgressiveScan() {
+ return getStartOfSpectralSelection() != 0 && getEndOfSpectralSelection() != 0;
+}
+
+public boolean isDCProgressiveScan() {
+ return getStartOfSpectralSelection() == 0 && getEndOfSpectralSelection() == 0;
+}
+
+public boolean isFirstScan() {
+ return getApproxBitPositionHigh() == 0;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGSegment.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGSegment.java
new file mode 100755
index 0000000000..4f41a6a98b
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGSegment.java
@@ -0,0 +1,54 @@
+package org.eclipse.swt.internal.image;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.eclipse.swt.*;
+
+class JPEGSegment {
+ public byte[] reference;
+
+ JPEGSegment() {
+ }
+
+ public JPEGSegment(byte[] reference) {
+ this.reference = reference;
+ }
+
+ public int signature() {
+ return 0;
+ }
+
+ public boolean verify() {
+ return getSegmentMarker() == signature();
+ }
+
+ public int getSegmentMarker() {
+ return ((reference[0] & 0xFF) << 8 | (reference[1] & 0xFF));
+ }
+
+ public void setSegmentMarker(int marker) {
+ reference[0] = (byte)((marker & 0xFF00) >> 8);
+ reference[1] = (byte)(marker & 0xFF);
+ }
+
+ public int getSegmentLength() {
+ return ((reference[2] & 0xFF) << 8 | (reference[3] & 0xFF));
+ }
+
+ public void setSegmentLength(int length) {
+ reference[2] = (byte)((length & 0xFF00) >> 8);
+ reference[3] = (byte)(length & 0xFF);
+ }
+
+ public boolean writeToStream(LEDataOutputStream byteStream) {
+ try {
+ byteStream.write(reference);
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGStartOfImage.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGStartOfImage.java
new file mode 100755
index 0000000000..4a487d421b
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGStartOfImage.java
@@ -0,0 +1,29 @@
+package org.eclipse.swt.internal.image;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp 2000
+ */
+
+final class JPEGStartOfImage extends JPEGFixedSizeSegment {
+
+ public JPEGStartOfImage() {
+ super();
+ }
+
+ public JPEGStartOfImage(byte[] reference) {
+ super(reference);
+ }
+
+ public JPEGStartOfImage(LEDataInputStream byteStream) {
+ super(byteStream);
+ }
+
+ public int signature() {
+ return JPEGFileFormat.SOI;
+ }
+
+ public int fixedSize() {
+ return 2;
+ }
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGVariableSizeSegment.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGVariableSizeSegment.java
new file mode 100755
index 0000000000..7b96ed1aac
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGVariableSizeSegment.java
@@ -0,0 +1,32 @@
+package org.eclipse.swt.internal.image;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.eclipse.swt.*;
+
+abstract class JPEGVariableSizeSegment extends JPEGSegment {
+
+ public JPEGVariableSizeSegment(byte[] reference) {
+ super(reference);
+ }
+
+ public JPEGVariableSizeSegment(LEDataInputStream byteStream) {
+ try {
+ byte[] header = new byte[4];
+ byteStream.read(header);
+ reference = header; // to use getSegmentLength()
+ byte[] contents = new byte[getSegmentLength() + 2];
+ contents[0] = header[0];
+ contents[1] = header[1];
+ contents[2] = header[2];
+ contents[3] = header[3];
+ byteStream.read(contents, 4, contents.length - 4);
+ reference = contents;
+ } catch (Exception e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ }
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/LEDataInputStream.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/LEDataInputStream.java
new file mode 100755
index 0000000000..46e843d4c0
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/LEDataInputStream.java
@@ -0,0 +1,88 @@
+package org.eclipse.swt.internal.image;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.io.*;
+
+final class LEDataInputStream extends InputStream {
+ int position;
+ PushbackInputStream in;
+
+ public LEDataInputStream(InputStream input) {
+ this(input, 512);
+ }
+
+ public LEDataInputStream(InputStream input, int bufferSize) {
+ this.in = new PushbackInputStream(input, bufferSize);
+ }
+
+ public void close() throws IOException {
+ in.close();
+ }
+
+ /**
+ * Answer how many bytes were read.
+ */
+ public int getPosition() {
+ return position;
+ }
+
+ /**
+ * Answer the next byte of the input stream.
+ */
+ public int read() throws IOException {
+ position++;
+ return in.read();
+ }
+
+ /**
+ * Don't imitate the JDK behaviour of reading a random number
+ * of bytes when you can actually read them all.
+ */
+ public int read(byte b[], int off, int len) throws IOException {
+ int result;
+ int left = len;
+ result = in.read(b, off, len);
+ while (true) {
+ if (result == -1)
+ return -1;
+ position += result;
+ if (result == left)
+ return len;
+ left -= result;
+ off += result;
+ result = in.read(b, off, left);
+ }
+ }
+
+ /**
+ * Answer an integer comprised of the next
+ * four bytes of the input stream.
+ */
+ public int readInt() throws IOException {
+ byte[] buf = new byte[4];
+ read(buf);
+ return ((((((buf[3] & 0xFF) << 8) |
+ (buf[2] & 0xFF)) << 8) |
+ (buf[1] & 0xFF)) << 8) |
+ (buf[0] & 0xFF);
+ }
+
+ /**
+ * Answer a short comprised of the next
+ * two bytes of the input stream.
+ */
+ public short readShort() throws IOException {
+ byte[] buf = new byte[2];
+ read(buf);
+ return (short)(((buf[1] & 0xFF) << 8) | (buf[0] & 0xFF));
+ }
+
+ public void unread(byte[] b) throws IOException {
+ position -= b.length;
+ in.unread(b);
+ }
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/LEDataOutputStream.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/LEDataOutputStream.java
new file mode 100755
index 0000000000..7859012ca8
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/LEDataOutputStream.java
@@ -0,0 +1,54 @@
+package org.eclipse.swt.internal.image;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+/* Imports */
+import java.io.*;
+
+/* Class Definition */
+final class LEDataOutputStream extends OutputStream {
+ OutputStream out;
+public LEDataOutputStream(OutputStream output) {
+ this.out = output;
+}
+public void close() throws IOException {
+ out.close();
+}
+public void write(byte b[], int off, int len) throws IOException {
+ out.write(b, off, len);
+}
+/**
+ * Answer the next byte of the input stream.
+ */
+public void write(int b) throws IOException {
+ out.write(b);
+}
+/**
+ * Answer the next byte of the input stream.
+ */
+public void writeByte(byte b) throws IOException {
+ out.write(b & 0xFF);
+}
+/**
+ * Answer an integer comprised of the next
+ * four bytes of the input stream.
+ */
+public void writeInt(int theInt) throws IOException {
+ out.write(theInt & 0xFF);
+ out.write((theInt >> 8) & 0xFF);
+ out.write((theInt >> 16) & 0xFF);
+ out.write((theInt >> 24) & 0xFF);
+}
+/**
+ * Answer an integer comprised of the next
+ * two bytes of the input stream.
+ */
+public void writeShort(int theShort) throws IOException {
+ out.write(theShort & 0xFF);
+ out.write((theShort >> 8) & 0xFF);
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/LZWCodec.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/LZWCodec.java
new file mode 100755
index 0000000000..fcf71f81a9
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/LZWCodec.java
@@ -0,0 +1,479 @@
+package org.eclipse.swt.internal.image;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+/* Imports */
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+/* Class Definition */
+final class LZWCodec {
+ int bitsPerPixel, blockSize, blockIndex, currentByte, bitsLeft,
+ codeSize, clearCode, endCode, newCodes, topSlot, currentSlot,
+ imageWidth, imageHeight, imageX, imageY, pass, line, codeMask, buffer;
+ byte[] block, lineArray;
+ int[] maskTable, stack, suffix, prefix;
+ LZWNode[] nodeStack;
+ LEDataInputStream inputStream;
+ LEDataOutputStream outputStream;
+ ImageData image;
+ ImageLoader loader;
+ boolean interlaced;
+/**
+ * Decode the input.
+ */
+void decode() {
+ int code;
+ int oc = 0;
+ int fc = 0;
+ byte[] buf = new byte[imageWidth];
+ int stackIndex = 0;
+ int bufIndex = 0;
+ int c;
+ while ((c = nextCode()) != endCode) {
+ if (c == clearCode) {
+ codeSize = bitsPerPixel + 1;
+ codeMask = maskTable[bitsPerPixel];
+ currentSlot = newCodes;
+ topSlot = 1 << codeSize;
+ while ((c = nextCode()) == clearCode) {};
+ if (c != endCode) {
+ oc = fc = c;
+ buf[bufIndex] = (byte)c;
+ bufIndex++;
+ if (bufIndex == imageWidth) {
+ nextPutPixels(buf);
+ bufIndex = 0;
+ }
+ }
+ } else {
+ code = c;
+ if (code >= currentSlot) {
+ if (code > currentSlot)
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ code = oc;
+ stack[stackIndex] = fc;
+ stackIndex++;
+ }
+ while (code >= newCodes) {
+ stack[stackIndex] = suffix[code];
+ stackIndex++;
+ code = prefix[code];
+ }
+ stack[stackIndex] = code;
+ stackIndex++;
+ if (currentSlot < topSlot) {
+ fc = code;
+ suffix[currentSlot] = fc;
+ prefix[currentSlot] = oc;
+ currentSlot++;
+ oc = c;
+ }
+ if (currentSlot >= topSlot) {
+ if (codeSize < 12) {
+ codeMask = maskTable[codeSize];
+ codeSize++;
+ topSlot = topSlot + topSlot;
+ }
+ }
+ while (stackIndex > 0) {
+ stackIndex--;
+ buf[bufIndex] = (byte)stack[stackIndex];
+ bufIndex++;
+ if (bufIndex == imageWidth) {
+ nextPutPixels(buf);
+ bufIndex = 0;
+ }
+ }
+ }
+ }
+ if (bufIndex != 0 && line < imageHeight) {
+ nextPutPixels(buf);
+ }
+}
+/**
+ * Decode the LZW-encoded bytes in the given byte stream
+ * into the given DeviceIndependentImage.
+ */
+public void decode(LEDataInputStream inputStream, ImageLoader loader, ImageData image, boolean interlaced, int depth) {
+ this.inputStream = inputStream;
+ this.loader = loader;
+ this.image = image;
+ this.interlaced = interlaced;
+ this.bitsPerPixel = depth;
+ initializeForDecoding();
+ decode();
+}
+/**
+ * Encode the image.
+ */
+void encode() {
+ nextPutCode(clearCode);
+ int lastPrefix = encodeLoop();
+ nextPutCode(lastPrefix);
+ nextPutCode(endCode);
+
+ // Write out last partial block
+ if (bitsLeft == 8) {
+ block[0] = (byte)(blockIndex - 1); // Nothing in last byte
+ } else {
+ block[0] = (byte)(blockIndex); // Last byte has data
+ }
+ writeBlock();
+
+ // Write out empty block to indicate the end (if needed)
+ if (block[0] != 0) {
+ block[0] = 0;
+ writeBlock();
+ }
+}
+/**
+ * Encode the bytes into the given byte stream
+ * from the given DeviceIndependentImage.
+ */
+public void encode(LEDataOutputStream byteStream, ImageData image) {
+ this.outputStream = byteStream;
+ this.image = image;
+ initializeForEncoding();
+ encode();
+}
+/**
+ * Encoding loop broken out to allow early return.
+ */
+int encodeLoop() {
+ int pixel = nextPixel();
+ boolean found;
+ LZWNode node;
+ while (true) {
+ int currentPrefix = pixel;
+ node = nodeStack[currentPrefix];
+ found = true;
+ pixel = nextPixel();
+ if (pixel < 0)
+ return currentPrefix;
+ while (found && (node.children != null)) {
+ node = node.children;
+ while (found && (node.suffix != pixel)) {
+ if (pixel < node.suffix) {
+ if (node.left == null) {
+ node.left = new LZWNode();
+ found = false;
+ }
+ node = node.left;
+ } else {
+ if (node.right == null) {
+ node.right = new LZWNode();
+ found = false;
+ }
+ node = node.right;
+ }
+ }
+ if (found) {
+ currentPrefix = node.code;
+ pixel = nextPixel();
+ if (pixel < 0)
+ return currentPrefix;
+ }
+ }
+ if (found) {
+ node.children = new LZWNode();
+ node = node.children;
+ }
+ node.children = null;
+ node.left = null;
+ node.right = null;
+ node.code = currentSlot;
+ node.prefix = currentPrefix;
+ node.suffix = pixel;
+ nextPutCode(currentPrefix);
+ currentSlot++;
+ // Off by one?
+ if (currentSlot < 4096) {
+ if (currentSlot > topSlot) {
+ codeSize++;
+ codeMask = maskTable[codeSize - 1];
+ topSlot *= 2;
+ }
+ } else {
+ nextPutCode(clearCode);
+ for (int i = 0; i < nodeStack.length; i++)
+ nodeStack[i].children = null;
+ codeSize = bitsPerPixel + 1;
+ codeMask = maskTable[codeSize - 1];
+ currentSlot = newCodes;
+ topSlot = 1 << codeSize;
+ }
+ }
+}
+/**
+ * Initialize the receiver for decoding the given
+ * byte array.
+ */
+void initializeForDecoding() {
+ pass = 1;
+ line = 0;
+ codeSize = bitsPerPixel + 1;
+ topSlot = 1 << codeSize;
+ clearCode = 1 << bitsPerPixel;
+ endCode = clearCode + 1;
+ newCodes = currentSlot = endCode + 1;
+ currentByte = -1;
+ blockSize = bitsLeft = 0;
+ blockIndex = 0;
+ maskTable = new int[] {
+ 0x1, 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F,
+ 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF
+ };
+ codeMask = maskTable[codeSize - 1];
+ stack = new int[4096];
+ suffix = new int[4096];
+ prefix = new int[4096];
+ block = new byte[256];
+ imageWidth = image.width;
+ imageHeight = image.height;
+}
+/**
+ * Initialize the receiver for encoding the given
+ * byte array.
+ */
+void initializeForEncoding() {
+ interlaced = false;
+ bitsPerPixel = image.depth;
+ codeSize = bitsPerPixel + 1;
+ topSlot = 1 << codeSize;
+ clearCode = 1 << bitsPerPixel;
+ endCode = clearCode + 1;
+ newCodes = currentSlot = endCode + 1;
+ bitsLeft = 8;
+ currentByte = 0;
+ blockIndex = 1;
+ blockSize = 255;
+ block = new byte[blockSize];
+ block[0] = (byte)(blockSize - 1);
+ maskTable = new int[] {
+ 0x1, 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F,
+ 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF
+ };
+ nodeStack = new LZWNode[1 << bitsPerPixel];
+ for (int i = 0; i < nodeStack.length; i++) {
+ LZWNode node = new LZWNode();
+ node.code = i + 1;
+ node.prefix = -1;
+ node.suffix = i + 1;
+ nodeStack[i] = node;
+ }
+ imageWidth = image.width;
+ imageHeight = image.height;
+ imageY = -1;
+ lineArray = new byte[imageWidth];
+ imageX = imageWidth + 1; // Force a read
+}
+/**
+ * Answer the next code from the input byte array.
+ */
+int nextCode() {
+ int code;
+ if (bitsLeft == 0) {
+ if (blockIndex >= blockSize) {
+ blockSize = readBlock();
+ blockIndex = 0;
+ if (blockSize == 0) return endCode;
+ }
+ blockIndex++;
+ currentByte = block[blockIndex] & 0xFF;
+ bitsLeft = 8;
+ code = currentByte;
+ } else {
+ int shift = bitsLeft - 8;
+ if (shift < 0)
+ code = currentByte >> (0 - shift);
+ else
+ code = currentByte << shift;
+ }
+ while (codeSize > bitsLeft) {
+ if (blockIndex >= blockSize) {
+ blockSize = readBlock();
+ blockIndex = 0;
+ if (blockSize == 0) return endCode;
+ }
+ blockIndex++;
+ currentByte = block[blockIndex] & 0xFF;
+ code += currentByte << bitsLeft;
+ bitsLeft += 8;
+ }
+ bitsLeft -= codeSize;
+ return code & codeMask;
+}
+/**
+ * Answer the next pixel to encode in the image
+ */
+int nextPixel() {
+ imageX++;
+ if (imageX > imageWidth) {
+ imageY++;
+ if (imageY >= imageHeight) {
+ return -1;
+ } else {
+ nextPixels(lineArray, imageWidth);
+ }
+ imageX = 1;
+ }
+ return this.lineArray[imageX - 1] & 0xFF;
+}
+/**
+ * Copy a row of pixel values from the image.
+ */
+void nextPixels(byte[] buf, int lineWidth) {
+ if (image.depth == 8) {
+ System.arraycopy(image.data, imageY * image.bytesPerLine, buf, 0, lineWidth);
+ } else {
+ image.getPixels(0, imageY, lineWidth, buf, 0);
+ }
+}
+/**
+ * Output aCode to the output stream.
+ */
+void nextPutCode(int aCode) {
+ int codeToDo = aCode;
+ int codeBitsToDo = codeSize;
+ // Fill in the remainder of the current byte with the
+ // *high-order* bits of the code.
+ int c = codeToDo & maskTable[bitsLeft - 1];
+ currentByte = currentByte | (c << (8 - bitsLeft));
+ block[blockIndex] = (byte)currentByte;
+ codeBitsToDo -= bitsLeft;
+ if (codeBitsToDo < 1) {
+ // The whole code fit in the first byte, so we are done.
+ bitsLeft -= codeSize;
+ if (bitsLeft == 0) {
+ // We used the whole last byte, so get ready
+ // for the next one.
+ bitsLeft = 8;
+ blockIndex++;
+ if (blockIndex >= blockSize) {
+ writeBlock();
+ blockIndex = 1;
+ }
+ currentByte = 0;
+ }
+ return;
+ }
+ codeToDo = codeToDo >> bitsLeft;
+
+ // Fill in any remaining whole bytes (i.e. not the last one!)
+ blockIndex++;
+ if (blockIndex >= blockSize) {
+ writeBlock();
+ blockIndex = 1;
+ }
+ while (codeBitsToDo >= 8) {
+ currentByte = codeToDo & 0xFF;
+ block[blockIndex] = (byte)currentByte;
+ codeToDo = codeToDo >> 8;
+ codeBitsToDo -= 8;
+ blockIndex++;
+ if (blockIndex >= blockSize) {
+ writeBlock();
+ blockIndex = 1;
+ }
+ }
+ // Fill the *low-order* bits of the last byte with the remainder
+ bitsLeft = 8 - codeBitsToDo;
+ currentByte = codeToDo;
+ block[blockIndex] = (byte)currentByte;
+}
+/**
+ * Copy a row of pixel values to the image.
+ */
+void nextPutPixels(byte[] buf) {
+ if (image.depth == 8) {
+ // Slight optimization for depth = 8.
+ int start = line * image.bytesPerLine;
+ for (int i = 0; i < imageWidth; i++)
+ image.data[start + i] = buf[i];
+ } else {
+ image.setPixels(0, line, imageWidth, buf, 0);
+ }
+ if (interlaced) {
+ if (pass == 1) {
+ copyRow(buf, 7);
+ line += 8;
+ } else if (pass == 2) {
+ copyRow(buf, 3);
+ line += 8;
+ } else if (pass == 3) {
+ copyRow(buf, 1);
+ line += 4;
+ } else if (pass == 4) {
+ line += 2;
+ } else if (pass == 5) {
+ line += 0;
+ }
+ if (line >= imageHeight) {
+ pass++;
+ if (pass == 2) line = 4;
+ else if (pass == 3) line = 2;
+ else if (pass == 4) line = 1;
+ else if (pass == 5) line = 0;
+ if (pass < 5) {
+ if (loader.hasListeners()) {
+ ImageData imageCopy = (ImageData) image.clone();
+ loader.notifyListeners(
+ new ImageLoaderEvent(loader, imageCopy, pass - 2, false));
+ }
+ }
+ }
+ if (line >= imageHeight) line = 0;
+ } else {
+ line++;
+ }
+}
+/**
+ * Copy duplicate rows of pixel values to the image.
+ * This is to fill in rows if the image is interlaced.
+ */
+void copyRow(byte[] buf, int copies) {
+ for (int i = 1; i <= copies; i++) {
+ if (line + i < imageHeight) {
+ image.setPixels(0, line + i, imageWidth, buf, 0);
+ }
+ }
+}
+/**
+ * Read a block from the byte stream.
+ * Return the number of bytes read.
+ * Throw an exception if the block could not be read.
+ */
+int readBlock() {
+ int size = -1;
+ try {
+ size = inputStream.read();
+ if (size == -1) {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ }
+ block[0] = (byte)size;
+ size = inputStream.read(block, 1, size);
+ if (size == -1) {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ }
+ } catch (Exception e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ return size;
+}
+/**
+ * Write a block to the byte stream.
+ * Throw an exception if the block could not be written.
+ */
+void writeBlock() {
+ try {
+ outputStream.write(block, 0, (block[0] & 0xFF) + 1);
+ } catch (Exception e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/LZWNode.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/LZWNode.java
new file mode 100755
index 0000000000..d4d3d4b680
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/LZWNode.java
@@ -0,0 +1,13 @@
+package org.eclipse.swt.internal.image;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+/* Class Definition */
+final class LZWNode {
+ public LZWNode left, right, children;
+ public int code, prefix, suffix;
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PNGFileFormat.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PNGFileFormat.java
new file mode 100755
index 0000000000..6a9413bdb9
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PNGFileFormat.java
@@ -0,0 +1,525 @@
+package org.eclipse.swt.internal.image;
+
+import java.io.*;
+import java.util.*;
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+public class PNGFileFormat extends FileFormat {
+ static final int SIGNATURE_LENGTH = 8;
+ PngDecodingDataStream decodingStream;
+ PngIhdrChunk headerChunk;
+ PngPlteChunk paletteChunk;
+ PngTrnsChunk trnsChunk;
+ ImageData imageData;
+ byte[] data;
+ byte[] alphaPalette;
+
+/**
+ * Skip over signature data. This has already been
+ * verified in isPNGFile().
+ */
+void readSignature() throws IOException {
+ byte[] signature = new byte[SIGNATURE_LENGTH];
+ inputStream.read(signature);
+}
+/**
+ * Load the PNG image from the byte stream.
+ */
+ImageData[] loadFromByteStream() {
+ try {
+ readSignature();
+ PngChunkReader chunkReader = new PngChunkReader(inputStream);
+ headerChunk = chunkReader.getIhdrChunk();
+ int imageSize = getAlignedBytesPerRow() * headerChunk.getHeight();
+ data = new byte[imageSize];
+ imageData = ImageData.internal_new(
+ headerChunk.getWidth(),
+ headerChunk.getHeight(),
+ headerChunk.getSwtBitsPerPixel(),
+ new PaletteData(0, 0, 0),
+ 4,
+ data,
+ 0,
+ null,
+ null,
+ -1,
+ -1,
+ SWT.IMAGE_PNG,
+ 0,
+ 0,
+ 0,
+ 0);
+
+ if (headerChunk.usesDirectColor()) {
+ imageData.palette = headerChunk.getPaletteData();
+ };
+
+ // Read and process chunks until the IEND chunk is encountered.
+ while (chunkReader.hasMoreChunks()) {
+ readNextChunk(chunkReader);
+ }
+
+ return new ImageData[] {imageData};
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ return null;
+ }
+}
+/**
+ * Read and handle the next chunk of data from the
+ * PNG file.
+ */
+void readNextChunk(PngChunkReader chunkReader) {
+ PngChunk chunk = chunkReader.readNextChunk();
+ switch (chunk.getChunkType()) {
+ case PngChunk.CHUNK_IEND:
+ break;
+ case PngChunk.CHUNK_PLTE:
+ if (!headerChunk.usesDirectColor()) {
+ paletteChunk = (PngPlteChunk) chunk;
+ imageData.palette = paletteChunk.getPaletteData();
+ };
+ break;
+ case PngChunk.CHUNK_tRNS:
+ PngTrnsChunk trnsChunk = (PngTrnsChunk) chunk;
+ if (trnsChunk.getTransparencyType(headerChunk) ==
+ PngTrnsChunk.TRANSPARENCY_TYPE_PIXEL)
+ {
+ imageData.transparentPixel =
+ trnsChunk.getSwtTransparentPixel(headerChunk);
+ } else {
+ alphaPalette = trnsChunk.getAlphaValues(headerChunk, paletteChunk);
+ }
+ break;
+ case PngChunk.CHUNK_IDAT:
+ if (chunkReader.readPixelData()) {
+ // All IDAT chunks in an image file must be
+ // sequential. If the pixel data has already
+ // been read and another IDAT block is encountered,
+ // then this is an invalid image.
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ } else {
+ // Read in the pixel data for the image. This should
+ // go through all the image's IDAT chunks.
+ PngIdatChunk dataChunk = (PngIdatChunk) chunk;
+ readPixelData(dataChunk, chunkReader);
+ }
+ break;
+ default:
+ if (chunk.isCritical()) {
+ // All critical chunks must be supported.
+ SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+ }
+ }
+}
+void unloadIntoByteStream(ImageData p1) {
+ SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+}
+/**
+ * Answer whether the specified input stream
+ * contains a PNG image.
+ */
+public static boolean isPNGFile(LEDataInputStream stream) {
+ try {
+ byte[] signature = new byte[SIGNATURE_LENGTH];
+ stream.read(signature);
+ stream.unread(signature);
+ if ((signature[0] & 0xFF) != 137) return false; //137
+ if ((signature[1] & 0xFF) != 80) return false; //P
+ if ((signature[2] & 0xFF) != 78) return false; //N
+ if ((signature[3] & 0xFF) != 71) return false; //G
+ if ((signature[4] & 0xFF) != 13) return false; //<RETURN>
+ if ((signature[5] & 0xFF) != 10) return false; //<LINEFEED>
+ if ((signature[6] & 0xFF) != 26) return false; //<CTRL/Z>
+ if ((signature[7] & 0xFF) != 10) return false; //<LINEFEED>
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+}
+/**
+ * SWT does not support 16-bit depths. If this image uses
+ * 16-bit depths, convert the data to an 8-bit depth.
+ */
+byte[] validateBitDepth(byte[] data) {
+ if (headerChunk.getBitDepth() > 8) {
+ byte[] result = new byte[data.length / 2];
+ compress16BitDepthTo8BitDepth(data, 0, result, 0, result.length);
+ return result;
+ } else {
+ return data;
+ }
+}
+/**
+ * SWT does not support greyscale as a color type. For
+ * plain grayscale, we create a palette. For Grayscale
+ * with Alpha, however, we need to convert the pixels
+ * to use RGB values.
+ * Note: This method assumes that the bit depth of the
+ * data has already been restricted to 8 or less.
+ */
+void setPixelData(byte[] data, ImageData imageData) {
+ switch (headerChunk.getColorType()) {
+ case PngIhdrChunk.COLOR_TYPE_GRAYSCALE_WITH_ALPHA:
+ {
+ int width = imageData.width;
+ int height = imageData.height;
+ int destBytesPerLine = imageData.bytesPerLine;
+ int srcBytesPerLine = width * 2;
+ byte[] rgbData = new byte[destBytesPerLine * height];
+ byte[] alphaData = new byte[width * height];
+ for (int y = 0; y < height; y++) {
+ int srcIndex = srcBytesPerLine * y;
+ int destIndex = destBytesPerLine * y;
+ int destAlphaIndex = width * y;
+ for (int x = 0; x < width; x++) {
+ byte grey = data[srcIndex];
+ byte alpha = data[srcIndex + 1];
+ rgbData[destIndex + 0] = grey;
+ rgbData[destIndex + 1] = grey;
+ rgbData[destIndex + 2] = grey;
+ alphaData[destAlphaIndex] = alpha;
+ srcIndex += 2;
+ destIndex += 3;
+ destAlphaIndex++;
+ }
+ }
+ imageData.data = rgbData;
+ imageData.alphaData = alphaData;
+ break;
+ }
+ case PngIhdrChunk.COLOR_TYPE_RGB_WITH_ALPHA:
+ {
+ int width = imageData.width;
+ int height = imageData.height;
+ int destBytesPerLine = imageData.bytesPerLine;
+ int srcBytesPerLine = getAlignedBytesPerRow();
+ byte[] rgbData = new byte[destBytesPerLine * height];
+ byte[] alphaData = new byte[width * height];
+ for (int y = 0; y < height; y++) {
+ int srcIndex = srcBytesPerLine * y;
+ int destIndex = destBytesPerLine * y;
+ int destAlphaIndex = width * y;
+ for (int x = 0; x < width; x++) {
+ rgbData[destIndex + 0] = data[srcIndex + 0];
+ rgbData[destIndex + 1] = data[srcIndex + 1];
+ rgbData[destIndex + 2] = data[srcIndex + 2];
+ alphaData[destAlphaIndex] = data[srcIndex + 3];
+ srcIndex += 4;
+ destIndex += 3;
+ destAlphaIndex++;
+ }
+ }
+ imageData.data = rgbData;
+ imageData.alphaData = alphaData;
+ break;
+ }
+ case PngIhdrChunk.COLOR_TYPE_RGB:
+ imageData.data = data;
+ break;
+ case PngIhdrChunk.COLOR_TYPE_PALETTE:
+ imageData.data = data;
+ if (alphaPalette != null) {
+ int size = imageData.width * imageData.height;
+ byte[] alphaData = new byte[size];
+ byte[] pixelData = new byte[size];
+ imageData.getPixels(0, 0, size, pixelData, 0);
+ for (int i = 0; i < pixelData.length; i++) {
+ alphaData[i] = alphaPalette[pixelData[i] & 0xFF];
+ }
+ imageData.alphaData = alphaData;
+ }
+ break;
+ default:
+ imageData.data = data;
+ break;
+ }
+}
+/**
+ * PNG supports some color types and bit depths that are
+ * unsupported by SWT. If the image uses an unsupported
+ * color type (either of the gray scale types) or bit
+ * depth (16), convert the data to an SWT-supported
+ * format. Then assign the data into the ImageData given.
+ */
+void setImageDataValues(byte[] data, ImageData imageData) {
+ byte[] result = validateBitDepth(data);
+ setPixelData(result, imageData);
+}
+/**
+ * Read the image data from the data stream. This must handle
+ * decoding the data, filtering, and interlacing.
+ */
+void readPixelData(PngIdatChunk chunk, PngChunkReader chunkReader) {
+ decodingStream = new PngDecodingDataStream(chunk, chunkReader);
+ int interlaceMethod = headerChunk.getInterlaceMethod();
+ if (interlaceMethod == PngIhdrChunk.INTERLACE_METHOD_NONE) {
+ readNonInterlacedImage();
+ } else {
+ readInterlacedImage();
+ }
+ decodingStream.assertImageDataAtEnd();
+ decodingStream.checkAdler();
+}
+/**
+ * Answer the number of bytes in a word-aligned row of pixel data.
+ */
+int getAlignedBytesPerRow() {
+ return ((getBytesPerRow(headerChunk.getWidth()) + 3) / 4) * 4;
+}
+/**
+ * Answer the number of bytes in each row of the image
+ * data. Each PNG row is byte-aligned, so images with bit
+ * depths less than a byte may have unused bits at the
+ * end of each row. The value of these bits is undefined.
+ */
+int getBytesPerRow() {
+ return getBytesPerRow(headerChunk.getWidth());
+}
+/**
+ * Answer the number of bytes needed to represent a pixel.
+ * This value depends on the image's color type and bit
+ * depth.
+ * Note that this method rounds up if an image's pixel size
+ * isn't byte-aligned.
+ */
+int getBytesPerPixel() {
+ int bitsPerPixel = headerChunk.getBitsPerPixel();
+ return (bitsPerPixel + 7) / 8;
+}
+/**
+ * Answer the number of bytes in a row of the given pixel
+ * width. Each row is byte-aligned, so images with bit
+ * depths less than a byte may have unused bits at the
+ * end of each row. The value of these bits is undefined.
+ */
+int getBytesPerRow(int rowWidthInPixels) {
+ int bitsPerPixel = headerChunk.getBitsPerPixel();
+ int bitsPerRow = bitsPerPixel * rowWidthInPixels;
+ int bitsPerByte = 8;
+ return (bitsPerRow + (bitsPerByte - 1)) / bitsPerByte;
+}
+/**
+ * 1. Read one of the seven frames of interlaced data.
+ * 2. Update the imageData.
+ * 3. Notify the image loader's listeners of the frame load.
+ */
+void readInterlaceFrame(
+ int rowInterval,
+ int columnInterval,
+ int startRow,
+ int startColumn,
+ int frameCount)
+{
+ int width = headerChunk.getWidth();
+ int alignedBytesPerRow = getAlignedBytesPerRow();
+ int height = headerChunk.getHeight();
+ if (startRow >= height || startColumn >= width) return;
+
+ int pixelsPerRow = (width - startColumn + columnInterval - 1) / columnInterval;
+ int bytesPerRow = getBytesPerRow(pixelsPerRow);
+ byte[] row1 = new byte[bytesPerRow];
+ byte[] row2 = new byte[bytesPerRow];
+ byte[] currentRow = row1;
+ byte[] lastRow = row2;
+ for (int row = startRow; row < height; row += rowInterval) {
+ byte filterType = decodingStream.getNextDecodedByte();
+ for (int col = 0; col < bytesPerRow; col++) {
+ currentRow[col] = decodingStream.getNextDecodedByte();
+ }
+ filterRow(currentRow, lastRow, filterType);
+ if (headerChunk.getBitDepth() >= 8) {
+ int bytesPerPixel = getBytesPerPixel();
+ int dataOffset = (row * alignedBytesPerRow) + (startColumn * bytesPerPixel);
+ for (int rowOffset = 0; rowOffset < currentRow.length; rowOffset += bytesPerPixel) {
+ for (int byteOffset = 0; byteOffset < bytesPerPixel; byteOffset++) {
+ data[dataOffset + byteOffset] = currentRow[rowOffset + byteOffset];
+ }
+ dataOffset += (columnInterval * bytesPerPixel);
+ }
+ } else {
+ int bitsPerPixel = headerChunk.getBitDepth();
+ int pixelsPerByte = 8 / bitsPerPixel;
+ int column = startColumn;
+ int rowBase = row * alignedBytesPerRow;
+ int valueMask = 0;
+ for (int i = 0; i < bitsPerPixel; i++) {
+ valueMask <<= 1;
+ valueMask |= 1;
+ }
+ int maxShift = 8 - bitsPerPixel;
+ for (int byteOffset = 0; byteOffset < currentRow.length; byteOffset++) {
+ for (int bitOffset = maxShift; bitOffset >= 0; bitOffset -= bitsPerPixel) {
+ if (column < width) {
+ int dataOffset = rowBase + (column * bitsPerPixel / 8);
+ int value = (currentRow[byteOffset] >> bitOffset) & valueMask;
+ int dataShift = maxShift - (bitsPerPixel * (column % pixelsPerByte));
+ data[dataOffset] |= value << dataShift;
+ }
+ column += columnInterval;
+ }
+ }
+ }
+ currentRow = (currentRow == row1) ? row2 : row1;
+ lastRow = (lastRow == row1) ? row2 : row1;
+ }
+ setImageDataValues(data, imageData);
+ fireInterlacedFrameEvent(frameCount);
+}
+/**
+ * Read the pixel data for an interlaced image from the
+ * data stream.
+ */
+void readInterlacedImage() {
+ readInterlaceFrame(8, 8, 0, 0, 0);
+ readInterlaceFrame(8, 8, 0, 4, 1);
+ readInterlaceFrame(8, 4, 4, 0, 2);
+ readInterlaceFrame(4, 4, 0, 2, 3);
+ readInterlaceFrame(4, 2, 2, 0, 4);
+ readInterlaceFrame(2, 2, 0, 1, 5);
+ readInterlaceFrame(2, 1, 1, 0, 6);
+}
+/**
+ * Fire an event to let listeners know that an interlaced
+ * frame has been loaded.
+ * finalFrame should be true if the image has finished
+ * loading, false if there are more frames to come.
+ */
+void fireInterlacedFrameEvent(int frameCount) {
+ if (loader.hasListeners()) {
+ ImageData image = (ImageData) imageData.clone();
+ boolean finalFrame = frameCount == 6;
+ loader.notifyListeners(new ImageLoaderEvent(loader, image, frameCount, finalFrame));
+ }
+}
+/**
+ * Read the pixel data for a non-interlaced image from the
+ * data stream.
+ * Update the imageData to reflect the new data.
+ */
+void readNonInterlacedImage() {
+ int dataOffset = 0;
+ int alignedBytesPerRow = getAlignedBytesPerRow();
+ int bytesPerRow = getBytesPerRow();
+ byte[] row1 = new byte[bytesPerRow];
+ byte[] row2 = new byte[bytesPerRow];
+ byte[] currentRow = row1;
+ byte[] lastRow = row2;
+ for (int row = 0; row < headerChunk.getHeight(); row++) {
+ byte filterType = decodingStream.getNextDecodedByte();
+ for (int col = 0; col < bytesPerRow; col++) {
+ currentRow[col] = decodingStream.getNextDecodedByte();
+ }
+ filterRow(currentRow, lastRow, filterType);
+ System.arraycopy(currentRow, 0, data, dataOffset, bytesPerRow);
+ dataOffset += alignedBytesPerRow;
+ currentRow = (currentRow == row1) ? row2 : row1;
+ lastRow = (lastRow == row1) ? row2 : row1;
+ }
+ setImageDataValues(data, imageData);
+}
+/**
+ * SWT does not support 16-bit depth color formats.
+ * Convert the 16-bit data to 8-bit data.
+ * The correct way to do this is to multiply each
+ * 16 bit value by the value:
+ * (2^8 - 1) / (2^16 - 1).
+ * The fast way to do this is just to drop the low
+ * byte of the 16-bit value.
+ */
+static void compress16BitDepthTo8BitDepth(
+ byte[] source,
+ int sourceOffset,
+ byte[] destination,
+ int destinationOffset,
+ int numberOfValues)
+{
+ //double multiplier = (Math.pow(2, 8) - 1) / (Math.pow(2, 16) - 1);
+ for (int i = 0; i < numberOfValues; i++) {
+ int sourceIndex = sourceOffset + (2 * i);
+ int destinationIndex = destinationOffset + i;
+ //int value = (source[sourceIndex] << 8) | source[sourceIndex + 1];
+ //byte compressedValue = (byte)(value * multiplier);
+ byte compressedValue = source[sourceIndex];
+ destination[destinationIndex] = compressedValue;
+ }
+}
+/**
+ * SWT does not support 16-bit depth color formats.
+ * Convert the 16-bit data to 8-bit data.
+ * The correct way to do this is to multiply each
+ * 16 bit value by the value:
+ * (2^8 - 1) / (2^16 - 1).
+ * The fast way to do this is just to drop the low
+ * byte of the 16-bit value.
+ */
+static int compress16BitDepthTo8BitDepth(int value) {
+ //double multiplier = (Math.pow(2, 8) - 1) / (Math.pow(2, 16) - 1);
+ //byte compressedValue = (byte)(value * multiplier);
+ return value >> 8;
+}
+/**
+ * PNG supports four filtering types. These types are applied
+ * per row of image data. This method unfilters the given row
+ * based on the filterType.
+ */
+void filterRow(byte[] row, byte[] previousRow, int filterType) {
+ int byteOffset = headerChunk.getFilterByteOffset();
+ switch (filterType) {
+ case PngIhdrChunk.FILTER_NONE:
+ break;
+ case PngIhdrChunk.FILTER_SUB:
+ for (int i = byteOffset; i < row.length; i++) {
+ int current = row[i] & 0xFF;
+ int left = row[i - byteOffset] & 0xFF;
+ row[i] = (byte)((current + left) & 0xFF);
+ }
+ break;
+ case PngIhdrChunk.FILTER_UP:
+ for (int i = 0; i < row.length; i++) {
+ int current = row[i] & 0xFF;
+ int above = previousRow[i] & 0xFF;
+ row[i] = (byte)((current + above) & 0xFF);
+ }
+ break;
+ case PngIhdrChunk.FILTER_AVERAGE:
+ for (int i = 0; i < row.length; i++) {
+ int left = (i < byteOffset) ? 0 : row[i - byteOffset] & 0xFF;
+ int above = previousRow[i] & 0xFF;
+ int current = row[i] & 0xFF;
+ row[i] = (byte)((current + ((left + above) / 2)) & 0xFF);
+ }
+ break;
+ case PngIhdrChunk.FILTER_PAETH:
+ for (int i = 0; i < row.length; i++) {
+ int left = (i < byteOffset) ? 0 : row[i - byteOffset] & 0xFF;
+ int aboveLeft = (i < byteOffset) ? 0 : previousRow[i - byteOffset] & 0xFF;
+ int above = previousRow[i] & 0xFF;
+
+ int a = Math.abs(above - aboveLeft);
+ int b = Math.abs(left - aboveLeft);
+ int c = Math.abs(left - aboveLeft + above - aboveLeft);
+
+ int preductor = 0;
+ if (a <= b && a <= c) {
+ preductor = left;
+ } else if (b <= c) {
+ preductor = above;
+ } else {
+ preductor = aboveLeft;
+ }
+
+ int currentValue = row[i] & 0xFF;
+ row[i] = (byte) ((currentValue + preductor) & 0xFF);
+ }
+ break;
+ }
+}
+
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngChunk.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngChunk.java
new file mode 100755
index 0000000000..1715ebccb1
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngChunk.java
@@ -0,0 +1,333 @@
+package org.eclipse.swt.internal.image;
+
+import org.eclipse.swt.*;
+import java.io.*;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2000 All Rights Reserved
+ */
+
+class PngChunk extends Object {
+ byte[] reference;
+
+ static final int LENGTH_OFFSET = 0;
+ static final int TYPE_OFFSET = 4;
+ static final int DATA_OFFSET = 8;
+
+ static final int TYPE_FIELD_LENGTH = 4;
+ static final int LENGTH_FIELD_LENGTH = 4;
+ static final int MIN_LENGTH = 12;
+
+ static int[] crcTable;
+
+ static final int CHUNK_UNKNOWN = -1;
+ // Critical chunks.
+ static final int CHUNK_IHDR = 0;
+ static final int CHUNK_PLTE = 1;
+ static final int CHUNK_IDAT = 2;
+ static final int CHUNK_IEND = 3;
+ // Non-critical chunks.
+ static final int CHUNK_tRNS = 5;
+
+ static final byte[] TYPE_IHDR = {(byte) 'I', (byte) 'H', (byte) 'D', (byte) 'R'};
+ static final byte[] TYPE_PLTE = {(byte) 'P', (byte) 'L', (byte) 'T', (byte) 'E'};
+ static final byte[] TYPE_IDAT = {(byte) 'I', (byte) 'D', (byte) 'A', (byte) 'T'};
+ static final byte[] TYPE_IEND = {(byte) 'I', (byte) 'E', (byte) 'N', (byte) 'D'};
+ static final byte[] TYPE_tRNS = {(byte) 't', (byte) 'R', (byte) 'N', (byte) 'S'};
+
+/**
+ * Construct a PngChunk using the reference bytes
+ * given.
+ */
+PngChunk(byte[] reference) {
+ super();
+ setReference(reference);
+}
+
+/**
+ * Get the PngChunk's reference byteArray;
+ */
+byte[] getReference() {
+ return reference;
+}
+
+/**
+ * Set the PngChunk's reference byteArray;
+ */
+void setReference(byte[] reference) {
+ this.reference = reference;
+}
+
+/**
+ * Get the 32-bit integer from the reference byte
+ * array at the given offset.
+ */
+int getInt32(int offset) {
+ int answer = 0;
+ answer |= (reference[offset] & 0xFF) << 24;
+ answer |= (reference[offset + 1] & 0xFF) << 16;
+ answer |= (reference[offset + 2] & 0xFF) << 8;
+ answer |= (reference[offset + 3] & 0xFF);
+ return answer;
+}
+
+/**
+ * Set the 32-bit integer in the reference byte
+ * array at the given offset.
+ */
+void setInt32(int offset, int value) {
+ reference[offset] = (byte) ((value >> 24) & 0xFF);
+ reference[offset + 1] = (byte) ((value >> 16) & 0xFF);
+ reference[offset + 2] = (byte) ((value >> 8) & 0xFF);
+ reference[offset + 3] = (byte) (value & 0xFF);
+}
+
+/**
+ * Get the length of the data component of this chunk.
+ * This is not the length of the entire chunk.
+ */
+int getLength() {
+ return getInt32(LENGTH_OFFSET);
+}
+
+/**
+ * Set the length of the data component of this chunk.
+ * This is not the length of the entire chunk.
+ */
+void setLength(int value) {
+ setInt32(LENGTH_OFFSET, value);
+}
+
+/**
+ * Get the chunk type. This is a four byte value.
+ * Each byte should be an ASCII character.
+ * The first byte is upper case if the chunk is critical.
+ * The second byte is upper case if the chunk is publicly defined.
+ * The third byte must be upper case.
+ * The fourth byte is upper case if the chunk is unsafe to copy.
+ * Public chunk types are defined by the PNG Development Group.
+ */
+byte[] getTypeBytes() {
+ byte[] type = new byte[4];
+ System.arraycopy(reference, TYPE_OFFSET, type, 0, TYPE_FIELD_LENGTH);
+ return type;
+}
+
+/**
+ * Set the chunk type. This is a four byte value.
+ * Each byte should be an ASCII character.
+ * The first byte is upper case if the chunk is critical.
+ * The second byte is upper case if the chunk is publicly defined.
+ * The third byte must be upper case.
+ * The fourth byte is upper case if the chunk is unsafe to copy.
+ * Public chunk types are defined by the PNG Development Group.
+ */
+void setType(byte[] value) {
+ if (value.length != TYPE_FIELD_LENGTH) {
+ throw new SWTException(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ System.arraycopy(value, 0, reference, TYPE_OFFSET, TYPE_FIELD_LENGTH);
+}
+
+/**
+ * Get the chunk's data.
+ */
+byte[] getData() {
+ int dataLength = getLength();
+ if (reference.length < MIN_LENGTH + dataLength) {
+ throw new SWTException(SWT.ERROR_INVALID_RANGE);
+ }
+ byte[] data = new byte[dataLength];
+ System.arraycopy(reference, DATA_OFFSET, data, 0, dataLength);
+ return data;
+}
+
+/**
+ * Set the chunk's data.
+ * This method has two side-effects.
+ * 1. It will set the length field to be the length
+ * of the data array given.
+ * 2. It will set the CRC field to the computed CRC
+ * value of the data array given.
+ */
+void setData(byte[] data) {
+ setLength(data.length);
+ System.arraycopy(data, 0, reference, DATA_OFFSET, data.length);
+ setCRC(computeCRC());
+}
+
+/**
+ * Get the CRC value for the chunk's data.
+ * Ensure that the length field has a good
+ * value before making this call.
+ */
+int getCRC() {
+ int crcOffset = DATA_OFFSET + getLength();
+ return getInt32(crcOffset);
+}
+
+/**
+ * Set the CRC value for the chunk's data.
+ * Ensure that the length field has a good
+ * value before making this call.
+ */
+void setCRC(int value) {
+ int crcOffset = DATA_OFFSET + getLength();
+ setInt32(crcOffset, value);
+}
+
+/**
+ * Get the chunk's total size including the length, type, and crc fields.
+ */
+int getSize() {
+ return MIN_LENGTH + getLength();
+}
+
+/**
+ * Compute the CRC value for the chunk's data. Answer
+ * whether this value matches the value stored in the
+ * chunk.
+ */
+boolean checkCRC() {
+ int crc = computeCRC();
+ int storedCRC = getCRC();
+ return crc == storedCRC;
+}
+
+/**
+ * Answer the CRC value of chunk's data.
+ */
+int computeCRC() {
+ if (crcTable == null) {
+ crcTable = new int[256];
+ for (int i = 0; i < 256; i++) {
+ crcTable[i] = i;
+ for (int j = 0; j < 8; j++) {
+ if ((crcTable[i] & 0x1) == 0) {
+ crcTable[i] = (crcTable[i] >> 1) & 0x7FFFFFFF;
+ } else {
+ crcTable[i] = 0xEDB88320 ^ ((crcTable[i] >> 1) & 0x7FFFFFFF);
+ }
+ }
+ }
+ }
+ int crc = 0xFFFFFFFF;
+ int start = TYPE_OFFSET;
+ int stop = DATA_OFFSET + getLength();
+ for (int i = start; i < stop; i++) {
+ int index = (crc ^ reference[i]) & 0xFF;
+ crc = crcTable[index] ^ ((crc >> 8) & 0x00FFFFFF);
+ }
+ return ~crc;
+}
+
+boolean typeMatchesArray(byte[] array) {
+ for (int i = 0; i < TYPE_FIELD_LENGTH; i++) {
+ if (reference[TYPE_OFFSET + i] != array[i]){
+ return false;
+ }
+ }
+ return true;
+}
+
+boolean isCritical() {
+ return Character.isUpperCase((char) getTypeBytes()[0]);
+}
+
+int getChunkType() {
+ if (typeMatchesArray(TYPE_IHDR)) return CHUNK_IHDR;
+ if (typeMatchesArray(TYPE_PLTE)) return CHUNK_PLTE;
+ if (typeMatchesArray(TYPE_IDAT)) return CHUNK_IDAT;
+ if (typeMatchesArray(TYPE_IEND)) return CHUNK_IEND;
+ if (typeMatchesArray(TYPE_tRNS)) return CHUNK_tRNS;
+ return CHUNK_UNKNOWN;
+}
+
+
+
+
+/**
+ * Read the next PNG chunk from the input stream given.
+ * If unable to read a chunk, return null.
+ */
+static PngChunk readNextFromStream(LEDataInputStream stream) {
+ try {
+ int headerLength = LENGTH_FIELD_LENGTH + TYPE_FIELD_LENGTH;
+ byte[] headerBytes = new byte[headerLength];
+ int result = stream.read(headerBytes, 0, headerLength);
+ stream.unread(headerBytes);
+ if (result != headerLength) return null;
+
+ PngChunk tempChunk = new PngChunk(headerBytes);
+
+ int chunkLength = tempChunk.getSize();
+ byte[] chunk = new byte[chunkLength];
+ result = stream.read(chunk, 0, chunkLength);
+ if (result != chunkLength) return null;
+
+ switch (tempChunk.getChunkType()) {
+ case CHUNK_IHDR:
+ return new PngIhdrChunk(chunk);
+ case CHUNK_PLTE:
+ return new PngPlteChunk(chunk);
+ case CHUNK_IDAT:
+ return new PngIdatChunk(chunk);
+ case CHUNK_IEND:
+ return new PngIendChunk(chunk);
+ case CHUNK_tRNS:
+ return new PngTrnsChunk(chunk);
+ default:
+ return new PngChunk(chunk);
+ }
+ } catch (IOException e) {
+ return null;
+ }
+}
+
+/**
+ * Answer whether the chunk is a valid PNG chunk.
+ */
+void validate(PngFileReadState readState, PngIhdrChunk headerChunk) {
+ if (reference.length < MIN_LENGTH) SWT.error(SWT.ERROR_INVALID_IMAGE);
+
+ byte[] type = getTypeBytes();
+
+ // The third character MUST be upper case.
+ if (!Character.isUpperCase((char) type[2])) SWT.error(SWT.ERROR_INVALID_IMAGE);
+
+ // All characters must be letters.
+ for (int i = 0; i < TYPE_FIELD_LENGTH; i++) {
+ if (!Character.isLetter((char) type[i])) SWT.error(SWT.ERROR_INVALID_IMAGE);
+ }
+
+ // The stored CRC must match the data's computed CRC.
+ if (!checkCRC()) SWT.error(SWT.ERROR_INVALID_IMAGE);
+}
+
+/**
+ * Provided so that subclasses can override and add
+ * data to the toString() call.
+ */
+void contributeToString(StringBuffer buffer) {}
+
+public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("{");
+ buffer.append("\n\tLength: ");
+ buffer.append(getLength());
+ buffer.append("\n\tType: ");
+ byte[] type = getTypeBytes();
+ for(int i = 0; i < type.length; i++) {
+ buffer.append((char) type[i]);
+ }
+
+ contributeToString(buffer);
+
+ buffer.append("\n\tCRC: ");
+ buffer.append(Integer.toHexString(getCRC()));
+ buffer.append("\n}");
+ return buffer.toString();
+}
+
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngChunkReader.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngChunkReader.java
new file mode 100755
index 0000000000..f93b716697
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngChunkReader.java
@@ -0,0 +1,64 @@
+package org.eclipse.swt.internal.image;
+
+import org.eclipse.swt.*;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2000 All Rights Reserved
+ */
+
+public class PngChunkReader {
+ LEDataInputStream inputStream;
+ PngFileReadState readState;
+ PngIhdrChunk headerChunk;
+ PngPlteChunk paletteChunk;
+
+PngChunkReader(LEDataInputStream inputStream) {
+ this.inputStream = inputStream;
+ readState = new PngFileReadState();
+ headerChunk = null;
+}
+
+PngIhdrChunk getIhdrChunk() {
+ if (headerChunk == null) {
+ try {
+ PngChunk chunk = PngChunk.readNextFromStream(inputStream);
+ headerChunk = (PngIhdrChunk) chunk;
+ headerChunk.validate(readState, null);
+ } catch (ClassCastException e) {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ }
+ }
+ return headerChunk;
+}
+
+PngChunk readNextChunk() {
+ if (headerChunk == null) return getIhdrChunk();
+
+ PngChunk chunk = PngChunk.readNextFromStream(inputStream);
+ switch (chunk.getChunkType()) {
+ case PngChunk.CHUNK_tRNS:
+ ((PngTrnsChunk) chunk).validate(readState, headerChunk, paletteChunk);
+ break;
+ case PngChunk.CHUNK_PLTE:
+ chunk.validate(readState, headerChunk);
+ paletteChunk = (PngPlteChunk) chunk;
+ break;
+ default:
+ chunk.validate(readState, headerChunk);
+ }
+ if (readState.readIDAT && !(chunk.getChunkType() == PngChunk.CHUNK_IDAT)) {
+ readState.readPixelData = true;
+ }
+ return chunk;
+}
+
+boolean readPixelData() {
+ return readState.readPixelData;
+}
+
+boolean hasMoreChunks() {
+ return !readState.readIEND;
+}
+
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngDecodingDataStream.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngDecodingDataStream.java
new file mode 100755
index 0000000000..1800a2415b
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngDecodingDataStream.java
@@ -0,0 +1,131 @@
+package org.eclipse.swt.internal.image;
+
+import java.io.*;
+import org.eclipse.swt.*;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2000 All Rights Reserved
+ */
+
+public class PngDecodingDataStream {
+ PngIdatChunk currentChunk;
+ PngChunkReader chunkReader;
+ byte currentByte;
+ int nextByteIndex;
+ int nextBitIndex;
+
+ PngLzBlockReader lzBlockReader;
+ int adlerValue;
+
+ static final int PRIME = 65521;
+ static final int MAX_BIT = 7;
+
+PngDecodingDataStream(PngIdatChunk idatChunk, PngChunkReader chunkReader) {
+ super();
+ this.currentChunk = idatChunk;
+ this.chunkReader = chunkReader;
+ nextByteIndex = 0;
+ nextBitIndex = MAX_BIT + 1;
+ adlerValue = 1;
+ lzBlockReader = new PngLzBlockReader(this);
+ readCompressedDataHeader();
+ lzBlockReader.readNextBlockHeader();
+}
+
+/**
+ * This method should be called when the image decoder thinks
+ * that all of the compressed image data has been read. This
+ * method will ensure that the next data value is an end of
+ * block marker. If there are more blocks after this one,
+ * the method will read them and ensure that they are empty.
+ */
+void assertImageDataAtEnd() {
+ lzBlockReader.assertCompressedDataAtEnd();
+}
+
+int getNextIdatBits(int length) {
+ int value = 0;
+ for (int i = 0; i < length; i++) {
+ value |= (getNextIdatBit() << i);
+ }
+ return value;
+}
+
+byte getNextIdatBit() {
+ if (nextBitIndex > MAX_BIT) {
+ currentByte = getNextIdatByte();
+ nextBitIndex = 0;
+ }
+ int mask = 1 << nextBitIndex;
+ nextBitIndex++;
+ return ((currentByte & mask) > 0) ? (byte) 1 : (byte) 0;
+}
+
+private PngIdatChunk getNextChunk() {
+ PngChunk chunk = chunkReader.readNextChunk();
+ if (chunk == null) error();
+ if (chunk.getChunkType() != PngChunk.CHUNK_IDAT) error();
+ return (PngIdatChunk) chunk;
+}
+
+byte getNextIdatByte() {
+ if (nextByteIndex > currentChunk.getLength() - 1) {
+ currentChunk = getNextChunk();
+ nextByteIndex = 0;
+ }
+ byte nextByte = currentChunk.getDataByteAtOffset(nextByteIndex);
+ nextByteIndex++;
+ nextBitIndex = MAX_BIT + 1;
+ return nextByte;
+}
+
+private void updateAdler(byte value) {
+ int low = adlerValue & 0xFFFF;
+ int high = (adlerValue >> 16) & 0xFFFF;
+ int valueInt = value & 0xFF;
+ low = (low + valueInt) % PRIME;
+ high = (low + high) % PRIME;
+ adlerValue = (high << 16) | low;
+}
+
+byte getNextDecodedByte() {
+ byte nextDecodedByte = lzBlockReader.getNextByte();
+ updateAdler(nextDecodedByte);
+ return nextDecodedByte;
+}
+
+void error() {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+}
+
+private void readCompressedDataHeader() {
+ byte headerByte1 = getNextIdatByte();
+ byte headerByte2 = getNextIdatByte();
+
+ int number = (headerByte1 << 8) | (headerByte2 & 0xFF);
+ if (number % 31 != 0) error();
+
+ int compressionMethod = headerByte1 & 0x0F;
+ if (compressionMethod != 8) error();
+
+ int windowSizeHint = (headerByte1 & 0xF0) >> 4;
+ if (windowSizeHint > 7) error();
+ int windowSize = (1 << (windowSizeHint + 8));
+ lzBlockReader.setWindowSize(windowSize);
+
+ int dictionary = (headerByte2 & (1 << 5));
+ if (dictionary != 0) error();
+
+ int compressionLevel = (headerByte2 & 0xC0) >> 6;
+}
+
+void checkAdler() {
+ int storedAdler = ((getNextIdatByte() & 0xFF) << 24)
+ | ((getNextIdatByte() & 0xFF) << 16)
+ | ((getNextIdatByte() & 0xFF) << 8)
+ | (getNextIdatByte() & 0xFF);
+ if (storedAdler != adlerValue) error();
+}
+
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngFileReadState.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngFileReadState.java
new file mode 100755
index 0000000000..13e23783f3
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngFileReadState.java
@@ -0,0 +1,20 @@
+package org.eclipse.swt.internal.image;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2000 All Rights Reserved
+ */
+
+class PngFileReadState extends Object {
+ boolean readIHDR;
+ boolean readPLTE;
+ boolean readIDAT;
+ boolean readIEND;
+
+ // Non - critical chunks
+ boolean readBKGD;
+ boolean readTRNS;
+
+ // Set to true after IDATs have been read.
+ boolean readPixelData;
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngHuffmanTable.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngHuffmanTable.java
new file mode 100755
index 0000000000..5c5eafa9a7
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngHuffmanTable.java
@@ -0,0 +1,122 @@
+package org.eclipse.swt.internal.image;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2000 All Rights Reserved
+ */
+
+public class PngHuffmanTable {
+ CodeLengthInfo[] codeLengthInfo;
+ int[] codeValues;
+
+ static final int MAX_CODE_LENGTH = 15;
+ static final int BAD_CODE = 0xFFFFFFF;
+
+PngHuffmanTable (int[] lengths) {
+ super();
+ initialize(lengths);
+ generateTable(lengths);
+}
+
+private void initialize(int[] lengths) {
+ codeValues = new int[lengths.length];
+ for (int i = 0; i < codeValues.length; i++) {
+ codeValues[i] = i;
+ }
+
+ // minCodesByLength[n] : The smallest Huffman code of length n + 1.
+ // maxCodesByLength[n] : The largest Huffman code of length n + 1.
+ // indexesByLength[n] : Index into the values array. First value with a code of length n + 1.
+ codeLengthInfo = new CodeLengthInfo[MAX_CODE_LENGTH];
+ for (int i = 0; i < MAX_CODE_LENGTH; i++) {
+ codeLengthInfo[i] = new CodeLengthInfo();
+ codeLengthInfo[i].length = i;
+ codeLengthInfo[i].baseIndex = 0;
+ codeLengthInfo[i].min = BAD_CODE;
+ codeLengthInfo[i].max = -1;
+ }
+}
+
+private void generateTable(int[] lengths) {
+ // Sort the values. Primary key is code size. Secondary key is value.
+ for (int i = 0; i < lengths.length - 1; i++) {
+ for (int j = i + 1; j < lengths.length; j++) {
+ if (lengths[j] < lengths[i]
+ || (lengths[j] == lengths[i]
+ && codeValues[j] < codeValues[i]))
+ {
+ int tmp;
+ tmp = lengths[j];
+ lengths[j] = lengths[i];
+ lengths[i] = tmp;
+ tmp = codeValues[j];
+ codeValues[j] = codeValues[i];
+ codeValues[i] = tmp;
+ }
+ }
+ }
+
+ // These values in these arrays correspond to the elements of the
+ // "values" array. The Huffman code for codeValues[N] is codes[N]
+ // and the length of the code is lengths[N].
+ int[] codes = new int[lengths.length];
+ int lastLength = 0;
+ int code = 0;
+ for (int i = 0; i < lengths.length; i++) {
+ while (lastLength != lengths[i]) {
+ lastLength++;
+ code <<= 1;
+ }
+ if (lastLength != 0) {
+ codes[i] = code;
+ code++;
+ }
+ }
+
+ int last = 0;
+ for (int i = 0; i < lengths.length; i++) {
+ if (last != lengths[i]) {
+ last = lengths[i];
+ codeLengthInfo[last - 1].baseIndex = i;
+ codeLengthInfo[last - 1].min = codes[i];
+ }
+ if (last != 0) codeLengthInfo[last - 1].max = codes[i];
+ }
+}
+
+int getNextValue(PngDecodingDataStream stream) {
+ int code = stream.getNextIdatBit();
+ int codelength = 0;
+
+ // Here we are taking advantage of the fact that 1 bits are used as
+ // a prefix to the longer codeValues.
+ while (code > codeLengthInfo[codelength].max && codelength < MAX_CODE_LENGTH) {
+ code = ((code << 1) | stream.getNextIdatBit());
+ codelength++;
+ }
+ if (codelength >= MAX_CODE_LENGTH) stream.error();
+
+ // Now we have a Huffman code of length (codelength + 1) that
+ // is somewhere in the range
+ // minCodesByLength[codelength]..maxCodesByLength[codelength].
+ // This code is the (offset + 1)'th code of (codelength + 1);
+ int offset = code - codeLengthInfo[codelength].min;
+
+ // indexesByLength[codelength] is the first code of length (codelength + 1)
+ // so now we can look up the value for the Huffman code in the table.
+ int index = codeLengthInfo[codelength].baseIndex + offset;
+ return codeValues[index];
+}
+
+class CodeValuePair {
+ int value;
+ int code;
+}
+class CodeLengthInfo {
+ int length;
+ int max;
+ int min;
+ int baseIndex;
+}
+
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngHuffmanTables.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngHuffmanTables.java
new file mode 100755
index 0000000000..383323da97
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngHuffmanTables.java
@@ -0,0 +1,156 @@
+package org.eclipse.swt.internal.image;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2000 All Rights Reserved
+ */
+
+public class PngHuffmanTables {
+ PngHuffmanTable literalTable;
+ PngHuffmanTable distanceTable;
+
+ static PngHuffmanTable FixedLiteralTable;
+ static PngHuffmanTable FixedDistanceTable;
+
+ static final int LiteralTableSize = 288;
+ static final int[] FixedLiteralLengths = {
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8,
+ };
+
+ static final int DistanceTableSize = 32;
+ static final int[] FixedDistanceLengths = {
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ };
+
+ static final int LengthCodeTableSize = 19;
+ static final int[] LengthCodeOrder = {
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5,
+ 11, 4, 12, 3, 13, 2, 14, 1, 15
+ };
+
+static PngHuffmanTables getDynamicTables(PngDecodingDataStream stream){
+ return new PngHuffmanTables(stream);
+}
+static PngHuffmanTables getFixedTables() {
+ return new PngHuffmanTables();
+}
+
+private PngHuffmanTable getFixedLiteralTable() {
+ if (FixedLiteralTable == null) {
+ FixedLiteralTable = new PngHuffmanTable(FixedLiteralLengths);
+ }
+ return FixedLiteralTable;
+}
+
+private PngHuffmanTable getFixedDistanceTable() {
+ if (FixedDistanceTable == null) {
+ FixedDistanceTable = new PngHuffmanTable(FixedDistanceLengths);
+ }
+ return FixedDistanceTable;
+}
+
+private PngHuffmanTables () {
+ super();
+ literalTable = getFixedLiteralTable();
+ distanceTable = getFixedDistanceTable();
+}
+
+private PngHuffmanTables (PngDecodingDataStream stream) {
+ super();
+
+ int literals = PngLzBlockReader.FIRST_LENGTH_CODE
+ + stream.getNextIdatBits(5);
+ int distances = PngLzBlockReader.FIRST_DISTANCE_CODE
+ + stream.getNextIdatBits(5);
+ int codeLengthCodes = PngLzBlockReader.FIRST_CODE_LENGTH_CODE
+ + stream.getNextIdatBits(4);
+
+ if (codeLengthCodes > PngLzBlockReader.LAST_CODE_LENGTH_CODE) {
+ stream.error();
+ }
+
+ /* Tricky, tricky, tricky. The length codes are stored in
+ * a very odd order. (For the order, see the definition of
+ * the static field lengthCodeOrder.) Also, the data may
+ * not contain values for all the codes. It may just contain
+ * values for the first X number of codes. The table should
+ * be of size <LengthCodeTableSize> regardless of the number
+ * of values actually given in the table.
+ */
+ int[] lengthCodes = new int[LengthCodeTableSize];
+ for (int i = 0; i < codeLengthCodes; i++) {
+ lengthCodes[LengthCodeOrder[i]] = stream.getNextIdatBits(3);
+ }
+ PngHuffmanTable codeLengthsTable = new PngHuffmanTable(lengthCodes);
+
+ int[] literalLengths = readLengths(
+ stream, literals, codeLengthsTable, LiteralTableSize);
+ int[] distanceLengths = readLengths(
+ stream, distances, codeLengthsTable, DistanceTableSize);
+
+ literalTable = new PngHuffmanTable(literalLengths);
+ distanceTable = new PngHuffmanTable(distanceLengths);
+}
+
+private int [] readLengths (PngDecodingDataStream stream,
+ int numLengths,
+ PngHuffmanTable lengthsTable,
+ int tableSize)
+{
+ int[] lengths = new int[tableSize];
+
+ for (int index = 0; index < numLengths;) {
+ int value = lengthsTable.getNextValue(stream);
+ if (value < 16) {
+ // Literal value
+ lengths[index] = value;
+ index++;
+ } else if (value == 16) {
+ // Repeat the previous code 3-6 times.
+ int count = stream.getNextIdatBits(2) + 3;
+ for (int i = 0; i < count; i++) {
+ lengths[index] = lengths [index - 1];
+ index++;
+ }
+ } else if (value == 17) {
+ // Repeat 0 3-10 times.
+ int count = stream.getNextIdatBits(3) + 3;
+ for (int i = 0; i < count; i++) {
+ lengths[index] = 0;
+ index++;
+ }
+ } else if (value == 18) {
+ // Repeat 0 11-138 times.
+ int count = stream.getNextIdatBits(7) + 11;
+ for (int i = 0; i < count; i++) {
+ lengths[index] = 0;
+ index++;
+ }
+ } else {
+ stream.error();
+ }
+ }
+ return lengths;
+}
+
+int getNextLiteralValue(PngDecodingDataStream stream) {
+ return literalTable.getNextValue(stream);
+}
+
+int getNextDistanceValue(PngDecodingDataStream stream) {
+ return distanceTable.getNextValue(stream);
+}
+
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngIdatChunk.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngIdatChunk.java
new file mode 100755
index 0000000000..883326ebe3
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngIdatChunk.java
@@ -0,0 +1,36 @@
+package org.eclipse.swt.internal.image;
+
+import org.eclipse.swt.*;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2000 All Rights Reserved
+ */
+
+class PngIdatChunk extends PngChunk {
+
+PngIdatChunk(byte[] reference){
+ super(reference);
+}
+
+/**
+ * Answer whether the chunk is a valid IDAT chunk.
+ */
+void validate(PngFileReadState readState, PngIhdrChunk headerChunk) {
+ if (!readState.readIHDR
+ || (headerChunk.getMustHavePalette() && !readState.readPLTE)
+ || readState.readIEND)
+ {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ } else {
+ readState.readIDAT = true;
+ }
+
+ super.validate(readState, headerChunk);
+}
+
+byte getDataByteAtOffset(int offset) {
+ return reference[DATA_OFFSET + offset];
+}
+
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngIendChunk.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngIendChunk.java
new file mode 100755
index 0000000000..189cf8f7a3
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngIendChunk.java
@@ -0,0 +1,39 @@
+package org.eclipse.swt.internal.image;
+
+import org.eclipse.swt.*;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2000 All Rights Reserved
+ */
+
+class PngIendChunk extends PngChunk {
+
+PngIendChunk(byte[] reference){
+ super(reference);
+}
+
+/**
+ * Answer whether the chunk is a valid IEND chunk.
+ */
+void validate(PngFileReadState readState, PngIhdrChunk headerChunk) {
+ // An IEND chunk is invalid if no IHDR has been read.
+ // Or if a palette is required and has not been read.
+ // Or if no IDAT chunk has been read.
+ if (!readState.readIHDR
+ || (headerChunk.getMustHavePalette() && !readState.readPLTE)
+ || !readState.readIDAT
+ || readState.readIEND)
+ {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ } else {
+ readState.readIEND = true;
+ }
+
+ super.validate(readState, headerChunk);
+
+ // IEND chunks are not allowed to have any data.
+ if (getLength() > 0) SWT.error(SWT.ERROR_INVALID_IMAGE);
+}
+
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngIhdrChunk.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngIhdrChunk.java
new file mode 100755
index 0000000000..00f3cec52e
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngIhdrChunk.java
@@ -0,0 +1,372 @@
+package org.eclipse.swt.internal.image;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2000 All Rights Reserved
+ */
+
+class PngIhdrChunk extends PngChunk {
+ static final int EXPECTED_DATA_LENGTH = 13;
+
+ static final int WIDTH_DATA_OFFSET = DATA_OFFSET + 0;
+ static final int HEIGHT_DATA_OFFSET = DATA_OFFSET + 4;
+ static final int BIT_DEPTH_OFFSET = DATA_OFFSET + 8;
+ static final int COLOR_TYPE_OFFSET = DATA_OFFSET + 9;
+ static final int COMPRESSION_METHOD_OFFSET = DATA_OFFSET + 10;
+ static final int FILTER_METHOD_OFFSET = DATA_OFFSET + 11;
+ static final int INTERLACE_METHOD_OFFSET = DATA_OFFSET + 12;
+
+ static final int COLOR_TYPE_GRAYSCALE = 0;
+ static final int COLOR_TYPE_RGB = 2;
+ static final int COLOR_TYPE_PALETTE = 3;
+ static final int COLOR_TYPE_GRAYSCALE_WITH_ALPHA = 4;
+ static final int COLOR_TYPE_RGB_WITH_ALPHA = 6;
+
+ static final int INTERLACE_METHOD_NONE = 0;
+ static final int INTERLACE_METHOD_ADAM7 = 1;
+
+ static final int FILTER_NONE = 0;
+ static final int FILTER_SUB = 1;
+ static final int FILTER_UP = 2;
+ static final int FILTER_AVERAGE = 3;
+ static final int FILTER_PAETH = 4;
+
+ static final byte[] ValidBitDepths = {1, 2, 4, 8, 16};
+ static final byte[] ValidColorTypes = {0, 2, 3, 4, 6};
+
+/**
+ * Construct a PNGChunk using the reference bytes
+ * given.
+ */
+PngIhdrChunk(byte[] reference) {
+ super(reference);
+}
+
+/**
+ * Get the image's width in pixels.
+ */
+int getWidth() {
+ return getInt32(WIDTH_DATA_OFFSET);
+}
+
+/**
+ * Set the image's width in pixels.
+ */
+void setWidth(int value) {
+ setInt32(WIDTH_DATA_OFFSET, value);
+}
+
+/**
+ * Get the image's height in pixels.
+ */
+int getHeight() {
+ return getInt32(HEIGHT_DATA_OFFSET);
+}
+
+/**
+ * Set the image's height in pixels.
+ */
+void setHeight(int value) {
+ setInt32(HEIGHT_DATA_OFFSET, value);
+}
+
+/**
+ * Get the image's bit depth.
+ * This is limited to the values 1, 2, 4, 8, or 16.
+ */
+byte getBitDepth() {
+ return reference[BIT_DEPTH_OFFSET];
+}
+
+/**
+ * Set the image's bit depth.
+ * This is limited to the values 1, 2, 4, 8, or 16.
+ */
+void setBitDepth(byte value) {
+ reference[BIT_DEPTH_OFFSET] = value;
+}
+
+/**
+ * Get the image's color type.
+ * This is limited to the values:
+ * 0 - Grayscale image.
+ * 2 - RGB triple.
+ * 3 - Palette.
+ * 4 - Grayscale with Alpha channel.
+ * 6 - RGB with Alpha channel.
+ */
+byte getColorType() {
+ return reference[COLOR_TYPE_OFFSET];
+}
+
+/**
+ * Set the image's color type.
+ * This is limited to the values:
+ * 0 - Grayscale image.
+ * 2 - RGB triple.
+ * 3 - Palette.
+ * 4 - Grayscale with Alpha channel.
+ * 6 - RGB with Alpha channel.
+ */
+void setColorType(byte value) {
+ reference[COLOR_TYPE_OFFSET] = value;
+}
+
+/**
+ * Get the image's compression method.
+ * This value must be 0.
+ */
+byte getCompressionMethod() {
+ return reference[COMPRESSION_METHOD_OFFSET];
+}
+
+/**
+ * Set the image's compression method.
+ * This value must be 0.
+ */
+void setCompressionMethod(byte value) {
+ reference[COMPRESSION_METHOD_OFFSET] = value;
+}
+
+/**
+ * Get the image's filter method.
+ * This value must be 0.
+ */
+byte getFilterMethod() {
+ return reference[FILTER_METHOD_OFFSET];
+}
+
+/**
+ * Set the image's filter method.
+ * This value must be 0.
+ */
+void setFilterMethod(byte value) {
+ reference[FILTER_METHOD_OFFSET] = value;
+}
+
+/**
+ * Get the image's interlace method.
+ * This value is limited to:
+ * 0 - No interlacing used.
+ * 1 - Adam7 interlacing used.
+ */
+byte getInterlaceMethod() {
+ return reference[INTERLACE_METHOD_OFFSET];
+}
+
+/**
+ * Set the image's interlace method.
+ * This value is limited to:
+ * 0 - No interlacing used.
+ * 1 - Adam7 interlacing used.
+ */
+void setInterlaceMethod(byte value) {
+ reference[INTERLACE_METHOD_OFFSET] = value;
+}
+
+/**
+ * Answer whether the chunk is a valid IHDR chunk.
+ */
+void validate(PngFileReadState readState, PngIhdrChunk headerChunk) {
+ // An IHDR chunk is invalid if any other chunk has
+ // been read.
+ if (readState.readIHDR
+ || readState.readPLTE
+ || readState.readIDAT
+ || readState.readIEND)
+ {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ } else {
+ readState.readIHDR = true;
+ }
+
+ super.validate(readState, headerChunk);
+
+ if (getLength() != EXPECTED_DATA_LENGTH) SWT.error(SWT.ERROR_INVALID_IMAGE);
+ if (getCompressionMethod() != 0) SWT.error(SWT.ERROR_INVALID_IMAGE);
+ if (getInterlaceMethod() != INTERLACE_METHOD_NONE &&
+ getInterlaceMethod() != INTERLACE_METHOD_ADAM7) {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ }
+
+ boolean colorTypeIsValid = false;
+ byte colorType = getColorType();
+ for (int i = 0; i < ValidColorTypes.length; i++) {
+ if (ValidColorTypes[i] == colorType) {
+ colorTypeIsValid = true;
+ break;
+ }
+ }
+ if (!colorTypeIsValid) SWT.error(SWT.ERROR_INVALID_IMAGE);;
+
+ boolean bitDepthIsValid = false;
+ byte bitDepth = getBitDepth();
+ for (int i = 0; i < ValidBitDepths.length; i++) {
+ if (ValidBitDepths[i] == bitDepth) {
+ bitDepthIsValid = true;
+ break;
+ }
+ }
+ if (!bitDepthIsValid) SWT.error(SWT.ERROR_INVALID_IMAGE);
+
+ if ((colorType == COLOR_TYPE_RGB
+ || colorType == COLOR_TYPE_RGB_WITH_ALPHA
+ || colorType == COLOR_TYPE_GRAYSCALE_WITH_ALPHA)
+ && bitDepth < 8)
+ {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ }
+
+ if (colorType == COLOR_TYPE_PALETTE && bitDepth > 8) {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ }
+}
+
+String getColorTypeString() {
+ switch (getColorType()) {
+ case COLOR_TYPE_GRAYSCALE: return "Grayscale";
+ case COLOR_TYPE_RGB: return "RGB";
+ case COLOR_TYPE_PALETTE: return "Palette";
+ case COLOR_TYPE_GRAYSCALE_WITH_ALPHA: return "Grayscale with Alpha";
+ case COLOR_TYPE_RGB_WITH_ALPHA: return "RGB with Alpha";
+ default: return "Unknown - " + getColorType();
+ }
+}
+
+String getFilterMethodString() {
+ switch (getFilterMethod()) {
+ case FILTER_NONE: return "None";
+ case FILTER_SUB: return "Sub";
+ case FILTER_UP: return "Up";
+ case FILTER_AVERAGE: return "Average";
+ case FILTER_PAETH: return "Paeth";
+ default: return "Unknown";
+ }
+}
+
+String getInterlaceMethodString() {
+ switch (getInterlaceMethod()) {
+ case INTERLACE_METHOD_NONE: return "Not Interlaced";
+ case INTERLACE_METHOD_ADAM7: return "Interlaced - ADAM7";
+ default: return "Unknown";
+ }
+}
+
+void contributeToString(StringBuffer buffer) {
+ buffer.append("\n\tWidth: ");
+ buffer.append(getWidth());
+ buffer.append("\n\tHeight: ");
+ buffer.append(getHeight());
+ buffer.append("\n\tBit Depth: ");
+ buffer.append(getBitDepth());
+ buffer.append("\n\tColor Type: ");
+ buffer.append(getColorTypeString());
+ buffer.append("\n\tCompression Method: ");
+ buffer.append(getCompressionMethod());
+ buffer.append("\n\tFilter Method: ");
+ buffer.append(getFilterMethodString());
+ buffer.append("\n\tInterlace Method: ");
+ buffer.append(getInterlaceMethodString());
+}
+
+boolean getMustHavePalette() {
+ return getColorType() == COLOR_TYPE_PALETTE;
+}
+
+boolean getCanHavePalette() {
+ int colorType = getColorType();
+ return colorType != COLOR_TYPE_GRAYSCALE &&
+ colorType != COLOR_TYPE_GRAYSCALE_WITH_ALPHA;
+}
+
+/**
+ * Answer the pixel size in bits based on the color type
+ * and bit depth.
+ */
+int getBitsPerPixel() {
+ int bitDepth = getBitDepth();
+ switch (getColorType()) {
+ case COLOR_TYPE_RGB_WITH_ALPHA:
+ return 4 * bitDepth;
+ case COLOR_TYPE_RGB:
+ return 3 * bitDepth;
+ case COLOR_TYPE_GRAYSCALE_WITH_ALPHA:
+ return 2 * bitDepth;
+ case COLOR_TYPE_GRAYSCALE:
+ case COLOR_TYPE_PALETTE:
+ return bitDepth;
+ default:
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ return 0;
+ }
+}
+
+/**
+ * Answer the pixel size in bits based on the color type
+ * and bit depth.
+ */
+int getSwtBitsPerPixel() {
+ int bitDepth = getBitDepth();
+ switch (getColorType()) {
+ case COLOR_TYPE_RGB_WITH_ALPHA:
+ case COLOR_TYPE_RGB:
+ case COLOR_TYPE_GRAYSCALE_WITH_ALPHA:
+ return 24;
+ case COLOR_TYPE_GRAYSCALE:
+ case COLOR_TYPE_PALETTE:
+ return Math.min(bitDepth, 8);
+ default:
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ return 0;
+ }
+}
+
+int getFilterByteOffset() {
+ if (getBitDepth() < 8) return 1;
+ return getBitsPerPixel() / 8;
+}
+
+boolean usesDirectColor() {
+ switch (getColorType()) {
+ case COLOR_TYPE_GRAYSCALE:
+ case COLOR_TYPE_GRAYSCALE_WITH_ALPHA:
+ case COLOR_TYPE_RGB:
+ case COLOR_TYPE_RGB_WITH_ALPHA:
+ return true;
+ default:
+ return false;
+ }
+}
+
+PaletteData createGrayscalePalette() {
+ int bitDepth = Math.min(getBitDepth(), 8);
+ int max = (int) (Math.pow(2, bitDepth) - 1);
+ int delta = 255 / max;
+ int gray = 0;
+ RGB[] rgbs = new RGB[max + 1];
+ for (int i = 0; i <= max; i++) {
+ rgbs[i] = new RGB(gray, gray, gray);
+ gray += delta;
+ }
+ return new PaletteData(rgbs);
+}
+
+PaletteData getPaletteData() {
+ switch (getColorType()) {
+ case COLOR_TYPE_GRAYSCALE:
+ return createGrayscalePalette();
+ case COLOR_TYPE_GRAYSCALE_WITH_ALPHA:
+ case COLOR_TYPE_RGB:
+ case COLOR_TYPE_RGB_WITH_ALPHA:
+ return new PaletteData(0xFF0000, 0xFF00, 0xFF);
+ default:
+ return null;
+ }
+}
+
+
+
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngLzBlockReader.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngLzBlockReader.java
new file mode 100755
index 0000000000..eab8cdfa7b
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngLzBlockReader.java
@@ -0,0 +1,169 @@
+package org.eclipse.swt.internal.image;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2000 All Rights Reserved
+ */
+
+public class PngLzBlockReader {
+ boolean readHeader;
+ boolean isLastBlock;
+ byte compressionType;
+ int uncompressedBytesRemaining;
+ PngDecodingDataStream stream;
+ PngHuffmanTables huffmanTables;
+
+ byte[] window;
+ int windowIndex;
+ int copyIndex;
+ int copyBytesRemaining;
+
+ static final int UNCOMPRESSED = 0;
+ static final int COMPRESSED_FIXED = 1;
+ static final int COMPRESSED_DYNAMIC = 2;
+
+ static final int END_OF_COMPRESSED_BLOCK = 256;
+ static final int FIRST_LENGTH_CODE = 257;
+ static final int LAST_LENGTH_CODE = 285;
+ static final int FIRST_DISTANCE_CODE = 1;
+ static final int LAST_DISTANCE_CODE = 29;
+ static final int FIRST_CODE_LENGTH_CODE = 4;
+ static final int LAST_CODE_LENGTH_CODE = 19;
+
+ static final int[] lengthBases = {
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27,
+ 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258
+ } ;
+ static final int[] extraLengthBits = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0,
+ };
+ static final int[] distanceBases = {
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129,
+ 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097,
+ 6145, 8193, 12289, 16385, 24577,
+ };
+ static final int[] extraDistanceBits = {
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
+ 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13,
+ };
+
+
+PngLzBlockReader(PngDecodingDataStream stream) {
+ this.stream = stream;
+ readHeader = false;
+ isLastBlock = false;
+}
+
+void setWindowSize(int windowSize) {
+ window = new byte[windowSize];
+}
+
+void readNextBlockHeader() {
+ isLastBlock = stream.getNextIdatBit() != 0;
+ compressionType = (byte)(stream.getNextIdatBits(2) & 0xFF);
+ if (compressionType > 2) stream.error();
+
+ if (compressionType == UNCOMPRESSED) {
+ int length = stream.getNextIdatByte()
+ | (stream.getNextIdatByte() << 8);
+ int testValue = stream.getNextIdatByte()
+ | (stream.getNextIdatByte() << 8);
+ if (length != ~testValue) stream.error();
+ uncompressedBytesRemaining = length;
+ } else if (compressionType == COMPRESSED_DYNAMIC) {
+ huffmanTables = PngHuffmanTables.getDynamicTables(stream);
+ } else {
+ huffmanTables = PngHuffmanTables.getFixedTables();
+ }
+}
+
+byte getNextByte() {
+ if (compressionType == UNCOMPRESSED) {
+ if (uncompressedBytesRemaining == 0) {
+ readNextBlockHeader();
+ return getNextByte();
+ }
+ uncompressedBytesRemaining--;
+ return stream.getNextIdatByte();
+ } else {
+ byte value = getNextCompressedByte();
+ if (value == END_OF_COMPRESSED_BLOCK) {
+ if (isLastBlock) stream.error();
+ readNextBlockHeader();
+ return getNextByte();
+ } else {
+ return value;
+ }
+ }
+}
+
+private void assertBlockAtEnd() {
+ if (compressionType == UNCOMPRESSED) {
+ if (uncompressedBytesRemaining > 0) stream.error();
+ } else if (copyBytesRemaining > 0 ||
+ (huffmanTables.getNextLiteralValue(stream) != END_OF_COMPRESSED_BLOCK))
+ {
+ stream.error();
+ }
+}
+void assertCompressedDataAtEnd() {
+ assertBlockAtEnd();
+ while (!isLastBlock) {
+ readNextBlockHeader();
+ assertBlockAtEnd();
+ }
+}
+
+private byte getNextCompressedByte() {
+ if (copyBytesRemaining > 0) {
+ byte value = window[copyIndex];
+ byte temp = (byte) (value & 0xFF);
+ window[windowIndex] = value;
+ copyBytesRemaining--;
+
+ copyIndex++;
+ windowIndex++;
+ if (copyIndex == window.length) copyIndex = 0;
+ if (windowIndex == window.length) windowIndex = 0;
+
+ return value;
+ }
+
+ int value = huffmanTables.getNextLiteralValue(stream);
+ if (value < END_OF_COMPRESSED_BLOCK) {
+ byte temp = (byte) (value & 0xFF);
+ window[windowIndex] = (byte) (value & 0xFF);
+ windowIndex++;
+ if (windowIndex >= window.length) windowIndex = 0;
+ return (byte) (value & 0xFF);
+ } else if (value == END_OF_COMPRESSED_BLOCK) {
+ readNextBlockHeader();
+ return getNextCompressedByte();
+ } else if (value <= LAST_LENGTH_CODE) {
+ int extraBits = extraLengthBits[value - FIRST_LENGTH_CODE];
+ int length = lengthBases[value - FIRST_LENGTH_CODE];
+ if (extraBits > 0) {
+ length += stream.getNextIdatBits(extraBits);
+ }
+
+ value = huffmanTables.getNextDistanceValue(stream);
+ if (value > LAST_DISTANCE_CODE) stream.error();
+ extraBits = extraDistanceBits[value];
+ int distance = distanceBases[value];
+ if (extraBits > 0) {
+ distance += stream.getNextIdatBits(extraBits);
+ }
+
+ copyIndex = windowIndex - distance;
+ if (copyIndex < 0) copyIndex += window.length;
+
+ copyBytesRemaining = length;
+ return getNextCompressedByte();
+ } else {
+ stream.error();
+ return 0;
+ }
+}
+
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngPlteChunk.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngPlteChunk.java
new file mode 100755
index 0000000000..8c41b83d22
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngPlteChunk.java
@@ -0,0 +1,87 @@
+package org.eclipse.swt.internal.image;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2000 All Rights Reserved
+ */
+
+class PngPlteChunk extends PngChunk {
+
+PngPlteChunk(byte[] reference){
+ super(reference);
+}
+
+/**
+ * Get the number of colors in this palette.
+ */
+int getPaletteSize() {
+ return getLength() / 3;
+}
+
+/**
+ * Get a PaletteData object representing the colors
+ * stored in this PLTE chunk.
+ * The result should be cached as the PLTE chunk
+ * does not store the palette data created.
+ */
+PaletteData getPaletteData() {
+ RGB[] rgbs = new RGB[getPaletteSize()];
+ int start = DATA_OFFSET;
+ int end = DATA_OFFSET + getLength();
+ for (int i = 0; i < rgbs.length; i++) {
+ int offset = DATA_OFFSET + (i * 3);
+ int red = reference[offset] & 0xFF;
+ int green = reference[offset + 1] & 0xFF;
+ int blue = reference[offset + 2] & 0xFF;
+ rgbs[i] = new RGB(red, green, blue);
+ }
+ return new PaletteData(rgbs);
+}
+
+/**
+ * Answer whether the chunk is a valid PLTE chunk.
+ */
+void validate(PngFileReadState readState, PngIhdrChunk headerChunk) {
+ // A PLTE chunk is invalid if no IHDR has been read or if any PLTE,
+ // IDAT, or IEND chunk has been read.
+ if (!readState.readIHDR
+ || readState.readPLTE
+ || readState.readTRNS
+ || readState.readBKGD
+ || readState.readIDAT
+ || readState.readIEND)
+ {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ } else {
+ readState.readPLTE = true;
+ }
+
+ super.validate(readState, headerChunk);
+
+ // Palettes cannot be included in grayscale images.
+ if (!headerChunk.getCanHavePalette()) SWT.error(SWT.ERROR_INVALID_IMAGE);
+
+ // Palette chunks' data fields must be event multiples
+ // of 3. Each 3-byte group represents an RGB value.
+ if (getLength() % 3 != 0) SWT.error(SWT.ERROR_INVALID_IMAGE);
+
+ // Palettes cannot have more entries than 2^bitDepth
+ // where bitDepth is the bit depth of the image given
+ // in the IHDR chunk.
+ if (Math.pow(2, headerChunk.getBitDepth()) < getPaletteSize()) {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ }
+
+ // Palettes cannot have more than 256 entries.
+ if (256 < getPaletteSize()) SWT.error(SWT.ERROR_INVALID_IMAGE);
+}
+
+void contributeToString(StringBuffer buffer) {
+ buffer.append("\n\tPalette size:");
+ buffer.append(getPaletteSize());
+}
+
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngTrnsChunk.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngTrnsChunk.java
new file mode 100755
index 0000000000..a1910bade6
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PngTrnsChunk.java
@@ -0,0 +1,133 @@
+package org.eclipse.swt.internal.image;
+
+import org.eclipse.swt.*;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2000 All Rights Reserved
+ */
+
+public class PngTrnsChunk extends PngChunk {
+ static final int TRANSPARENCY_TYPE_PIXEL = 0;
+ static final int TRANSPARENCY_TYPE_ALPHAS = 1;
+
+PngTrnsChunk(byte[] reference){
+ super(reference);
+}
+
+void validateLength(PngIhdrChunk header, PngPlteChunk paletteChunk) {
+ boolean valid;
+ switch (header.getColorType()) {
+ case PngIhdrChunk.COLOR_TYPE_RGB:
+ // Three 2-byte values (RGB)
+ valid = getLength() == 6;
+ break;
+ case PngIhdrChunk.COLOR_TYPE_PALETTE:
+ // Three 2-byte values (RGB)
+ valid = getLength() <= paletteChunk.getLength();
+ break;
+ case PngIhdrChunk.COLOR_TYPE_GRAYSCALE:
+ // One 2-byte value
+ valid = getLength() == 2;
+ break;
+ // Cannot use both Alpha and tRNS
+ case PngIhdrChunk.COLOR_TYPE_RGB_WITH_ALPHA:
+ case PngIhdrChunk.COLOR_TYPE_GRAYSCALE_WITH_ALPHA:
+ default:
+ valid = false;
+ }
+ if (!valid) {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ }
+}
+
+/**
+ * Answer whether the chunk is a valid tRNS chunk.
+ */
+void validate(PngFileReadState readState, PngIhdrChunk headerChunk, PngPlteChunk paletteChunk) {
+ if (!readState.readIHDR
+ || (headerChunk.getMustHavePalette() && !readState.readPLTE)
+ || readState.readIDAT
+ || readState.readIEND)
+ {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ } else {
+ readState.readTRNS = true;
+ }
+
+ validateLength(headerChunk, paletteChunk);
+
+ super.validate(readState, headerChunk);
+}
+
+
+int getTransparencyType(PngIhdrChunk header) {
+ if (header.getColorType() == PngIhdrChunk.COLOR_TYPE_PALETTE) {
+ return TRANSPARENCY_TYPE_ALPHAS;
+ }
+ return TRANSPARENCY_TYPE_PIXEL;
+}
+
+/**
+ * Answer the transparent pixel RGB value.
+ * This is not valid for palette color types.
+ * This is not valid for alpha color types.
+ * This will convert a grayscale value into
+ * a palette index.
+ * It will compress a 6 byte RGB into a 3 byte
+ * RGB.
+ */
+int getSwtTransparentPixel(PngIhdrChunk header) {
+ switch (header.getColorType()) {
+ case PngIhdrChunk.COLOR_TYPE_GRAYSCALE:
+ int gray = ((reference[DATA_OFFSET] & 0xFF) << 8)
+ + (reference[DATA_OFFSET + 1] & 0xFF);
+ if (header.getBitDepth() > 8) {
+ return PNGFileFormat.compress16BitDepthTo8BitDepth(gray);
+ }
+ return gray & 0xFF;
+ case PngIhdrChunk.COLOR_TYPE_RGB:
+ int red = ((reference[DATA_OFFSET] & 0xFF) << 8)
+ | (reference[DATA_OFFSET + 1] & 0xFF);
+ int green = ((reference[DATA_OFFSET + 2] & 0xFF) << 8)
+ | (reference[DATA_OFFSET + 3] & 0xFF);
+ int blue = ((reference[DATA_OFFSET + 4] & 0xFF) << 8)
+ | (reference[DATA_OFFSET + 5] & 0xFF);
+ if (header.getBitDepth() > 8) {
+ red = PNGFileFormat.compress16BitDepthTo8BitDepth(red);
+ green = PNGFileFormat.compress16BitDepthTo8BitDepth(green);
+ blue = PNGFileFormat.compress16BitDepthTo8BitDepth(blue);
+ }
+ return (red << 16) | (green << 8) | blue;
+ default:
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ return -1;
+ }
+}
+
+/**
+ * Answer an array of Alpha values that correspond to the
+ * colors in the palette.
+ * This is only valid for the COLOR_TYPE_PALETTE color type.
+ */
+byte[] getAlphaValues(PngIhdrChunk header, PngPlteChunk paletteChunk) {
+ if (header.getColorType() != PngIhdrChunk.COLOR_TYPE_PALETTE) {
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ }
+ byte[] alphas = new byte[paletteChunk.getPaletteSize()];
+ int dataLength = getLength();
+ int i = 0;
+ for (i = 0; i < dataLength; i++) {
+ alphas[i] = reference[DATA_OFFSET + i];
+ }
+ /**
+ * Any palette entries which do not have a corresponding
+ * alpha value in the tRNS chunk are spec'd to have an
+ * alpha of 255.
+ */
+ for (int j = i; j < alphas.length; j++) {
+ alphas[j] = (byte) 255;
+ }
+ return alphas;
+}
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/WinBMPFileFormat.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/WinBMPFileFormat.java
new file mode 100755
index 0000000000..fc94da00d2
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/WinBMPFileFormat.java
@@ -0,0 +1,667 @@
+package org.eclipse.swt.internal.image;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+/* Imports */
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import java.io.*;
+
+/* Class Definition */
+final class WinBMPFileFormat extends FileFormat {
+ int compression;
+ int importantColors;
+ Point pelsPerMeter = new Point(0, 0);
+ public static final int BMPHeaderFixedSize = 40;
+
+/**
+ * Compress numBytes bytes of image data from src, storing in dest
+ * (starting at 0), using the technique specified by comp.
+ * If last is true, this indicates the last line of the image.
+ * Answer the size of the compressed data.
+ */
+int compress(int comp, byte[] src, int srcOffset, int numBytes, byte[] dest, boolean last) {
+ if (comp == 1) { // BMP_RLE8_COMPRESSION
+ return compressRLE8Data(src, srcOffset, numBytes, dest, last);
+ }
+ if (comp == 2) { // BMP_RLE4_COMPRESSION
+ return compressRLE4Data(src, srcOffset, numBytes, dest, last);
+ }
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ return 0;
+}
+int compressRLE4Data(byte[] src, int srcOffset, int numBytes, byte[] dest, boolean last) {
+ int sp = srcOffset, end = srcOffset + numBytes, dp = 0;
+ int size = 0, left, i, n;
+ byte theByte;
+ while (sp < end) {
+ /* find two consecutive bytes that are the same in the next 128 */
+ left = end - sp - 1;
+ if (left > 127)
+ left = 127;
+ for (n = 0; n < left; n++) {
+ if (src[sp + n] == src[sp + n + 1])
+ break;
+ }
+ /* if there is only one more byte in the scan line, include it */
+ if (n < 127 && n == left)
+ n++;
+ /* store the intervening data */
+ switch (n) {
+ case 0:
+ break;
+ case 1: /* handled separately because 0,2 is a command */
+ dest[dp] = 2; dp++; /* 1 byte == 2 pixels */
+ dest[dp] = src[sp];
+ dp++; sp++;
+ size += 2;
+ break;
+ default:
+ dest[dp] = 0; dp++;
+ dest[dp] = (byte)(n + n); dp++; /* n bytes = n*2 pixels */
+ for (i = n; i > 0; i--) {
+ dest[dp] = src[sp];
+ dp++; sp++;
+ }
+ size += 2 + n;
+ if ((n & 1) != 0) { /* pad to word */
+ dest[dp] = 0;
+ dp++;
+ size++;
+ }
+ break;
+ }
+ /* find the length of the next run (up to 127) and store it */
+ left = end - sp;
+ if (left > 0) {
+ if (left > 127)
+ left = 127;
+ theByte = src[sp];
+ for (n = 1; n < left; n++) {
+ if (src[sp + n] != theByte)
+ break;
+ }
+ dest[dp] = (byte)(n + n); dp++; /* n bytes = n*2 pixels */
+ dest[dp] = theByte; dp++;
+ sp += n;
+ size += 2;
+ }
+ }
+
+ /* store the end of line or end of bitmap codes */
+ dest[dp] = 0; dp++;
+ if (last) {
+ dest[dp] = 1; dp++;
+ } else {
+ dest[dp] = 0; dp++;
+ }
+ size += 2;
+
+ return size;
+}
+int compressRLE8Data(byte[] src, int srcOffset, int numBytes, byte[] dest, boolean last) {
+ int sp = srcOffset, end = srcOffset + numBytes, dp = 0;
+ int size = 0, left, i, n;
+ byte theByte;
+ while (sp < end) {
+ /* find two consecutive bytes that are the same in the next 256 */
+ left = end - sp - 1;
+ if (left > 254)
+ left = 254;
+ for (n = 0; n < left; n++) {
+ if (src[sp + n] == src[sp + n + 1])
+ break;
+ }
+ /* if there is only one more byte in the scan line, include it */
+ if (n == left)
+ n++;
+ /* store the intervening data */
+ switch (n) {
+ case 0:
+ break;
+ case 2: /* handled separately because 0,2 is a command */
+ dest[dp] = 1; dp++;
+ dest[dp] = src[sp];
+ dp++; sp++;
+ size += 2;
+ /* don't break, fall through */
+ case 1: /* handled separately because 0,1 is a command */
+ dest[dp] = 1; dp++;
+ dest[dp] = src[sp];
+ dp++; sp++;
+ size += 2;
+ break;
+ default:
+ dest[dp] = 0; dp++;
+ dest[dp] = (byte)n; dp++;
+ for (i = n; i > 0; i--) {
+ dest[dp] = src[sp];
+ dp++; sp++;
+ }
+ size += 2 + n;
+ if ((n & 1) != 0) { /* pad to word */
+ dest[dp] = 0;
+ dp++;
+ size++;
+ }
+ break;
+ }
+ /* find the length of the next run (up to 255) and store it */
+ left = end - sp;
+ if (left > 0) {
+ if (left > 255)
+ left = 255;
+ theByte = src[sp];
+ for (n = 1; n < left; n++) {
+ if (src[sp + n] != theByte)
+ break;
+ }
+ dest[dp] = (byte)n; dp++;
+ dest[dp] = theByte; dp++;
+ sp += n;
+ size += 2;
+ }
+ }
+
+ /* store the end of line or end of bitmap codes */
+ dest[dp] = 0; dp++;
+ if (last) {
+ dest[dp] = 1; dp++;
+ } else {
+ dest[dp] = 0; dp++;
+ }
+ size += 2;
+
+ return size;
+}
+void decompressData(byte[] src, byte[] dest, int stride, int cmp) {
+ if (cmp == 1) { // BMP_RLE8_COMPRESSION
+ if (decompressRLE8Data(src, src.length, stride, dest, dest.length) <= 0)
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ return;
+ }
+ if (cmp == 2) { // BMP_RLE4_COMPRESSION
+ if (decompressRLE4Data(src, src.length, stride, dest, dest.length) <= 0)
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ return;
+ }
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+}
+int decompressRLE4Data(byte[] src, int numBytes, int stride, byte[] dest, int destSize) {
+ int sp = 0;
+ int se = numBytes;
+ int dp = 0;
+ int de = destSize;
+ int x = 0, y = 0;
+ while (sp < se) {
+ int len = src[sp] & 0xFF;
+ sp++;
+ if (len == 0) {
+ len = src[sp] & 0xFF;
+ sp++;
+ switch (len) {
+ case 0: /* end of line */
+ y++;
+ x = 0;
+ dp = y * stride;
+ if (dp >= de)
+ return -1;
+ break;
+ case 1: /* end of bitmap */
+ return 1;
+ case 2: /* delta */
+ x += src[sp] & 0xFF;
+ sp++;
+ y += src[sp] & 0xFF;
+ sp++;
+ dp = y * stride + x / 2;
+ if (dp >= de)
+ return -1;
+ break;
+ default: /* absolute mode run */
+ if ((len & 1) != 0) /* odd run lengths not currently supported */
+ return -1;
+ x += len;
+ len = len / 2;
+ if (len > (se - sp))
+ return -1;
+ if (len > (de - dp))
+ return -1;
+ for (int i = 0; i < len; i++) {
+ dest[dp] = src[sp];
+ dp++;
+ sp++;
+ }
+ if ((sp & 1) != 0)
+ sp++; /* word align sp? */
+ break;
+ }
+ } else {
+ if ((len & 1) != 0)
+ return -1;
+ x += len;
+ len = len / 2;
+ byte theByte = src[sp];
+ sp++;
+ if (len > (de - dp))
+ return -1;
+ for (int i = 0; i < len; i++) {
+ dest[dp] = theByte;
+ dp++;
+ }
+ }
+ }
+ return 1;
+}
+int decompressRLE8Data(byte[] src, int numBytes, int stride, byte[] dest, int destSize) {
+ int sp = 0;
+ int se = numBytes;
+ int dp = 0;
+ int de = destSize;
+ int x = 0, y = 0;
+ while (sp < se) {
+ int len = src[sp] & 0xFF;
+ sp++;
+ if (len == 0) {
+ len = src[sp] & 0xFF;
+ sp++;
+ switch (len) {
+ case 0: /* end of line */
+ y++;
+ x = 0;
+ dp = y * stride;
+ if (dp >= de)
+ return -1;
+ break;
+ case 1: /* end of bitmap */
+ return 1;
+ case 2: /* delta */
+ x += src[sp] & 0xFF;
+ sp++;
+ y += src[sp] & 0xFF;
+ sp++;
+ dp = y * stride + x;
+ if (dp >= de)
+ return -1;
+ break;
+ default: /* absolute mode run */
+ if (len > (se - sp))
+ return -1;
+ if (len > (de - dp))
+ return -1;
+ for (int i = 0; i < len; i++) {
+ dest[dp] = src[sp];
+ dp++;
+ sp++;
+ }
+ if ((sp & 1) != 0)
+ sp++; /* word align sp? */
+ x += len;
+ break;
+ }
+ } else {
+ byte theByte = src[sp];
+ sp++;
+ if (len > (de - dp))
+ return -1;
+ for (int i = 0; i < len; i++) {
+ dest[dp] = theByte;
+ dp++;
+ }
+ x += len;
+ }
+ }
+ return 1;
+}
+public static boolean isBMPFile(LEDataInputStream stream) {
+ try {
+ byte[] header = new byte[2];
+ stream.read(header);
+ stream.unread(header);
+ return header[0] == 0x42 && header[1] == 0x4D;
+ } catch (Exception e) {
+ return false;
+ }
+}
+byte[] loadData(byte[] infoHeader) {
+ int width = (infoHeader[4] & 0xFF) | ((infoHeader[5] & 0xFF) << 8) | ((infoHeader[6] & 0xFF) << 16) | ((infoHeader[7] & 0xFF) << 24);
+ int height = (infoHeader[8] & 0xFF) | ((infoHeader[9] & 0xFF) << 8) | ((infoHeader[10] & 0xFF) << 16) | ((infoHeader[11] & 0xFF) << 24);
+ int bitCount = (infoHeader[14] & 0xFF) | ((infoHeader[15] & 0xFF) << 8);
+ int stride = (width * bitCount + 7) / 8;
+ stride = (stride + 3) / 4 * 4; // Round up to 4 byte multiple
+ byte[] data = loadData(infoHeader, stride);
+ flipScanLines(data, stride, height);
+ return data;
+}
+byte[] loadData(byte[] infoHeader, int stride) {
+ int height = (infoHeader[8] & 0xFF) | ((infoHeader[9] & 0xFF) << 8) | ((infoHeader[10] & 0xFF) << 16) | ((infoHeader[11] & 0xFF) << 24);
+ int dataSize = height * stride;
+ byte[] data = new byte[dataSize];
+ int cmp = (infoHeader[16] & 0xFF) | ((infoHeader[17] & 0xFF) << 8) | ((infoHeader[18] & 0xFF) << 16) | ((infoHeader[19] & 0xFF) << 24);
+ if (cmp == 0) { // BMP_NO_COMPRESSION
+ try {
+ if (inputStream.read(data) != dataSize)
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ } else {
+ int compressedSize = (infoHeader[20] & 0xFF) | ((infoHeader[21] & 0xFF) << 8) | ((infoHeader[22] & 0xFF) << 16) | ((infoHeader[23] & 0xFF) << 24);
+ byte[] compressed = new byte[compressedSize];
+ try {
+ if (inputStream.read(compressed) != compressedSize)
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ decompressData(compressed, data, stride, cmp);
+ }
+ return data;
+}
+int[] loadFileHeader() {
+ int[] header = new int[5];
+ try {
+ header[0] = inputStream.readShort();
+ header[1] = inputStream.readInt();
+ header[2] = inputStream.readShort();
+ header[3] = inputStream.readShort();
+ header[4] = inputStream.readInt();
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ if (header[0] != 0x4D42)
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ return header;
+}
+ImageData[] loadFromByteStream() {
+ int[] fileHeader = loadFileHeader();
+ byte[] infoHeader = new byte[BMPHeaderFixedSize];
+ try {
+ inputStream.read(infoHeader);
+ } catch (Exception e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ PaletteData palette = loadPalette(infoHeader);
+ if (inputStream.getPosition() < fileHeader[4]) {
+ // Seek to the specified offset
+ try {
+ inputStream.skip(fileHeader[4] - inputStream.getPosition());
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ }
+ byte[] data = loadData(infoHeader);
+ this.compression = (infoHeader[16] & 0xFF) | ((infoHeader[17] & 0xFF) << 8) | ((infoHeader[18] & 0xFF) << 16) | ((infoHeader[19] & 0xFF) << 24);
+ this.importantColors = (infoHeader[36] & 0xFF) | ((infoHeader[37] & 0xFF) << 8) | ((infoHeader[38] & 0xFF) << 16) | ((infoHeader[39] & 0xFF) << 24);
+ int xPelsPerMeter = (infoHeader[24] & 0xFF) | ((infoHeader[25] & 0xFF) << 8) | ((infoHeader[26] & 0xFF) << 16) | ((infoHeader[27] & 0xFF) << 24);
+ int yPelsPerMeter = (infoHeader[28] & 0xFF) | ((infoHeader[29] & 0xFF) << 8) | ((infoHeader[30] & 0xFF) << 16) | ((infoHeader[31] & 0xFF) << 24);
+ this.pelsPerMeter = new Point(xPelsPerMeter, yPelsPerMeter);
+ int width = (infoHeader[4] & 0xFF) | ((infoHeader[5] & 0xFF) << 8) | ((infoHeader[6] & 0xFF) << 16) | ((infoHeader[7] & 0xFF) << 24);
+ int height = (infoHeader[8] & 0xFF) | ((infoHeader[9] & 0xFF) << 8) | ((infoHeader[10] & 0xFF) << 16) | ((infoHeader[11] & 0xFF) << 24);
+ int bitCount = (infoHeader[14] & 0xFF) | ((infoHeader[15] & 0xFF) << 8);
+ int type = (this.compression == 1 /*BMP_RLE8_COMPRESSION*/) || (this.compression == 2 /*BMP_RLE4_COMPRESSION*/) ? SWT.IMAGE_BMP_RLE : SWT.IMAGE_BMP;
+ return new ImageData[] {
+ ImageData.internal_new(
+ width,
+ height,
+ bitCount,
+ palette,
+ 4,
+ data,
+ 0,
+ null,
+ null,
+ -1,
+ -1,
+ type,
+ 0,
+ 0,
+ 0,
+ 0)
+ };
+}
+PaletteData loadPalette(byte[] infoHeader) {
+ int depth = (infoHeader[14] & 0xFF) | ((infoHeader[15] & 0xFF) << 8);
+ if (depth <= 8) {
+ int numColors = (infoHeader[32] & 0xFF) | ((infoHeader[33] & 0xFF) << 8) | ((infoHeader[34] & 0xFF) << 16) | ((infoHeader[35] & 0xFF) << 24);
+ if (numColors == 0) {
+ numColors = 1 << ((infoHeader[14] & 0xFF) | ((infoHeader[15] & 0xFF) << 8));
+ } else {
+ if (numColors > 256)
+ numColors = 256;
+ }
+ byte[] buf = new byte[numColors * 4];
+ try {
+ if (inputStream.read(buf) != buf.length)
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ return paletteFromBytes(buf, numColors);
+ }
+ if (depth == 16)
+ return new PaletteData(0x7C00, 0x3E0, 0x1F);
+ return new PaletteData(0xFF, 0xFF00, 0xFF0000);
+}
+PaletteData paletteFromBytes(byte[] bytes, int numColors) {
+ int bytesOffset = 0;
+ RGB[] colors = new RGB[numColors];
+ for (int i = 0; i < numColors; i++) {
+ colors[i] = new RGB(bytes[bytesOffset + 2] & 0xFF,
+ bytes[bytesOffset + 1] & 0xFF,
+ bytes[bytesOffset] & 0xFF);
+ bytesOffset += 4;
+ }
+ return new PaletteData(colors);
+}
+/**
+ * Answer a byte array containing the BMP representation of
+ * the given device independent palette.
+ */
+byte[] paletteToBytes(PaletteData pal) {
+ int n = (pal.colors.length < 256) ? pal.colors.length : 256;
+ byte[] bytes = new byte[n * 4];
+ int offset = 0;
+ for (int i = 0; i < n; i++) {
+ RGB col = pal.colors[i];
+ bytes[offset] = (byte)col.blue;
+ bytes[offset + 1] = (byte)col.green;
+ bytes[offset + 2] = (byte)col.red;
+ offset += 4;
+ }
+ return bytes;
+}
+/**
+ * Unload the given image's data into the given byte stream
+ * using the given compression strategy.
+ * Answer the number of bytes written.
+ */
+int unloadData(ImageData image, OutputStream out, int comp) {
+ int totalSize = 0;
+ try {
+ if (comp == 0)
+ return unloadDataNoCompression(image, out);
+ int bpl = (image.width * image.depth + 7) / 8;
+ int bmpBpl = (bpl + 3) / 4 * 4; // BMP pads scanlines to multiples of 4 bytes
+ int imageBpl = image.bytesPerLine;
+ // Compression can actually take twice as much space, in worst case
+ byte[] buf = new byte[bmpBpl * 2];
+ int srcOffset = imageBpl * (image.height - 1); // Start at last line
+ byte[] data = image.data;
+ totalSize = 0;
+ byte[] buf2 = new byte[32768];
+ int buf2Offset = 0;
+ for (int y = image.height - 1; y >= 0; y--) {
+ int lineSize = compress(comp, data, srcOffset, bpl, buf, y == 0);
+ if (buf2Offset + lineSize > buf2.length) {
+ out.write(buf2, 0, buf2Offset);
+ buf2Offset = 0;
+ }
+ System.arraycopy(buf, 0, buf2, buf2Offset, lineSize);
+ buf2Offset += lineSize;
+ totalSize += lineSize;
+ srcOffset -= imageBpl;
+ }
+ if (buf2Offset > 0)
+ out.write(buf2, 0, buf2Offset);
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ return totalSize;
+}
+/**
+ * Prepare the given image's data for unloading into a byte stream
+ * using no compression strategy.
+ * Answer the number of bytes written.
+ */
+int unloadDataNoCompression(ImageData image, OutputStream out) {
+ int bmpBpl = 0;
+ try {
+ int bpl = (image.width * image.depth + 7) / 8;
+ bmpBpl = (bpl + 3) / 4 * 4; // BMP pads scanlines to multiples of 4 bytes
+ int linesPerBuf = 32678 / bmpBpl;
+ byte[] buf = new byte[linesPerBuf * bmpBpl];
+ byte[] data = image.data;
+ int imageBpl = image.bytesPerLine;
+ int dataIndex = imageBpl * (image.height - 1); // Start at last line
+ if (image.depth == 16) {
+ for (int y = 0; y < image.height; y += linesPerBuf) {
+ int count = image.height - y;
+ if (linesPerBuf < count) count = linesPerBuf;
+ int bufOffset = 0;
+ for (int i = 0; i < count; i++) {
+ for (int wIndex = 0; wIndex < bpl; wIndex += 2) {
+ buf[bufOffset + wIndex + 1] = data[dataIndex + wIndex + 1];
+ buf[bufOffset + wIndex] = data[dataIndex + wIndex];
+ }
+ bufOffset += bmpBpl;
+ dataIndex -= imageBpl;
+ }
+ out.write(buf, 0, bufOffset);
+ }
+ } else {
+ for (int y = 0; y < image.height; y += linesPerBuf) {
+ int tmp = image.height - y;
+ int count = tmp < linesPerBuf ? tmp : linesPerBuf;
+ int bufOffset = 0;
+ for (int i = 0; i < count; i++) {
+ System.arraycopy(data, dataIndex, buf, bufOffset, bpl);
+ bufOffset += bmpBpl;
+ dataIndex -= imageBpl;
+ }
+ out.write(buf, 0, bufOffset);
+ }
+ }
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ return bmpBpl * image.height;
+}
+/**
+ * Unload a DeviceIndependentImage using Windows .BMP format into the given
+ * byte stream.
+ */
+void unloadIntoByteStream(ImageData image) {
+ byte[] rgbs;
+ int numCols;
+ if (!((image.depth == 1) || (image.depth == 4) || (image.depth == 8) ||
+ (image.depth == 16) || (image.depth == 24)))
+ SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+ int comp = this.compression;
+ if (!((comp == 0) || ((comp == 1) && (image.depth == 8)) ||
+ ((comp == 2) && (image.depth == 4))))
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ PaletteData pal = image.palette;
+ if ((image.depth == 16) || (image.depth == 24)) {
+ if (!pal.isDirect)
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ numCols = 0;
+ rgbs = null;
+ } else {
+ if (pal.isDirect)
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ numCols = pal.colors.length;
+ rgbs = paletteToBytes(pal);
+ }
+ // Fill in file header, except for bfsize, which is done later.
+ int headersSize = 54;
+ int[] fileHeader = new int[5];
+ fileHeader[0] = 0x4D42; // Signature
+ fileHeader[1] = 0; // File size - filled in later
+ fileHeader[2] = 0; // Reserved 1
+ fileHeader[3] = 0; // Reserved 2
+ fileHeader[4] = headersSize; // Offset to data
+ if (rgbs != null) {
+ fileHeader[4] += rgbs.length;
+ }
+
+ // Prepare data. This is done first so we don't have to try to rewind
+ // the stream and fill in the details later.
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ unloadData(image, out, comp);
+ byte[] compressedData = out.toByteArray();
+
+ // Calculate file size
+ fileHeader[1] = fileHeader[4] + compressedData.length;
+
+ // Write the headers
+ try {
+ outputStream.writeShort(fileHeader[0]);
+ outputStream.writeInt(fileHeader[1]);
+ outputStream.writeShort(fileHeader[2]);
+ outputStream.writeShort(fileHeader[3]);
+ outputStream.writeInt(fileHeader[4]);
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ try {
+ outputStream.writeInt(WinBMPFileFormat.BMPHeaderFixedSize);
+ outputStream.writeInt(image.width);
+ outputStream.writeInt(image.height);
+ outputStream.writeShort(1);
+ outputStream.writeShort((short)image.depth);
+ outputStream.writeInt(comp);
+ outputStream.writeInt(compressedData.length);
+ outputStream.writeInt(pelsPerMeter.x);
+ outputStream.writeInt(pelsPerMeter.y);
+ outputStream.writeInt(numCols);
+ outputStream.writeInt(importantColors);
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+
+ // Unload palette
+ if (numCols > 0) {
+ try {
+ outputStream.write(rgbs);
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ }
+
+ // Unload the data
+ try {
+ outputStream.write(compressedData);
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+}
+void flipScanLines(byte[] data, int stride, int height) {
+ int i1 = 0;
+ int i2 = (height - 1) * stride;
+ for (int i = 0; i < height / 2; i++) {
+ for (int index = 0; index < stride; index++) {
+ byte b = data[index + i1];
+ data[index + i1] = data[index + i2];
+ data[index + i2] = b;
+ }
+ i1 += stride;
+ i2 -= stride;
+ }
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/WinICOFileFormat.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/WinICOFileFormat.java
new file mode 100755
index 0000000000..4ff4b0d3f9
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/WinICOFileFormat.java
@@ -0,0 +1,284 @@
+package org.eclipse.swt.internal.image;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+/* Imports */
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import java.io.*;
+
+/* Class Definition */
+final class WinICOFileFormat extends FileFormat {
+/**
+ * Answer the size in bytes of the file representation of the given
+ * icon
+ */
+int iconSize(ImageData i) {
+ int shapeDataStride = (i.width * i.depth + 31) / 32 * 4;
+ int maskDataStride = (i.width + 31) / 32 * 4;
+ int dataSize = (shapeDataStride + maskDataStride) * i.height;
+ return WinBMPFileFormat.BMPHeaderFixedSize + (i.palette.colors.length * 4) + dataSize;
+}
+public static boolean isICOFile(LEDataInputStream stream) {
+ try {
+ byte[] header = new byte[4];
+ stream.read(header);
+ stream.unread(header);
+ return header[0] == 0 && header[1] == 0 && header[2] == 1 && header[3] == 0;
+ } catch (Exception e) {
+ return false;
+ }
+}
+boolean isValidIcon(ImageData i) {
+ if (!((i.depth == 1) || (i.depth == 4) || (i.depth == 8)))
+ return false;
+ int size = i.palette.colors.length;
+ return ((size == 2) || (size == 16) || (size == 32) || (size == 256));
+}
+int loadFileHeader(LEDataInputStream byteStream) {
+ int[] fileHeader = new int[3];
+ try {
+ fileHeader[0] = byteStream.readShort();
+ fileHeader[1] = byteStream.readShort();
+ fileHeader[2] = byteStream.readShort();
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ if ((fileHeader[0] != 0) || (fileHeader[1] != 1))
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ int numIcons = fileHeader[2];
+ if (numIcons <= 0)
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ return numIcons;
+}
+int loadFileHeader(LEDataInputStream byteStream, boolean hasHeader) {
+ int[] fileHeader = new int[3];
+ try {
+ if (hasHeader) {
+ fileHeader[0] = byteStream.readShort();
+ fileHeader[1] = byteStream.readShort();
+ } else {
+ fileHeader[0] = 0;
+ fileHeader[1] = 1;
+ }
+ fileHeader[2] = byteStream.readShort();
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ if ((fileHeader[0] != 0) || (fileHeader[1] != 1))
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ int numIcons = fileHeader[2];
+ if (numIcons <= 0)
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ return numIcons;
+}
+ImageData[] loadFromByteStream() {
+ int numIcons = loadFileHeader(inputStream);
+ int[][] headers = loadIconHeaders(numIcons);
+ ImageData[] icons = new ImageData[headers.length];
+ for (int i = 0; i < icons.length; i++) {
+ icons[i] = loadIcon(headers[i]);
+ }
+ return icons;
+}
+/**
+ * Load one icon from the byte stream.
+ */
+ImageData loadIcon(int[] iconHeader) {
+ byte[] infoHeader = loadInfoHeader(iconHeader);
+ WinBMPFileFormat bmpFormat = new WinBMPFileFormat();
+ bmpFormat.inputStream = inputStream;
+ PaletteData palette = bmpFormat.loadPalette(infoHeader);
+ byte[] shapeData = bmpFormat.loadData(infoHeader);
+ int depth = (infoHeader[14] & 0xFF) | ((infoHeader[15] & 0xFF) << 8);
+ infoHeader[14] = 1;
+ infoHeader[15] = 0;
+ byte[] maskData = bmpFormat.loadData(infoHeader);
+ bitInvertData(maskData, 0, maskData.length);
+ int infoWidth = (infoHeader[4] & 0xFF) | ((infoHeader[5] & 0xFF) << 8) | ((infoHeader[6] & 0xFF) << 16) | ((infoHeader[7] & 0xFF) << 24);
+ int infoHeight = (infoHeader[8] & 0xFF) | ((infoHeader[9] & 0xFF) << 8) | ((infoHeader[10] & 0xFF) << 16) | ((infoHeader[11] & 0xFF) << 24);
+ return ImageData.internal_new(
+ infoWidth,
+ infoHeight,
+ depth,
+ palette,
+ 4,
+ shapeData,
+// 4,
+ 2,
+ maskData,
+ null,
+ -1,
+ -1,
+ SWT.IMAGE_ICO,
+ 0,
+ 0,
+ 0,
+ 0);
+}
+int[][] loadIconHeaders(int numIcons) {
+ int[][] headers = new int[numIcons][7];
+ try {
+ for (int i = 0; i < numIcons; i++) {
+ headers[i][0] = inputStream.read();
+ headers[i][1] = inputStream.read();
+ headers[i][2] = inputStream.readShort();
+ headers[i][3] = inputStream.readShort();
+ headers[i][4] = inputStream.readShort();
+ headers[i][5] = inputStream.readInt();
+ headers[i][6] = inputStream.readInt();
+ }
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ return headers;
+}
+byte[] loadInfoHeader(int[] iconHeader) {
+ int width = iconHeader[0];
+ int height = iconHeader[1];
+ int numColors = iconHeader[2];
+ if ((numColors != 2) && (numColors != 8) && (numColors != 16) &&
+ (numColors != 32) && (numColors != 256))
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ if (inputStream.getPosition() < iconHeader[6]) {
+ // Seek to the specified offset
+ try {
+ inputStream.skip(iconHeader[6] - inputStream.getPosition());
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ return null;
+ }
+ }
+ byte[] infoHeader = new byte[WinBMPFileFormat.BMPHeaderFixedSize];
+ try {
+ inputStream.read(infoHeader);
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ if (((infoHeader[12] & 0xFF) | ((infoHeader[13] & 0xFF) << 8)) != 1)
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ int infoWidth = (infoHeader[4] & 0xFF) | ((infoHeader[5] & 0xFF) << 8) | ((infoHeader[6] & 0xFF) << 16) | ((infoHeader[7] & 0xFF) << 24);
+ int infoHeight = (infoHeader[8] & 0xFF) | ((infoHeader[9] & 0xFF) << 8) | ((infoHeader[10] & 0xFF) << 16) | ((infoHeader[11] & 0xFF) << 24);
+ int bitCount = (infoHeader[14] & 0xFF) | ((infoHeader[15] & 0xFF) << 8);
+ if (height == infoHeight && bitCount == 1) height /= 2;
+ if (!((width == infoWidth) && (height * 2 == infoHeight) &&
+ ((bitCount == 1) || (bitCount == 4) || (bitCount == 8))))
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ infoHeader[8] = (byte)(height & 0xFF);
+ infoHeader[9] = (byte)((height >> 8) & 0xFF);
+ infoHeader[10] = (byte)((height >> 16) & 0xFF);
+ infoHeader[11] = (byte)((height >> 24) & 0xFF);
+ return infoHeader;
+}
+/**
+ * Unload a single icon
+ */
+void unloadIcon(ImageData icon) {
+ int sizeImage = (((icon.width * icon.depth + 31) / 32 * 4) +
+ ((icon.width + 31) / 32 * 4)) * icon.height;
+ try {
+ outputStream.writeInt(WinBMPFileFormat.BMPHeaderFixedSize);
+ outputStream.writeInt(icon.width);
+ outputStream.writeInt(icon.height * 2);
+ outputStream.writeShort(1);
+ outputStream.writeShort((short)icon.depth);
+ outputStream.writeInt(0);
+ outputStream.writeInt(sizeImage);
+ outputStream.writeInt(0);
+ outputStream.writeInt(0);
+ outputStream.writeInt(icon.palette.colors.length);
+ outputStream.writeInt(0);
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+
+ byte[] rgbs = new WinBMPFileFormat().paletteToBytes(icon.palette);
+ try {
+ outputStream.write(rgbs);
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ unloadShapeData(icon);
+ unloadMaskData(icon);
+}
+/**
+ * Unload the icon header for the given icon, calculating the offset.
+ */
+void unloadIconHeader(ImageData i) {
+ int headerSize = 16;
+ int offset = headerSize + 6;
+ int iconSize = iconSize(i);
+ try {
+ outputStream.writeByte((byte)i.width);
+ outputStream.writeByte((byte)i.height);
+ outputStream.writeShort(i.palette.colors.length);
+ outputStream.writeShort(0);
+ outputStream.writeShort(0);
+ outputStream.writeInt(iconSize);
+ outputStream.writeInt(offset);
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+}
+void unloadIntoByteStream(ImageData image) {
+ if (!isValidIcon(image))
+ SWT.error(SWT.ERROR_INVALID_IMAGE);
+ try {
+ outputStream.writeShort(0);
+ outputStream.writeShort(1);
+ outputStream.writeShort(1);
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+ unloadIconHeader(image);
+ unloadIcon(image);
+}
+/**
+ * Unload the mask data for an icon. The data is flipped vertically
+ * and inverted.
+ */
+void unloadMaskData(ImageData icon) {
+ int bpl = (icon.width + 7) / 8;
+ int pad = 4;
+ int srcBpl = (bpl + pad - 1) / pad * pad;
+ int destBpl = (bpl + 3) / 4 * 4;
+ byte[] buf = new byte[destBpl];
+ int offset = (icon.height - 1) * srcBpl;
+ byte[] data = icon.getTransparencyMask().data;
+ try {
+ for (int i = 0; i < icon.height; i++) {
+ System.arraycopy(data, offset, buf, 0, bpl);
+ bitInvertData(buf, 0, bpl);
+ outputStream.write(buf, 0, destBpl);
+ offset -= srcBpl;
+ }
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+}
+/**
+ * Unload the shape data for an icon. The data is flipped vertically.
+ */
+void unloadShapeData(ImageData icon) {
+ int bpl = (icon.width * icon.depth + 7) / 8;
+ int pad = 4;
+ int srcBpl = (bpl + pad - 1) / pad * pad;
+ int destBpl = (bpl + 3) / 4 * 4;
+ byte[] buf = new byte[destBpl];
+ int offset = (icon.height - 1) * srcBpl;
+ byte[] data = icon.data;
+ try {
+ for (int i = 0; i < icon.height; i++) {
+ System.arraycopy(data, offset, buf, 0, bpl);
+ outputStream.write(buf, 0, destBpl);
+ offset -= srcBpl;
+ }
+ } catch (IOException e) {
+ SWT.error(SWT.ERROR_IO, e);
+ }
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/package.html b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/package.html
new file mode 100755
index 0000000000..62fccda519
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/package.html
@@ -0,0 +1,18 @@
+ <html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="Author" content="IBM">
+ <title>Package-level Javadoc</title>
+</head>
+<body>
+SWT internal image loading/saving support classes.
+<h2>
+Package Specification</h2>
+This package contains the classes used by SWT to load and save images
+in the various formats we support, including GIF, JPEG, PNG, BMP, and ICO.
+<p>
+Applications should not need to reference the classes in this package
+directly.
+</p>
+</body>
+</html>
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/package.html b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/package.html
new file mode 100755
index 0000000000..da0cec585e
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/package.html
@@ -0,0 +1,20 @@
+ <html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="Author" content="IBM">
+ <title>Package-level Javadoc</title>
+</head>
+<body>
+SWT internal classes
+<h2>
+Package Specification</h2>
+This package provides the <code>Callback</code> class which is used to
+map the operating system's callback mechanism to Java message sends, and
+the <code>Converter</code> class which provides translation between Unicode
+and platform specific character sets.
+<p>
+Applications should not need to reference the classes in this package
+directly.
+</p>
+</body>
+</html>
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/FillLayout.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/FillLayout.java
new file mode 100755
index 0000000000..64d1bf4dc0
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/FillLayout.java
@@ -0,0 +1,67 @@
+package org.eclipse.swt.layout;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+public final class FillLayout extends Layout {
+ /**
+ * type specifies how controls will be positioned
+ * within the layout.
+ *
+ * The default value is HORIZONTAL.
+ *
+ * Possible values are:
+ *
+ * HORIZONTAL: Position the controls horizontally from left to right
+ * VERTICAL: Position the controls vertically from top to bottom
+ */
+ public int type = SWT.HORIZONTAL;
+public FillLayout () {
+}
+protected Point computeSize (Composite composite, int wHint, int hHint, boolean flushCache) {
+ Control [] children = composite.getChildren ();
+ int count = children.length;
+ int maxWidth = 0, maxHeight = 0;
+ for (int i=0; i<count; i++) {
+ Control child = children [i];
+ Point pt = child.computeSize (SWT.DEFAULT, SWT.DEFAULT, flushCache);
+ maxWidth = Math.max (maxWidth, pt.x);
+ maxHeight = Math.max (maxHeight, pt.y);
+ }
+ if (type == SWT.HORIZONTAL) {
+ return new Point (count * maxWidth, maxHeight);
+ }
+ return new Point (maxWidth, count * maxHeight);
+}
+protected void layout (Composite composite, boolean flushCache) {
+ Rectangle rect = composite.getClientArea ();
+ Control [] children = composite.getChildren ();
+ int count = children.length;
+ if (count == 0) return;
+ if (type == SWT.HORIZONTAL) {
+ int x = rect.x + ((rect.width % count) / 2);
+ int width = rect.width / count;
+ int y = rect.y, height = rect.height;
+ for (int i=0; i<count; i++) {
+ Control child = children [i];
+ child.setBounds (x, y, width, height);
+ x += width;
+ }
+ return;
+ }
+ int x = rect.x, width = rect.width;
+ int y = rect.y + ((rect.height % count) / 2);
+ int height = rect.height / count;
+ for (int i=0; i<count; i++) {
+ Control child = children [i];
+ child.setBounds (x, y, width, height);
+ y += height;
+ }
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/GridData.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/GridData.java
new file mode 100755
index 0000000000..b58e62fb39
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/GridData.java
@@ -0,0 +1,157 @@
+package org.eclipse.swt.layout;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+public final class GridData {
+ /**
+ * verticalAlignment specifies how controls will be positioned
+ * vertically within a cell.
+ *
+ * The default value is CENTER.
+ *
+ * Possible values are:
+ *
+ * BEGINNING: Position the control at the top of the cell
+ * CENTER: Position the control in the vertical center of the cell
+ * END: Position the control at the bottom of the cell
+ * FILL: Resize the control to fill the cell vertically
+ */
+ public int verticalAlignment = CENTER;
+ /**
+ * horizontalAlignment specifies how controls will be positioned
+ * horizontally within a cell.
+ *
+ * The default value is BEGINNING.
+ *
+ * Possible values are:
+ *
+ * BEGINNING: Position the control at the left of the cell
+ * CENTER: Position the control in the horizontal center of the cell
+ * END: Position the control at the right of the cell
+ * FILL: Resize the control to fill the cell horizontally
+ */
+ public int horizontalAlignment = BEGINNING;
+ /**
+ * widthHint specifies a minimum width for the column. A value of
+ * SWT.DEFAULT indicates that no minimum width is specified.
+ *
+ * The default value is SWT.DEFAULT.
+ */
+ public int widthHint = SWT.DEFAULT;
+ /**
+ * heightHint specifies a minimum height for the row. A value of
+ * SWT.DEFAULT indicates that no minimum height is specified.
+ *
+ * The default value is SWT.DEFAULT.
+ */
+ public int heightHint = SWT.DEFAULT;
+ /**
+ * horizontalIndent specifies the number of pixels of indentation
+ * that will be placed along the left side of the cell.
+ *
+ * The default value is 0.
+ */
+ public int horizontalIndent = 0;
+ /**
+ * horizontalSpan specifies the number of column cells that the control
+ * will take up.
+ *
+ * The default value is 1.
+ */
+ public int horizontalSpan = 1;
+ /**
+ * verticalSpan specifies the number of row cells that the control
+ * will take up.
+ *
+ * The default value is 1.
+ */
+ public int verticalSpan = 1;
+ /**
+ * grabExcessHorizontalSpace specifies whether the cell will be made
+ * wide enough to fit the remaining horizontal space.
+ *
+ * The default value is false.
+ */
+ public boolean grabExcessHorizontalSpace = false;
+ /**
+ * grabExcessVerticalSpace specifies whether the cell will be made
+ * tall enough to fit the remaining vertical space.
+ *
+ * The default value is false.
+ */
+ public boolean grabExcessVerticalSpace = false;
+
+ // Alignment constants.
+ public static final int BEGINNING = 1;
+ public static final int CENTER = 2;
+ public static final int END = 3;
+ public static final int FILL = 4;
+
+ // Style constants
+ public static final int VERTICAL_ALIGN_BEGINNING = 1 << 1;
+ public static final int VERTICAL_ALIGN_CENTER = 1 << 2;
+ public static final int VERTICAL_ALIGN_END = 1 << 3;
+ public static final int VERTICAL_ALIGN_FILL = 1 << 4;
+ public static final int HORIZONTAL_ALIGN_BEGINNING = 1 << 5;
+ public static final int HORIZONTAL_ALIGN_CENTER = 1 << 6;
+ public static final int HORIZONTAL_ALIGN_END = 1 << 7;
+ public static final int HORIZONTAL_ALIGN_FILL = 1 << 8;
+ public static final int GRAB_HORIZONTAL = 1 << 9;
+ public static final int GRAB_VERTICAL = 1 << 10;
+
+ // Style convenience constants
+ public static final int FILL_VERTICAL = VERTICAL_ALIGN_FILL | GRAB_VERTICAL;
+ public static final int FILL_HORIZONTAL = HORIZONTAL_ALIGN_FILL | GRAB_HORIZONTAL;
+ public static final int FILL_BOTH = FILL_VERTICAL | FILL_HORIZONTAL;
+
+ // Private
+ int childIndex;
+ boolean isItemData = true;
+public GridData() {
+ super();
+}
+public GridData(int style) {
+ super();
+
+ if ((style & VERTICAL_ALIGN_BEGINNING) != 0)
+ verticalAlignment = BEGINNING;
+ if ((style & VERTICAL_ALIGN_CENTER) != 0)
+ verticalAlignment = CENTER;
+ if ((style & VERTICAL_ALIGN_FILL) != 0)
+ verticalAlignment = FILL;
+ if ((style & VERTICAL_ALIGN_END) != 0)
+ verticalAlignment = END;
+
+ if ((style & HORIZONTAL_ALIGN_BEGINNING) != 0)
+ horizontalAlignment = BEGINNING;
+ if ((style & HORIZONTAL_ALIGN_CENTER) != 0)
+ horizontalAlignment = CENTER;
+ if ((style & HORIZONTAL_ALIGN_FILL) != 0)
+ horizontalAlignment = FILL;
+ if ((style & HORIZONTAL_ALIGN_END) != 0)
+ horizontalAlignment = END;
+
+ if ((style & GRAB_HORIZONTAL) != 0)
+ grabExcessHorizontalSpace = true;
+ else
+ grabExcessHorizontalSpace = false;
+ if ((style & GRAB_VERTICAL) != 0)
+ grabExcessVerticalSpace = true;
+ else
+ grabExcessVerticalSpace = false;
+
+}
+boolean isItemData() {
+ return isItemData;
+}
+boolean isSpacerData() {
+ return !isItemData;
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/GridLayout.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/GridLayout.java
new file mode 100755
index 0000000000..76d3220c92
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/GridLayout.java
@@ -0,0 +1,638 @@
+package org.eclipse.swt.layout;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+import org.eclipse.swt.*;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.swt.graphics.*;
+import java.util.*;
+
+public final class GridLayout extends Layout {
+ /**
+ * marginWidth specifies the number of pixels of horizontal margin
+ * that will be placed along the left and right edges of the layout.
+ *
+ * The default value is 5.
+ */
+ public int marginWidth = 5;
+ /**
+ * marginHeight specifies the number of pixels of vertical margin
+ * that will be placed along the top and bottom edges of the layout.
+ *
+ * The default value is 5.
+ */
+ public int marginHeight = 5;
+ /**
+ * numColumns specifies the number of cell columns in the layout.
+ *
+ * The default value is 1.
+ */
+ public int numColumns = 1;
+ /**
+ * makeColumnsEqualWidth specifies whether all columns in the layout
+ * will be forced to have the same width.
+ *
+ * The default value is false.
+ */
+ public boolean makeColumnsEqualWidth = false;
+ /**
+ * horizontalSpacing specifies the number of pixels between the right
+ * edge of one cell and the left edge of its neighbouring cell to
+ * the right.
+ *
+ * The default value is 5.
+ */
+ public int horizontalSpacing = 5;
+ /**
+ * verticalSpacing specifies the number of pixels between the bottom
+ * edge of one cell and the top edge of its neighbouring cell underneath.
+ *
+ * The default value is 5.
+ */
+ public int verticalSpacing = 5;
+
+ // Private variables. Cached values used to cut down on grid calculations.
+ boolean initialLayout = true;
+ Vector grid = new Vector();
+ int [] pixelColumnWidths;
+ int [] pixelRowHeights;
+ int [] expandableColumns;
+ int [] expandableRows;
+public GridLayout() {
+ super();
+}
+void adjustGridDimensions(Composite composite, boolean flushCache) {
+ // Ensure that widgets that span more than one row or column have enough space.
+ for (int row = 0; row < grid.size(); row++) {
+ for (int column = 0; column < numColumns; column++) {
+ GridData spec = ((GridData[]) grid.elementAt(row))[column];
+ if (spec.isItemData()) {
+ // Widgets spanning columns.
+ if (spec.horizontalSpan > 1) {
+ Control child = composite.getChildren()[spec.childIndex];
+ Point extent = child.computeSize(spec.widthHint, spec.heightHint, flushCache);
+
+ // Calculate the size of the widget's spanned columns.
+ int lastSpanIndex = column + spec.horizontalSpan;
+ int spannedSize = 0;
+ for (int c = column; c < lastSpanIndex; c++) {
+ spannedSize = spannedSize + pixelColumnWidths[c] + horizontalSpacing;
+ }
+ spannedSize = spannedSize - horizontalSpacing;
+
+ // If the spanned columns are not large enough to display the widget, adjust the column
+ // sizes to account for the extra space that is needed.
+ if (extent.x + spec.horizontalIndent > spannedSize) {
+ int extraSpaceNeeded = extent.x + spec.horizontalIndent - spannedSize;
+ int lastColumn = column + spec.horizontalSpan - 1;
+ int colWidth;
+ if (makeColumnsEqualWidth) {
+ // Evenly distribute the extra space amongst all of the columns.
+ int columnExtra = extraSpaceNeeded / numColumns;
+ int columnRemainder = extraSpaceNeeded % numColumns;
+ for (int i = 0; i < pixelColumnWidths.length; i++) {
+ colWidth = pixelColumnWidths[i] + columnExtra;
+ pixelColumnWidths[i] = colWidth;
+ }
+ colWidth = pixelColumnWidths[lastColumn] + columnRemainder;
+ pixelColumnWidths[lastColumn] = colWidth;
+ } else {
+ Vector localExpandableColumns = new Vector();
+ for (int i = column; i < lastColumn; i++) {
+ for (int j = 0; j < expandableColumns.length; j++) {
+ if (expandableColumns[j] == i) {
+ localExpandableColumns.addElement(new Integer(i));
+ }
+ }
+ }
+ if (localExpandableColumns.size() > 0) {
+ // If any of the widget's columns grab excess space, allocate the space amongst those columns.
+ int columnExtra = extraSpaceNeeded / localExpandableColumns.size();
+ int columnRemainder = extraSpaceNeeded % localExpandableColumns.size();
+ for (int i = 0; i < localExpandableColumns.size(); i++) {
+ int expandableCol = ((Integer) localExpandableColumns.elementAt(i)).intValue();
+ colWidth = pixelColumnWidths[expandableCol] + columnExtra;
+ pixelColumnWidths[expandableCol] = colWidth;
+ }
+ colWidth = pixelColumnWidths[lastColumn] + columnRemainder;
+ pixelColumnWidths[lastColumn] = colWidth;
+ } else {
+ // Add the extra space to the widget's last column if none of its columns grab excess space.
+ colWidth = pixelColumnWidths[lastColumn] + extraSpaceNeeded;
+ pixelColumnWidths[lastColumn] = colWidth;
+ }
+ }
+ }
+ }
+
+ // Widgets spanning rows.
+ if (spec.verticalSpan > 1) {
+ Control child = composite.getChildren()[spec.childIndex];
+ Point extent = child.computeSize(spec.widthHint, spec.heightHint, flushCache);
+
+ // Calculate the size of the widget's spanned rows.
+ int lastSpanIndex = row + spec.verticalSpan;
+ int spannedSize = 0;
+ for (int r = row; r < lastSpanIndex; r++) {
+ spannedSize = spannedSize + pixelRowHeights[r] + verticalSpacing;
+ }
+ spannedSize = spannedSize - verticalSpacing;
+ // If the spanned rows are not large enough to display the widget, adjust the row
+ // sizes to account for the extra space that is needed.
+ if (extent.y > spannedSize) {
+ int extraSpaceNeeded = extent.y - spannedSize;
+ int lastRow = row + spec.verticalSpan - 1;
+ int rowHeight;
+ Vector localExpandableRows = new Vector();
+ for (int i = row; i < lastRow; i++) {
+ for (int j = 0; j < expandableRows.length; j++) {
+ if (expandableRows[j] == i) {
+ localExpandableRows.addElement(new Integer(i));
+ }
+ }
+ }
+ if (localExpandableRows.size() > 0) {
+ // If any of the widget's rows grab excess space, allocate the space amongst those rows.
+ int rowExtra = extraSpaceNeeded / localExpandableRows.size();
+ int rowRemainder = extraSpaceNeeded % localExpandableRows.size();
+ for (int i = 0; i < localExpandableRows.size(); i++) {
+ int expandableRow = ((Integer) localExpandableRows.elementAt(i)).intValue();
+ rowHeight = pixelRowHeights[expandableRow] + rowExtra;
+ pixelRowHeights[expandableRow] = rowHeight;
+ }
+ rowHeight = pixelRowHeights[lastRow] + rowRemainder;
+ pixelRowHeights[lastRow] = rowHeight;
+ } else {
+ // Add the extra space to the widget's last row if no rows grab excess space.
+ rowHeight = pixelRowHeights[lastRow] + extraSpaceNeeded;
+ pixelRowHeights[lastRow] = rowHeight;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+void calculateGridDimensions(Composite composite, boolean flushCache) {
+ int maxWidth, childWidth, maxHeight, childHeight;
+
+ //
+ Control[] children = composite.getChildren();
+ Point[] childSizes = new Point[children.length];
+ pixelColumnWidths = new int[numColumns];
+ pixelRowHeights = new int[grid.size()];
+
+ // Loop through the grid by column to get the width that each column needs to be.
+ // Each column will be as wide as its widest widget.
+ for (int column = 0; column < numColumns; column++) {
+ maxWidth = 0;
+ for (int row = 0; row < grid.size(); row++) {
+ GridData spec = ((GridData[]) grid.elementAt(row))[column];
+ if (spec.isItemData()) {
+ Control child = children[spec.childIndex];
+ childSizes[spec.childIndex] = child.computeSize(spec.widthHint, spec.heightHint, flushCache);
+ childWidth = childSizes[spec.childIndex].x + spec.horizontalIndent;
+ if (spec.horizontalSpan == 1) {
+ maxWidth = Math.max(maxWidth, childWidth);
+ }
+ }
+ }
+ // Cache the values for later use.
+ pixelColumnWidths[column] = maxWidth;
+ }
+
+ //
+ if (makeColumnsEqualWidth) {
+ maxWidth = 0;
+ // Find the largest column size that is necessary and make each column that size.
+ for (int i = 0; i < numColumns; i++) {
+ maxWidth = Math.max(maxWidth, pixelColumnWidths[i]);
+ }
+ for (int i = 0; i < numColumns; i++) {
+ pixelColumnWidths[i] = maxWidth;
+ }
+ }
+
+ // Loop through the grid by row to get the height that each row needs to be.
+ // Each row will be as high as its tallest widget.
+ for (int row = 0; row < grid.size(); row++) {
+ maxHeight = 0;
+ for (int column = 0; column < numColumns; column++) {
+ GridData spec = ((GridData[]) grid.elementAt(row))[column];
+ if (spec.isItemData()) {
+ Control child = children[spec.childIndex];
+ childHeight = childSizes[spec.childIndex].y;
+ if (spec.verticalSpan == 1) {
+ maxHeight = Math.max(maxHeight, childHeight);
+ }
+ }
+ }
+ // Cache the values for later use.
+ pixelRowHeights[row] = maxHeight;
+ }
+}
+void computeExpandableCells() {
+ // If a widget grabs excess horizontal space, the last column that the widget spans
+ // will be expandable. Similarly, if a widget grabs excess vertical space, the
+ // last row that the widget spans will be expandable.
+ Hashtable growColumns = new Hashtable();
+ Hashtable growRows = new Hashtable();
+ for (int col = 0; col < numColumns; col++) {
+ for (int row = 0; row < grid.size(); row++) {
+ GridData spec = ((GridData[]) grid.elementAt(row))[col];
+ if (spec.grabExcessHorizontalSpace) {
+ growColumns.put(new Integer(col + spec.horizontalSpan - 1), new Object());
+ }
+ if (spec.grabExcessVerticalSpace) {
+ growRows.put(new Integer(row + spec.verticalSpan - 1), new Object());
+ }
+ }
+ }
+
+ // Cache the values. These values are used later during children layout.
+ int i = 0;
+ Enumeration enum = growColumns.keys();
+ expandableColumns = new int[growColumns.size()];
+ while (enum.hasMoreElements()) {
+ expandableColumns[i] = ((Integer)enum.nextElement()).intValue();
+ i = i + 1;
+ }
+ i = 0;
+ enum = growRows.keys();
+ expandableRows = new int[growRows.size()];
+ while (enum.hasMoreElements()) {
+ expandableRows[i] = ((Integer)enum.nextElement()).intValue();
+ i = i + 1;
+ }
+}
+Point computeLayoutSize(Composite composite, int wHint, int hHint, boolean flushCache) {
+ int totalMarginHeight, totalMarginWidth;
+ int totalWidth, totalHeight;
+ int cols, rows;
+
+ // Initialize the grid and other cached information that help with the grid layout.
+ if (grid.size() == 0) {
+ createGrid(composite);
+ calculateGridDimensions(composite, flushCache);
+ computeExpandableCells();
+ adjustGridDimensions(composite, flushCache);
+ }
+
+ //
+ cols = numColumns;
+ rows = grid.size();
+ totalMarginHeight = marginHeight;
+ totalMarginWidth = marginWidth;
+
+ // The total width is the margin plus border width plus space between each column,
+ // plus the width of each column.
+ totalWidth = (totalMarginWidth * 2) + ((cols - 1) * horizontalSpacing);
+
+ //Add up the width of each column.
+ for (int i = 0; i < pixelColumnWidths.length; i++) {
+ totalWidth = totalWidth + pixelColumnWidths[i];
+ }
+
+ // The total height is the margin plus border height, plus space between each row,
+ // plus the height of the tallest child in each row.
+ totalHeight = (totalMarginHeight * 2) + ((rows - 1) * verticalSpacing);
+
+ //Add up the height of each row.
+ for (int i = 0; i < pixelRowHeights.length; i++) {
+ totalHeight = totalHeight + pixelRowHeights[i];
+ }
+
+ if (wHint != SWT.DEFAULT) {
+ totalWidth = wHint;};
+ if (hHint != SWT.DEFAULT) {
+ totalHeight = hHint;};
+ // The preferred extent is the width and height that will accomodate the grid's widgets.
+ return new Point(totalWidth, totalHeight);
+}
+protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
+ Control[] children = composite.getChildren();
+ int numChildren = children.length;
+
+ if (numChildren == 0) return new Point(0,0);
+
+ // Make sure that all of the composite children have a layout spec. Do this by
+ // using the initialLayout flag.
+ if (flushCache)
+ initialLayout = true;
+ if (initialLayout) {
+ initializeLayoutData(composite);
+ initialLayout = false;
+ }
+
+ if (flushCache) {
+ // Cause the grid and its related information to be calculated
+ // again.
+ grid.removeAllElements();
+ }
+ return computeLayoutSize(composite, wHint, hHint, flushCache);
+}
+void createGrid(Composite composite) {
+ int row, column, rowFill, columnFill;
+ Vector rows;
+ Control[] children;
+ GridData spacerSpec;
+
+ //
+ children = composite.getChildren();
+
+ //
+ grid.addElement(emptyRow());
+ row = 0;
+ column = 0;
+
+ // Loop through the children and place their associated layout specs in the
+ // grid. Placement occurs left to right, top to bottom (i.e., by row).
+ for (int i = 0; i < children.length; i++) {
+ // Find the first available spot in the grid.
+ Control child = children[i];
+ GridData spec = (GridData) child.getLayoutData();
+ while (((GridData[]) grid.elementAt(row))[column] != null) {
+ column = column + 1;
+ if (column >= numColumns) {
+ row = row + 1;
+ column = 0;
+ if (row >= grid.size()) {
+ grid.addElement(emptyRow());
+ }
+ }
+ }
+ // See if the place will support the widget's horizontal span. If not, go to the
+ // next row.
+ if (column + spec.horizontalSpan - 1 >= numColumns) {
+ grid.addElement(emptyRow());
+ row = row + 1;
+ column = 0;
+ }
+
+ // The vertical span for the item will be at least 1. If it is > 1,
+ // add other rows to the grid.
+ for (int j = 2; j <= spec.verticalSpan; j++) {
+ if (row + j > grid.size()) {
+ grid.addElement(emptyRow());
+ }
+ }
+
+ // Store the layout spec. Also cache the childIndex. NOTE: That we assume the children of a
+ // composite are maintained in the order in which they are created and added to the composite.
+ ((GridData[]) grid.elementAt(row))[column] = spec;
+ spec.childIndex = i;
+
+ // Put spacers in the grid to account for the item's vertical and horizontal
+ // span.
+ rowFill = spec.verticalSpan - 1;
+ columnFill = spec.horizontalSpan - 1;
+ for (int r = 1; r <= rowFill; r++) {
+ for (int c = 0; c < spec.horizontalSpan; c++) {
+ spacerSpec = new GridData();
+ spacerSpec.isItemData = false;
+ ((GridData[]) grid.elementAt(row + r))[column + c] = spacerSpec;
+ }
+ }
+ for (int c = 1; c <= columnFill; c++) {
+ for (int r = 0; r < spec.verticalSpan; r++) {
+ spacerSpec = new GridData();
+ spacerSpec.isItemData = false;
+ ((GridData[]) grid.elementAt(row + r))[column + c] = spacerSpec;
+ }
+ }
+ column = column + spec.horizontalSpan - 1;
+ }
+
+ // Fill out empty grid cells with spacers.
+ for (int k = column + 1; k < numColumns; k++) {
+ spacerSpec = new GridData();
+ spacerSpec.isItemData = false;
+ ((GridData[]) grid.elementAt(row))[k] = spacerSpec;
+ }
+ for (int k = row + 1; k < grid.size(); k++) {
+ spacerSpec = new GridData();
+ spacerSpec.isItemData = false;
+ ((GridData[]) grid.elementAt(k))[column] = spacerSpec;
+ }
+}
+GridData[] emptyRow() {
+ GridData[] row = new GridData[numColumns];
+ for (int i = 0; i < numColumns; i++) {
+ row[i] = null;}
+ return row;
+}
+void initializeLayoutData(Composite composite) {
+ Control[] children = composite.getChildren();
+ for (int i = 0; i < children.length; i++) {
+ Control child = children[i];
+ if (child.getLayoutData() == null) {
+ child.setLayoutData(new GridData());
+ }
+ }
+}
+protected void layout(Composite composite, boolean flushCache) {
+ int[] columnWidths;
+ int[] rowHeights;
+ int columnSize, rowSize, rowY, columnX;
+ int compositeWidth, compositeHeight;
+ int excessHorizontal, excessVertical;
+ Control[] children;
+ if (flushCache) {
+ // Cause the grid and its related information to be calculated
+ // again.
+ grid.removeAllElements();
+ }
+ children = composite.getChildren();
+ if (children.length == 0)
+ return;
+
+ //
+ Point extent = computeSize(composite, SWT.DEFAULT, SWT.DEFAULT, flushCache);
+ columnWidths = new int[numColumns];
+ for (int i = 0; i < pixelColumnWidths.length; i++) {
+ columnWidths[i] = pixelColumnWidths[i];
+ }
+ rowHeights = new int[grid.size()];
+ for (int i = 0; i < pixelRowHeights.length; i++) {
+ rowHeights[i] = pixelRowHeights[i];
+ }
+ int columnWidth = 0;
+ columnSize = Math.max(1, numColumns);
+ rowSize = Math.max(1, grid.size());
+
+ //
+ compositeWidth = extent.x;
+ compositeHeight = extent.y;
+
+ // Calculate whether or not there is any extra space or not enough space due to a resize
+ // operation. Then allocate/deallocate the space to columns and rows that are expandable.
+ // If a widget grabs excess space, its last column or row will be expandable.
+ excessHorizontal = composite.getClientArea().width - compositeWidth;
+ excessVertical = composite.getClientArea().height - compositeHeight;
+
+ // Allocate/deallocate horizontal space.
+ if (expandableColumns.length != 0) {
+ int excess, remainder, last;
+ int colWidth;
+ excess = excessHorizontal / expandableColumns.length;
+ remainder = excessHorizontal % expandableColumns.length;
+ last = 0;
+ for (int i = 0; i < expandableColumns.length; i++) {
+ int expandableCol = expandableColumns[i];
+ colWidth = columnWidths[expandableCol];
+ colWidth = colWidth + excess;
+ columnWidths[expandableCol] = colWidth;
+ last = Math.max(last, expandableCol);
+ }
+ colWidth = columnWidths[last];
+ colWidth = colWidth + remainder;
+ columnWidths[last] = colWidth;
+ }
+
+ // Go through all specs in each expandable column and get the maximum specified
+ // widthHint. Use this as the minimumWidth for the column.
+ for (int i = 0; i < expandableColumns.length; i++) {
+ int expandableCol = expandableColumns[i];
+ int colWidth = columnWidths[expandableCol];
+ int minWidth = 0;
+ for (int j = 0; j < grid.size(); j++) {
+ GridData[] row = (GridData[]) grid.elementAt(j);
+ GridData spec = row[expandableCol];
+ minWidth = Math.max(minWidth, spec.widthHint);
+ }
+ columnWidths[expandableCol] = Math.max(colWidth, minWidth);
+ }
+ // Allocate/deallocate vertical space.
+ if (expandableRows.length != 0) {
+ int excess, remainder, last;
+ int rowHeight;
+ excess = excessVertical / expandableRows.length;
+ remainder = excessVertical % expandableRows.length;
+ last = 0;
+ for (int i = 0; i < expandableRows.length; i++) {
+ int expandableRow = expandableRows[i];
+ rowHeight = rowHeights[expandableRow];
+ rowHeight = rowHeight + excess;
+ rowHeights[expandableRow] = rowHeight;
+ last = Math.max(last, expandableRow);
+ }
+ rowHeight = rowHeights[last];
+ rowHeight = rowHeight + remainder;
+ rowHeights[last] = rowHeight;
+ }
+ // Go through all specs in each expandable row and get the maximum specified
+ // heightHint. Use this as the minimumHeight for the row.
+ for (int i = 0; i < expandableRows.length; i++) {
+ int expandableRow = expandableRows[i];
+ int rowHeight = rowHeights[expandableRow];
+ int minHeight = 0;
+ GridData[] row = (GridData[]) grid.elementAt(expandableRow);
+ for (int j = 0; j < numColumns; j++) {
+ GridData spec = row[j];
+ minHeight = Math.max(minHeight, spec.heightHint);
+ }
+ rowHeights[expandableRow] = Math.max(rowHeight, minHeight);
+ }
+
+ // Get the starting x and y.
+ columnX = marginWidth + composite.getClientArea().x;
+ rowY = marginHeight + composite.getClientArea().y;
+
+ // Layout the widget left to right, top to bottom.
+ for (int r = 0; r < rowSize; r++) {
+ int rowHeight = rowHeights[r];
+ GridData[] row = (GridData[]) grid.elementAt(r);
+
+ //
+ for (int c = 0; c < row.length; c++) {
+ int spannedWidth = 0, spannedHeight = 0;
+ int hAlign = 0, vAlign = 0;
+ int widgetX = 0, widgetY = 0;
+ int widgetW = 0, widgetH = 0;
+
+ //
+ GridData spec = (GridData) row[c];
+ if (makeColumnsEqualWidth) {
+ columnWidth = composite.getClientArea().width - 2 * (marginWidth) - ((numColumns - 1) * horizontalSpacing);
+ columnWidth = columnWidth / numColumns;
+ for (int i = 0; i < columnWidths.length; i++) {
+ columnWidths[i] = columnWidth;
+ }
+ } else {
+ columnWidth = columnWidths[c];
+ }
+
+ //
+ spannedWidth = columnWidth;
+ for (int k = 1; k < spec.horizontalSpan; k++) {
+ if ((c + k) <= numColumns) {
+ if (!makeColumnsEqualWidth) {
+ columnWidth = columnWidths[c + k];
+ }
+ spannedWidth = spannedWidth + columnWidth + horizontalSpacing;
+ }
+ }
+
+ //
+ spannedHeight = rowHeight;
+ for (int k = 1; k < spec.verticalSpan; k++) {
+ if ((r + k) <= grid.size()) {
+ spannedHeight = spannedHeight + rowHeights[r + k] + verticalSpacing;
+ }
+ }
+
+ //
+ if (spec.isItemData()) {
+ Control child = children[spec.childIndex];
+ Point childExtent = child.computeSize(spec.widthHint, spec.heightHint, flushCache);
+ hAlign = spec.horizontalAlignment;
+ widgetX = columnX;
+
+ // Calculate the x and width values for the widget.
+ if (hAlign == spec.CENTER) {
+ widgetX = widgetX + (spannedWidth / 2) - (childExtent.x / 2);
+ } else
+ if (hAlign == spec.END) {
+ widgetX = widgetX + spannedWidth - childExtent.x - spec.horizontalIndent;
+ } else {
+ widgetX = widgetX + spec.horizontalIndent;
+ }
+ if (hAlign == spec.FILL) {
+ widgetW = spannedWidth - spec.horizontalIndent;
+ widgetX = columnX + spec.horizontalIndent;
+ } else {
+ widgetW = childExtent.x;
+ }
+
+ // Calculate the y and height values for the widget.
+ vAlign = spec.verticalAlignment;
+ widgetY = rowY;
+ if (vAlign == spec.CENTER) {
+ widgetY = widgetY + (spannedHeight / 2) - (childExtent.y / 2);
+ } else
+ if (vAlign == spec.END) {
+ widgetY = widgetY + spannedHeight - childExtent.y;
+ } else {
+ widgetY = widgetY;
+ }
+ if (vAlign == spec.FILL) {
+ widgetH = spannedHeight;
+ widgetY = rowY;
+ } else {
+ widgetH = childExtent.y;
+ }
+ // Place the widget.
+ child.setBounds(widgetX, widgetY, widgetW, widgetH);
+ }
+ // Update the starting x value.
+ columnX = columnX + columnWidths[c] + horizontalSpacing;
+ }
+ // Update the starting y value and since we're starting a new row, reset the starting x value.
+ rowY = rowY + rowHeights[r] + verticalSpacing;
+ columnX = marginWidth + composite.getClientArea().x;
+ }
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/RowData.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/RowData.java
new file mode 100755
index 0000000000..a3a0f8f282
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/RowData.java
@@ -0,0 +1,29 @@
+package org.eclipse.swt.layout;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+public final class RowData {
+ /**
+ * width specifies the width of the cell in pixels.
+ */
+ public int width;
+ /**
+ * height specifies the height of the cell in pixels.
+ */
+ public int height;
+public RowData () {
+ this (SWT.DEFAULT, SWT.DEFAULT);
+}
+public RowData (int width, int height) {
+ this.width = width; this.height = height;
+}
+public RowData (Point point) {
+ this (point.x, point.y);
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/RowLayout.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/RowLayout.java
new file mode 100755
index 0000000000..1e43a2287c
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/RowLayout.java
@@ -0,0 +1,151 @@
+package org.eclipse.swt.layout;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+public final class RowLayout extends Layout {
+ /**
+ * wrap specifies whether a control will be wrapped to the next
+ * row if there is insufficient space on the current row.
+ *
+ * The default value is true.
+ */
+ public boolean wrap = true;
+ /**
+ * pack specifies whether all controls in the layout are forced
+ * to be the same size.
+ *
+ * The default value is true.
+ */
+ public boolean pack = true;
+ /**
+ * justify specifies whether the controls in a row should be
+ * fully justified, with any extra space placed between the controls.
+ *
+ * The default value is false.
+ */
+ public boolean justify = false;
+ /**
+ * spacing specifies the number of pixels between the edge of one cell
+ * and the edge of its neighbouring cell.
+ *
+ * The default value is 3.
+ */
+ public int spacing = 3;
+ /**
+ * marginLeft specifies the number of pixels of horizontal margin
+ * that will be placed along the left edge of the layout.
+ *
+ * The default value is 3.
+ */
+ public int marginLeft = 3;
+ /**
+ * marginTop specifies the number of pixels of vertical margin
+ * that will be placed along the top edge of the layout.
+ *
+ * The default value is 3.
+ */
+ public int marginTop = 3;
+ /**
+ * marginRight specifies the number of pixels of horizontal margin
+ * that will be placed along the right edge of the layout.
+ *
+ * The default value is 3.
+ */
+ public int marginRight = 3;
+ /**
+ * marginBottom specifies the number of pixels of vertical margin
+ * that will be placed along the bottom edge of the layout.
+ *
+ * The default value is 3.
+ */
+ public int marginBottom = 3;
+public RowLayout () {
+}
+protected Point computeSize (Composite composite, int wHint, int hHint, boolean flushCache) {
+ Point extent = layout (composite, false, (wHint != SWT.DEFAULT) && wrap, wHint, flushCache);
+ if (wHint != SWT.DEFAULT) extent.x = wHint;
+ if (hHint != SWT.DEFAULT) extent.y = hHint;
+ return extent;
+}
+Point getSize (Control control, boolean flushCache) {
+ int wHint = SWT.DEFAULT, hHint = SWT.DEFAULT;
+ RowData data = (RowData) control.getLayoutData ();
+ if (data != null) {
+ wHint = data.width;
+ hHint = data.height;
+ }
+ return control.computeSize (wHint, hHint, flushCache);
+}
+protected void layout (Composite composite, boolean flushCache) {
+ Rectangle clientArea = composite.getClientArea ();
+ layout (composite, true, wrap, clientArea.width, flushCache);
+}
+Point layout (Composite composite, boolean move, boolean wrap, int width, boolean flushCache) {
+ Control [] children = composite.getChildren ();
+ int count = children.length;
+ int childWidth = 0, childHeight = 0, maxHeight = 0;
+ if (!pack) {
+ for (int i=0; i<count; i++) {
+ Control child = children [i];
+ Point pt = getSize (child, flushCache);
+ childWidth = Math.max (childWidth, pt.x);
+ childHeight = Math.max (childHeight, pt.y);
+ }
+ maxHeight = childHeight;
+ }
+ int clientX = 0, clientY = 0;
+ if (move) {
+ Rectangle rect = composite.getClientArea ();
+ clientX = rect.x; clientY = rect.y;
+ }
+ boolean wrapped = false;
+ Rectangle [] bounds = null;
+ if (move && justify) bounds = new Rectangle [count];
+ int maxX = 0, x = marginLeft, y = marginTop;
+ for (int i=0; i<count; i++) {
+ Control child = children [i];
+ if (pack) {
+ Point pt = getSize (child, flushCache);
+ childWidth = pt.x; childHeight = pt.y;
+ }
+ if (wrap && (i != 0) && (x + childWidth > width)) {
+ wrapped = true;
+ x = marginLeft; y += spacing + maxHeight;
+ }
+ if (pack) {
+ maxHeight = Math.max (maxHeight, childHeight);
+ }
+ if (move) {
+ int childX = x + clientX, childY = y + clientY;
+ if (justify) {
+ bounds [i] = new Rectangle (childX, childY, childWidth, childHeight);
+ } else {
+ child.setBounds (childX, childY, childWidth, childHeight);
+ }
+ }
+ x += spacing + childWidth;
+ maxX = Math.max (maxX, x);
+ }
+ if (!wrap) maxX = x + marginRight;
+ if (move && justify) {
+ int space = 0, margin = 0;
+ if (!wrapped) {
+ space = Math.max (0, (width - maxX) / (count + 1));
+ margin = Math.max (0, ((width - maxX) % (count + 1)) / 2);
+ }
+ for (int i=0; i<count; i++) {
+ Control child = children [i];
+ bounds [i].x += (space * (i + 1)) + margin;
+ child.setBounds (bounds [i]);
+ }
+ }
+ return new Point (maxX, y + maxHeight + marginBottom);
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/package.html b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/package.html
new file mode 100755
index 0000000000..2f36647b51
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/layout/package.html
@@ -0,0 +1,13 @@
+ <html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="Author" content="IBM">
+ <title>Package-level Javadoc</title>
+</head>
+<body>
+Brief overview will be provided here.
+<h2>
+Package Specification</h2>
+Detailed overview will be provided here.
+</body>
+</html>
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/package.html b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/package.html
new file mode 100755
index 0000000000..ec94fab277
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/package.html
@@ -0,0 +1,15 @@
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="Author" content="IBM">
+ <title>Package-level Javadoc</title>
+</head>
+<body>
+SWT constants and error handling support.
+<h2>
+Package Specification</h2>
+This package provides the class <code>SWT</code> which contains all of the
+constants used by SWT as well as a small selection of error handling routines
+and queries such as <code>getPlatform</code> and <code>getVersion</code>.
+</body>
+</html>
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Dialog.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Dialog.java
new file mode 100755
index 0000000000..c20fba446c
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Dialog.java
@@ -0,0 +1,207 @@
+package org.eclipse.swt.widgets;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * This class is the abstract superclass of the classes
+ * that represent the built in platform dialogs.
+ * A <code>Dialog</code> typically contains other widgets
+ * that are not accessible. A <code>Dialog</code> is not
+ * a <code>Widget</code>.
+ * <p>
+ * Note: The <em>modality</em> styles supported by this class
+ * must be treated as <em>HINT</em>s, because not all are
+ * supported by every subclass. If a modality style is
+ * not supported, it is "upgraded" to a more restrictive modality
+ * style that is supported. For example, if <code>PRIMARY_MODAL</code>
+ * is not supported by a particular dialog, it would be upgraded to
+ * <code>APPLICATION_MODAL</code>. In addition, as is the case
+ * for shells, the window manager for the desktop on which the
+ * instance is visible has ultimate control over the appearance
+ * and behavior of the instance, including its modality.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>APPLICATION_MODAL, MODELESS, PRIMARY_MODAL, SYSTEM_MODAL</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ *
+ * @see Shell
+ */
+
+public abstract class Dialog {
+
+ int style;
+ Shell parent;
+ String title;
+
+/**
+ * Constructs a new instance of this class given only its
+ * parent.
+ * <p>
+ * Note: Currently, null can be passed in for the parent.
+ * This has the effect of creating the dialog on the currently active
+ * display if there is one. If there is no current display, the
+ * dialog is created on a "default" display. <b>Passing in null as
+ * the parent is not considered to be good coding style,
+ * and may not be supported in a future release of SWT.</b>
+ * </p>
+ *
+ * @param parent a shell which will be the parent of the new instance
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ */
+public Dialog (Shell parent) {
+ this (parent, 0);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * for all SWT dialog classes should include a comment which
+ * describes the style constants which are applicable to the class.
+ * </p>
+ * Note: Currently, null can be passed in for the parent.
+ * This has the effect of creating the dialog on the currently active
+ * display if there is one. If there is no current display, the
+ * dialog is created on a "default" display. <b>Passing in null as
+ * the parent is not considered to be good coding style,
+ * and may not be supported in a future release of SWT.</b>
+ * </p>
+ *
+ * @param parent a shell which will be the parent of the new instance
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ */
+public Dialog (Shell parent, int style) {
+ checkSubclass ();
+ this.parent = parent;
+ this.style = style;
+ title = "";
+}
+
+/**
+ * Checks that this class can be subclassed.
+ * <p>
+ * IMPORTANT: See the comment in <code>Widget.checkSubclass()</code>.
+ * </p>
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see Widget#checkSubclass
+ */
+protected void checkSubclass () {
+ if (!Display.isValidClass (getClass ())) {
+ error (SWT.ERROR_INVALID_SUBCLASS);
+ }
+}
+
+/**
+ * Does whatever dialog specific cleanup is required, and then
+ * uses the code in <code>SWTError.error</code> to handle the error.
+ *
+ * @param code the descriptive error code
+ *
+ * @see SWTError#error
+ */
+void error (int code) {
+ SWT.error(code);
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>Shell</code>
+ * or null.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+public Shell getParent () {
+ return parent;
+}
+
+/**
+ * Returns the receiver's style information.
+ * <p>
+ * Note that, the value which is returned by this method <em>may
+ * not match</em> the value which was provided to the constructor
+ * when the receiver was created.
+ * </p>
+ *
+ * @return the style bits
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+public int getStyle () {
+ return style;
+}
+
+/**
+ * Returns the receiver's text, which is the string that the
+ * window manager will typically display as the receiver's
+ * <em>title</em>. If the text has not previously been set,
+ * returns an empty string.
+ *
+ * @return the text
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+public String getText () {
+ return title;
+}
+
+/**
+ * Sets the receiver's text, which is the string that the
+ * window manager will typically display as the receiver's
+ * <em>title</em>, to the argument, which may not be null.
+ *
+ * @param text the new text
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+public void setText (String string) {
+ title = string;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Event.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Event.java
new file mode 100755
index 0000000000..34c4c2ebea
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Event.java
@@ -0,0 +1,84 @@
+package org.eclipse.swt.widgets;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+/**
+ * Instances of this class provide a description of a particular
+ * event which occurred within SWT. The SWT <em>untyped listener</em>
+ * API uses these instances for all event dispatching.
+ * <p>
+ * Note: For a given event, only the fields which are appropriate
+ * will be filled in. The contents of the fields which are not used
+ * by the event are unspecified.
+ * </p>
+ *
+ * @see Listener
+ * @see TypedEvent
+ */
+
+public class Event {
+
+ /**
+ * the type of event, as defined by the event type constants
+ * in class <code>SWT</code>
+ *
+ * @see SWT
+ */
+ public int type;
+
+ /**
+ * the widget that the event occurred in
+ */
+ public Widget widget;
+ public Widget item;
+ public GC gc;
+ public int detail;
+ public int x, y, width, height;
+ public int time;
+ public int count;
+ public int button;
+ public int keyCode;
+ public int stateMask;
+ public char character;
+ public int start, end;
+ public String text;
+ public boolean doit = true;
+ public Object data;
+
+/**
+* Gets the bounds.
+* <p>
+* @return a rectangle that is the bounds.
+*/
+public Rectangle getBounds () {
+ return new Rectangle (x, y, width, height);
+}
+/**
+* Sets the bounds.
+* <p>
+* @param x the new x position
+* @param y the new y position
+* @param width the new width
+* @param height the new height
+*/
+public void setBounds (Rectangle rect) {
+ this.x = rect.x;
+ this.y = rect.y;
+ this.width = rect.width;
+ this.height = rect.height;
+}
+/**
+* Returns a string representation of the object.
+*
+* @return a string representation of the object
+*/
+public String toString () {
+ return "Event {type=" + type + ",widget=" + widget + ",x=" + x + ",y=" + y + ",width=" + width + ",height=" + height + "}";
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/EventTable.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/EventTable.java
new file mode 100755
index 0000000000..197c06245f
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/EventTable.java
@@ -0,0 +1,85 @@
+package org.eclipse.swt.widgets;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import java.util.EventListener;
+
+/**
+ * Instances of this class implement a simple
+ * look up mechanism that maps an event type
+ * to a listener. Muliple listeners for the
+ * same event type are supported.
+ */
+
+class EventTable {
+ int [] types;
+ Listener [] handlers;
+
+public void hook (int eventType, Listener handler) {
+ if (types == null) types = new int [4];
+ if (handlers == null) handlers = new Listener [4];
+ for (int i=0; i<types.length; i++) {
+ if (types [i] == 0) {
+ types [i] = eventType;
+ handlers [i] = handler;
+ return;
+ }
+ }
+ int size = types.length;
+ int [] newTypes = new int [size + 4];
+ Listener [] newHandlers = new Listener [size + 4];
+ System.arraycopy (types, 0, newTypes, 0, size);
+ System.arraycopy (handlers, 0, newHandlers, 0, size);
+ types = newTypes; handlers = newHandlers;
+ types [size] = eventType; handlers [size] = handler;
+}
+
+public boolean hooks (int eventType) {
+ if (handlers == null) return false;
+ for (int i=0; i<types.length; i++) {
+ if (types [i] == eventType) return true;
+ }
+ return false;
+}
+
+public void sendEvent (Event event) {
+ if (handlers == null) return;
+ for (int i=0; i<types.length; i++) {
+ if (types [i] == event.type) {
+ Listener listener = handlers [i];
+ if (listener != null) listener.handleEvent (event);
+ }
+ }
+}
+
+public void unhook (int eventType, Listener handler) {
+ if (handlers == null) return;
+ for (int i=0; i<types.length; i++) {
+ if ((types [i] == eventType) && (handlers [i] == handler)) {
+ types [i] = 0;
+ handlers [i] = null;
+ return;
+ }
+ }
+}
+
+public void unhook (int eventType, EventListener handler) {
+ if (handlers == null) return;
+ for (int i=0; i<types.length; i++) {
+ if (types [i] == eventType) {
+ if (handlers [i] instanceof TypedListener) {
+ TypedListener listener = (TypedListener) handlers [i];
+ if (listener.getEventListener () == handler) {
+ types [i] = 0;
+ handlers [i] = null;
+ return;
+ }
+ }
+ }
+ }
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Item.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Item.java
new file mode 100755
index 0000000000..a7c8744959
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Item.java
@@ -0,0 +1,110 @@
+package org.eclipse.swt.widgets;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+/**
+ * This class is the abstract superclass of all non-windowed
+ * user interface objects that occur within specific
+ * controls. For example, a tree will contain tree
+ * items.
+ */
+
+public abstract class Item extends Widget {
+ String text;
+ Image image;
+
+public Item (Widget parent, int style) {
+ super (parent, style);
+ text = "";
+}
+
+public Item (Widget parent, int style, int index) {
+ this (parent, style);
+}
+
+protected void checkSubclass () {
+ /* Do Nothing - Subclassing is allowed */
+}
+
+/**
+ * Returns the receiver's image if it has one, or null
+ * if it does not.
+ *
+ * @return the receiver's image
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+public Image getImage () {
+ checkWidget ();
+ return image;
+}
+
+String getNameText () {
+ return getText ();
+}
+
+/**
+ * Returns the receiver's text, which will be an empty
+ * string if it has never been set.
+ *
+ * @return the receiver's text
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+public String getText () {
+ checkWidget();
+ return text;
+}
+
+void releaseWidget () {
+ super.releaseWidget ();
+ text = null;
+ image = null;
+}
+/**
+ * Sets the receiver's image to the argument, which may be
+ * null indicating that no image should be displayed.
+ *
+ * @param image the image to display on the receiver (may be null)
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+public void setImage (Image image) {
+ checkWidget ();
+ this.image = image;
+}
+
+/**
+ * Sets the receiver's text.
+ *
+ * @param string the new text
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the text is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+public void setText (String string) {
+ checkWidget ();
+ text = string;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Layout.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Layout.java
new file mode 100755
index 0000000000..120a78d145
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Layout.java
@@ -0,0 +1,76 @@
+package org.eclipse.swt.widgets;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+
+/**
+ * A layout controls the position and size
+ * of the children of a composite widget.
+ * This class is the abstract base class for
+ * layouts.
+ */
+public abstract class Layout {
+
+/**
+ * Computes and returns the size of the specified
+ * composite's client area according to this layout.
+ * <p>
+ * This method computes the minimum size that the
+ * client area of the composite must be in order to
+ * position all children at their minimum size inside
+ * the composite according to the layout algorithm
+ * encoded by this layout.
+ * </p>
+ * <p>
+ * When a width or height hint is supplied, it is
+ * used to constrain the result. For example, if a
+ * width hint is provided that is less than the minimum
+ * width of the client area, the layout may choose
+ * to wrap and increase height, clip, overlap, or
+ * otherwise constrain the children.
+ * </p>
+ *
+ * @param composite a composite widget using this layout
+ * @param wHint width (<code>SWT.DEFAULT</code> for minimum)
+ * @param hHint height (<code>SWT.DEFAULT</code> for minimum)
+ * @param flushCache <code>true</code> means flush cached layout values
+ * @return a point containing the computed size (width, height)
+ * @see #layout
+ */
+protected abstract Point computeSize (Composite composite, int wHint, int hHint, boolean flushCache);
+
+/**
+ * Lays out the children of the specified composite
+ * according to this layout.
+ * <p>
+ * This method positions and sizes the children of a
+ * composite using the layout algorithm encoded by this
+ * layout. Children of the composite are positioned in
+ * the client area of the composite. The position of
+ * the composite is not altered by this method.
+ * </p>
+ * <p>
+ * When the flush cache hint is true, the layout is
+ * instructed to flush any cached values associated
+ * with the children. Typically, a layout will cache
+ * the preferred sizes of the children to avoid the
+ * expense of computing these values each time the
+ * widget is layed out.
+ * </p>
+ * <p>
+ * When layout is triggered explicitly by the programmer
+ * the flush cache hint is true. When layout is triggered
+ * by a resize, either caused by the programmer or by the
+ * user, the hint is false.
+ * </p>
+ *
+ * @param composite a composite widget using this layout
+ * @param flushCache <code>true</code> means flush cached layout values
+ */
+protected abstract void layout (Composite composite, boolean flushCache);
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Listener.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Listener.java
new file mode 100755
index 0000000000..0541c8a24f
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Listener.java
@@ -0,0 +1,45 @@
+package org.eclipse.swt.widgets;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+/**
+ * <code>Listener</code>s implement a simple <code>handleEvent(...)</code>
+ * method that is used internally by SWT to dispatch events.
+ * <p>
+ * After creating an instance of a class that implements this interface
+ * it can be added to a widget using the
+ * <code>addListener(int eventType, Listener handler)</code> method and
+ * removed using the
+ * <code>removeListener (int eventType, Listener handler)</code> method.
+ * When the specified event occurs, <code>handleEvent(...)</code> will
+ * will be sent to the instance.
+ * </p>
+ * <p>
+ * Classes which implement this interface are described within SWT as
+ * providing the <em>untyped listener</em> API. Typically, widgets will
+ * also provide a higher-level <em>typed listener</em> API, that is based
+ * on the standard <code>java.util.EventListener</code> pattern.
+ * </p>
+ * <p>
+ * Note that, since all internal SWT event dispatching is based on untyped
+ * listeners, it is simple to build subsets of SWT for use on memory
+ * constrained, small footprint devices, by removing the classes and
+ * methods which implement the typed listener API.
+ * </p>
+ *
+ * @see Widget#addListener
+ * @see java.util.EventListener
+ * @see org.eclipse.swt.events.*
+ */
+public interface Listener {
+
+/**
+ * Sent when an event that the receiver has registered for occurs.
+ *
+ * @param event the event which occurred
+ */
+void handleEvent (Event event);
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/RunnableLock.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/RunnableLock.java
new file mode 100755
index 0000000000..a50c77e828
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/RunnableLock.java
@@ -0,0 +1,32 @@
+package org.eclipse.swt.widgets;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+/**
+ * Instances of this class are used to ensure that an
+ * application cannot interfere with the locking mechanism
+ * used to implement asynchonous and synchronous communication
+ * between widgets and background threads.
+ */
+
+class RunnableLock {
+ Runnable runnable;
+ Thread thread;
+
+RunnableLock (Runnable runnable) {
+ this.runnable = runnable;
+}
+
+boolean done () {
+ return runnable == null;
+}
+
+void run () {
+ if (runnable != null) runnable.run ();
+ runnable = null;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Synchronizer.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Synchronizer.java
new file mode 100755
index 0000000000..6338a4c0bb
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Synchronizer.java
@@ -0,0 +1,140 @@
+package org.eclipse.swt.widgets;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+/**
+ * Instances of this class provide synchronization support
+ * for displays. A default instance is created automatically
+ * for each display, and this instance is sufficient for almost
+ * all applications.
+ * <p>
+ * <b>IMPORTANT:</b> Typical application code <em>never</em>
+ * needs to deal with this class. It is provided only to
+ * allow applications which require non-standard
+ * synchronization behavior to plug in the support they
+ * require. <em>Subclasses which override the methods in
+ * this class must ensure that the superclass methods are
+ * invoked in their implementations</em>
+ * </p>
+ *
+ * @see Display#setSynchronizer
+ */
+public class Synchronizer {
+ Display display;
+ int messagesSize;
+ RunnableLock [] messages;
+ Object messageLock = new Object ();
+ Thread syncThread;
+
+public Synchronizer (Display display) {
+ this.display = display;
+}
+
+void addLast (RunnableLock entry) {
+ synchronized (messageLock) {
+ if (messages == null) messages = new RunnableLock [4];
+ if (messagesSize == messages.length) {
+ RunnableLock[] newMessages = new RunnableLock [messagesSize + 4];
+ System.arraycopy (messages, 0, newMessages, 0, messagesSize);
+ messages = newMessages;
+ }
+ messages [messagesSize++] = entry;
+ }
+}
+
+/**
+ * Causes the <code>run()</code> method of the runnable to
+ * be invoked by the user-interface thread at the next
+ * reasonable opportunity. The caller of this method continues
+ * to run in parallel, and is not notified when the
+ * runnable has completed.
+ *
+ * @param runnable code to run on the user-interface thread.
+ *
+ * @see #syncExec
+ */
+protected void asyncExec (Runnable runnable) {
+ if (runnable != null) addLast (new RunnableLock (runnable));
+ display.wake ();
+}
+
+void releaseSynchronizer () {
+ display = null;
+ messages = null;
+ messageLock = null;
+ syncThread = null;
+}
+
+RunnableLock removeFirst () {
+ synchronized (messageLock) {
+ if (messagesSize == 0) return null;
+ RunnableLock lock = messages [0];
+ System.arraycopy (messages, 1, messages, 0, --messagesSize);
+ messages [messagesSize] = null;
+ if (messagesSize == 0) messages = null;
+ return lock;
+ }
+}
+
+boolean runAsyncMessages () {
+ if (messagesSize == 0) return false;
+ do {
+ RunnableLock lock = removeFirst ();
+ if (lock == null) return true;
+ synchronized (lock) {
+ syncThread = lock.thread;
+ try {
+ lock.run ();
+ } finally {
+ syncThread = null;
+ }
+ lock.notifyAll ();
+ };
+ } while (true);
+}
+
+/**
+ * Causes the <code>run()</code> method of the runnable to
+ * be invoked by the user-interface thread at the next
+ * reasonable opportunity. The thread which calls this method
+ * is suspended until the runnable completes.
+ *
+ * @param runnable code to run on the user-interface thread.
+ *
+ * @see #asyncExec
+ */
+protected void syncExec (Runnable runnable) {
+ if (display.isValidThread ()) {
+ if (runnable != null) runnable.run ();
+ return;
+ }
+ if (runnable == null) {
+ display.wake ();
+ return;
+ }
+ RunnableLock lock = new RunnableLock (runnable);
+ /*
+ * Only remember the syncThread for syncExec.
+ */
+ lock.thread = Thread.currentThread();
+ synchronized (lock) {
+ addLast (lock);
+ display.wake ();
+ boolean interrupted = false;
+ while (!lock.done ()) {
+ try {
+ lock.wait ();
+ } catch (InterruptedException e) {
+ interrupted = true;
+ }
+ }
+ if (interrupted) {
+ Thread.currentThread ().interrupt ();
+ }
+ }
+}
+
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/TypedListener.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/TypedListener.java
new file mode 100755
index 0000000000..f4489cacab
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/TypedListener.java
@@ -0,0 +1,222 @@
+package org.eclipse.swt.widgets;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2001 All Rights Reserved
+ */
+
+import java.util.EventListener;
+import org.eclipse.swt.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * Instances of this class are <em>internal SWT implementation</em>
+ * objects which provide a mapping between the typed and untyped
+ * listener mechanisms that SWT supports.
+ * <p>
+ * <b>IMPORTANT:</b> This class is <em>not</em> part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It should never be
+ * referenced from application code.
+ * </p>
+ *
+ * @see Listener
+ *
+ * @private
+ */
+public class TypedListener implements Listener {
+
+ /**
+ * The receiver's event listener
+ */
+ protected EventListener eventListener;
+
+/**
+ * Constructs a new instance of this class for the given event listener.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It should never be
+ * referenced from application code.
+ * </p>
+ *
+ * @param listener the event listener to store in the receiver
+ */
+public TypedListener (EventListener listener) {
+ eventListener = listener;
+}
+
+/**
+ * Returns the receiver's event listener.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It should never be
+ * referenced from application code.
+ * </p>
+ *
+ * @return the receiver's event listener
+ */
+public EventListener getEventListener () {
+ return eventListener;
+}
+
+/**
+ * Handles the given event.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It should never be
+ * referenced from application code.
+ * </p>
+ */
+public void handleEvent (Event e) {
+ switch (e.type) {
+ case SWT.Paint: {
+ /* Field set by Control */
+ PaintEvent event = new PaintEvent (e);
+ ((PaintListener) eventListener).paintControl (event);
+ e.gc = event.gc;
+ break;
+ }
+ case SWT.Selection: {
+ /* Fields set by Sash */
+ SelectionEvent event = new SelectionEvent (e);
+ ((SelectionListener) eventListener).widgetSelected (event);
+ e.x = event.x;
+ e.y = event.y;
+ e.doit = event.doit;
+ break;
+ }
+ case SWT.DefaultSelection: {
+ ((SelectionListener)eventListener).widgetDefaultSelected(new SelectionEvent(e));
+ break;
+ }
+ case SWT.Dispose: {
+ ((DisposeListener) eventListener).widgetDisposed(new DisposeEvent(e));
+ break;
+ }
+ case SWT.FocusIn: {
+ ((FocusListener) eventListener).focusGained(new FocusEvent(e));
+ break;
+ }
+ case SWT.FocusOut: {
+ ((FocusListener) eventListener).focusLost(new FocusEvent(e));
+ break;
+ }
+ case SWT.Hide: {
+ ((MenuListener) eventListener).menuHidden(new MenuEvent(e));
+ break;
+ }
+ case SWT.Show: {
+ ((MenuListener) eventListener).menuShown(new MenuEvent(e));
+ break;
+ }
+ case SWT.KeyDown: {
+ ((KeyListener) eventListener).keyPressed(new KeyEvent(e));
+ break;
+ }
+ case SWT.KeyUp: {
+ ((KeyListener) eventListener).keyReleased(new KeyEvent(e));
+ break;
+ }
+ case SWT.MouseDown: {
+ ((MouseListener) eventListener).mouseDown(new MouseEvent(e));
+ break;
+ }
+ case SWT.MouseUp: {
+ ((MouseListener) eventListener).mouseUp(new MouseEvent(e));
+ break;
+ }
+ case SWT.MouseDoubleClick: {
+ ((MouseListener) eventListener).mouseDoubleClick(new MouseEvent(e));
+ break;
+ }
+ case SWT.MouseMove: {
+ ((MouseMoveListener) eventListener).mouseMove(new MouseEvent(e));
+ return;
+ }
+ case SWT.Resize: {
+ ((ControlListener) eventListener).controlResized(new ControlEvent(e));
+ break;
+ }
+ case SWT.Move: {
+ ((ControlListener) eventListener).controlMoved(new ControlEvent(e));
+ break;
+ }
+ case SWT.Close: {
+ /* Fields set by Decorations */
+ ShellEvent event = new ShellEvent (e);
+ ((ShellListener) eventListener).shellClosed(event);
+ e.doit = event.doit;
+ break;
+ }
+ case SWT.Activate: {
+ ((ShellListener) eventListener).shellActivated(new ShellEvent(e));
+ break;
+ }
+ case SWT.Deactivate: {
+ ((ShellListener) eventListener).shellDeactivated(new ShellEvent(e));
+ break;
+ }
+ case SWT.Iconify: {
+ ((ShellListener) eventListener).shellIconified(new ShellEvent(e));
+ break;
+ }
+ case SWT.Deiconify: {
+ ((ShellListener) eventListener).shellDeiconified(new ShellEvent(e));
+ break;
+ }
+ case SWT.Expand: {
+ ((TreeListener) eventListener).treeExpanded(new TreeEvent(e));
+ break;
+ }
+ case SWT.Collapse: {
+ ((TreeListener) eventListener).treeCollapsed(new TreeEvent(e));
+ break;
+ }
+ case SWT.Modify: {
+ ((ModifyListener) eventListener).modifyText(new ModifyEvent(e));
+ break;
+ }
+ case SWT.Verify: {
+ /* Fields set by Text, RichText */
+ VerifyEvent event = new VerifyEvent (e);
+ ((VerifyListener) eventListener).verifyText (event);
+ e.text = event.text;
+ e.doit = event.doit;
+ break;
+ }
+ case SWT.Help: {
+ ((HelpListener) eventListener).helpRequested (new HelpEvent (e));
+ break;
+ }
+ case SWT.Arm: {
+ ((ArmListener) eventListener).widgetArmed (new ArmEvent (e));
+ break;
+ }
+ case SWT.MouseExit: {
+ ((MouseTrackListener) eventListener).mouseExit (new MouseEvent (e));
+ break;
+ }
+ case SWT.MouseEnter: {
+ ((MouseTrackListener) eventListener).mouseEnter (new MouseEvent (e));
+ break;
+ }
+ case SWT.MouseHover: {
+ ((MouseTrackListener) eventListener).mouseHover (new MouseEvent (e));
+ break;
+ }
+ case SWT.Traverse: {
+ /* Fields set by Control */
+ TraverseEvent event = new TraverseEvent (e);
+ ((TraverseListener) eventListener).keyTraversed (event);
+ e.detail = event.detail;
+ e.doit = event.doit;
+ break;
+ }
+
+ }
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/package.html b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/package.html
new file mode 100755
index 0000000000..b23d27be20
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/package.html
@@ -0,0 +1,15 @@
+ <html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="Author" content="IBM">
+ <title>Package-level Javadoc</title>
+</head>
+<body>
+SWT widget public API classes.
+<h2>
+Package Specification</h2>
+This package contains the classes which make up the public SWT widget
+API as well as the related public support classes (for example, class
+<code>Event</code>).
+</body>
+</html>