From 69831530c18f0b4229942b727c97be8ebbfc99c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Delgado?= Date: Tue, 2 Feb 2021 23:23:26 +0100 Subject: [PATCH] Initial commit --- .gitignore | 4 + META-INF/MANIFEST.MF | 4 + TileMolester.iml | 13 + TileMolester.jar | Bin 0 -> 466046 bytes languages/language.properties | 215 + languages/language_en_US.properties | 215 + languages/language_it_IT.properties | 215 + languages/language_no_NO.properties | 216 + languages/language_sp_LA.properties | 215 + languages/language_template | 213 + resources/tmres.dtd | 38 + settings.dtd | 9 + settings.xml | 9 + src/TileMolester.java | 52 + src/tm/FileImage.java | 221 + src/tm/TMBitmapExporter.java | 135 + src/tm/TMBitmapImporter.java | 130 + src/tm/TMFileResources.java | 358 ++ src/tm/TMPalette.java | 457 ++ src/tm/TMSpecReader.java | 371 ++ src/tm/canvases/TMEditorCanvas.java | 1591 ++++++ src/tm/canvases/TMPixelCanvas.java | 467 ++ src/tm/canvases/TMSelectionCanvas.java | 354 ++ src/tm/canvases/TMTileCanvas.java | 583 ++ src/tm/colorcodecs/ColorCodec.java | 186 + src/tm/colorcodecs/DirectColorCodec.java | 169 + src/tm/colorcodecs/IndexedColorCodec.java | 75 + .../GameBoyAdvanceFileListener.java | 104 + src/tm/filelistener/GameBoyFileListener.java | 156 + src/tm/filelistener/INESFileListener.java | 50 + .../filelistener/SegaGenesisFileListener.java | 176 + .../SegaMasterSystemFileListener.java | 84 + src/tm/filelistener/TMFileListener.java | 64 + .../TMApprovedFileOpenChooser.java | 72 + .../TMApprovedFileSaveChooser.java | 79 + src/tm/fileselection/TMFileFilter.java | 169 + src/tm/fileselection/TMPaletteFileFilter.java | 88 + .../fileselection/TMTileCodecFileFilter.java | 78 + src/tm/gfxlibs/BMPLoader.java | 543 ++ src/tm/gfxlibs/BMPReader.java | 305 ++ src/tm/gfxlibs/GIFOutputStream.java | 1010 ++++ src/tm/gfxlibs/ImageEncoder.java | 271 + src/tm/gfxlibs/PCXEncoder.java | 147 + src/tm/gfxlibs/PCXReader.java | 236 + src/tm/gfxlibs/PngEncoder.java | 621 +++ src/tm/gfxlibs/Quantize.java | 703 +++ src/tm/icons/Add24.gif | Bin 0 -> 470 bytes src/tm/icons/Back24.gif | Bin 0 -> 422 bytes src/tm/icons/Bookmarks24.gif | Bin 0 -> 283 bytes src/tm/icons/Brush24.gif | Bin 0 -> 145 bytes src/tm/icons/BrushCursor24.gif | Bin 0 -> 147 bytes src/tm/icons/ColorReplacer24.gif | Bin 0 -> 166 bytes src/tm/icons/ColumnDelete24.gif | Bin 0 -> 253 bytes src/tm/icons/ColumnInsertAfter24.gif | Bin 0 -> 239 bytes src/tm/icons/Copy24.gif | Bin 0 -> 682 bytes src/tm/icons/Cut24.gif | Bin 0 -> 1193 bytes src/tm/icons/DecHeight24.gif | Bin 0 -> 903 bytes src/tm/icons/DecPalIndex24.gif | Bin 0 -> 239 bytes src/tm/icons/DecWidth24.gif | Bin 0 -> 932 bytes src/tm/icons/Delete24.gif | Bin 0 -> 249 bytes src/tm/icons/Down24.gif | Bin 0 -> 635 bytes src/tm/icons/Dropper24.gif | Bin 0 -> 150 bytes src/tm/icons/DropperCursor24.gif | Bin 0 -> 162 bytes src/tm/icons/End24.gif | Bin 0 -> 1104 bytes src/tm/icons/Export24.gif | Bin 0 -> 473 bytes src/tm/icons/FastForward24.gif | Bin 0 -> 279 bytes src/tm/icons/Fill24.gif | Bin 0 -> 171 bytes src/tm/icons/FillCursor24.gif | Bin 0 -> 166 bytes src/tm/icons/Flip24.gif | Bin 0 -> 148 bytes src/tm/icons/Forward24.gif | Bin 0 -> 434 bytes src/tm/icons/Goto24.gif | Bin 0 -> 1392 bytes src/tm/icons/Home24.gif | Bin 0 -> 1190 bytes src/tm/icons/Icon24.gif | Bin 0 -> 108 bytes src/tm/icons/Import24.gif | Bin 0 -> 473 bytes src/tm/icons/IncHeight24.gif | Bin 0 -> 904 bytes src/tm/icons/IncPalIndex24.gif | Bin 0 -> 236 bytes src/tm/icons/IncWidth24.gif | Bin 0 -> 932 bytes src/tm/icons/Line24.gif | Bin 0 -> 124 bytes src/tm/icons/Minus24.gif | Bin 0 -> 146 bytes src/tm/icons/Mirror24.gif | Bin 0 -> 156 bytes src/tm/icons/Mover24.gif | Bin 0 -> 136 bytes src/tm/icons/New24.gif | Bin 0 -> 778 bytes src/tm/icons/Open24.gif | Bin 0 -> 462 bytes src/tm/icons/Paste24.gif | Bin 0 -> 374 bytes src/tm/icons/Play24.gif | Bin 0 -> 247 bytes src/tm/icons/Plus24.gif | Bin 0 -> 156 bytes src/tm/icons/Redo24.gif | Bin 0 -> 243 bytes src/tm/icons/Rewind24.gif | Bin 0 -> 279 bytes src/tm/icons/RotateLeft24.gif | Bin 0 -> 148 bytes src/tm/icons/RotateRight24.gif | Bin 0 -> 148 bytes src/tm/icons/RowDelete24.gif | Bin 0 -> 248 bytes src/tm/icons/RowInsertAfter24.gif | Bin 0 -> 239 bytes src/tm/icons/Save24.gif | Bin 0 -> 266 bytes src/tm/icons/SaveAll24.gif | Bin 0 -> 334 bytes src/tm/icons/SaveAs24.gif | Bin 0 -> 348 bytes src/tm/icons/Selection24.gif | Bin 0 -> 145 bytes src/tm/icons/ShiftDown24.gif | Bin 0 -> 159 bytes src/tm/icons/ShiftLeft24.gif | Bin 0 -> 158 bytes src/tm/icons/ShiftRight24.gif | Bin 0 -> 159 bytes src/tm/icons/ShiftUp24.gif | Bin 0 -> 158 bytes src/tm/icons/StepBack24.gif | Bin 0 -> 281 bytes src/tm/icons/StepForward24.gif | Bin 0 -> 279 bytes src/tm/icons/Swap24.gif | Bin 0 -> 138 bytes src/tm/icons/TMIcon.gif | Bin 0 -> 1504 bytes src/tm/icons/Undo24.gif | Bin 0 -> 239 bytes src/tm/icons/Up24.gif | Bin 0 -> 429 bytes src/tm/icons/Zoom24.gif | Bin 0 -> 485 bytes src/tm/icons/ZoomCursor24.gif | Bin 0 -> 950 bytes src/tm/icons/ZoomIn24.gif | Bin 0 -> 484 bytes src/tm/icons/ZoomOut24.gif | Bin 0 -> 477 bytes src/tm/modaldialog/TMAddToTreeDialog.java | 195 + src/tm/modaldialog/TMBlockSizeDialog.java | 135 + src/tm/modaldialog/TMCanvasSizeDialog.java | 135 + src/tm/modaldialog/TMCustomCodecDialog.java | 196 + src/tm/modaldialog/TMGoToDialog.java | 197 + .../TMImportInternalPaletteDialog.java | 186 + src/tm/modaldialog/TMModalDialog.java | 203 + src/tm/modaldialog/TMNewFileDialog.java | 101 + src/tm/modaldialog/TMNewFolderDialog.java | 106 + src/tm/modaldialog/TMNewPaletteDialog.java | 156 + src/tm/modaldialog/TMOrganizeTreeDialog.java | 362 ++ src/tm/modaldialog/TMPaletteSizeDialog.java | 101 + src/tm/modaldialog/TMStretchDialog.java | 135 + src/tm/osbaldeston/image/BMP.java | 500 ++ .../osbaldeston/io/PCBinaryInputStream.java | 69 + .../osbaldeston/io/PCBinaryOutputStream.java | 75 + src/tm/reversibleaction/ReversibleAction.java | 80 + .../ReversibleActionsSelectionAction.java | 137 + .../ReversibleAddBookmarkAction.java | 53 + .../ReversibleApplySelectionAction.java | 47 + .../ReversibleClearAction.java | 56 + .../reversibleaction/ReversibleCutAction.java | 56 + .../ReversibleMoveSelectionAction.java | 58 + .../ReversibleNewSelectionAction.java | 56 + .../ReversiblePaletteEditAction.java | 59 + .../ReversiblePasteSelectionAction.java | 42 + .../ReversibleStretchAction.java | 63 + .../ReversibleTileModifyAction.java | 86 + src/tm/splash.gif | Bin 0 -> 127897 bytes src/tm/threads/FileLoaderThread.java | 90 + src/tm/threads/FileSaverThread.java | 83 + src/tm/threads/ProgressThread.java | 23 + src/tm/tilecodecs/CompositeTileCodec.java | 102 + src/tm/tilecodecs/DirectColorTileCodec.java | 257 + src/tm/tilecodecs/LinearTileCodec.java | 166 + src/tm/tilecodecs/PlanarTileCodec.java | 126 + src/tm/tilecodecs/TileCodec.java | 150 + src/tm/tilecodecs/_3BPPLinearTileCodec.java | 70 + src/tm/treenodes/BookmarkItemNode.java | 256 + src/tm/treenodes/FolderNode.java | 86 + src/tm/treenodes/PaletteItemNode.java | 135 + src/tm/treenodes/TMTreeNode.java | 95 + src/tm/treenodes/TMTreeNodeTransferable.java | 59 + src/tm/treenodes/TMTreeNodeTree.java | 128 + src/tm/ui/ProgressDialog.java | 95 + src/tm/ui/TMAboutDialog.java | 37 + src/tm/ui/TMBitmapFilters.java | 137 + src/tm/ui/TMPalettePane.java | 444 ++ src/tm/ui/TMPaletteVizualiser.java | 192 + src/tm/ui/TMSplashScreen.java | 83 + src/tm/ui/TMStatusBar.java | 224 + src/tm/ui/TMUI.java | 4833 +++++++++++++++++ src/tm/ui/TMView.java | 983 ++++ src/tm/ui/ViewKeyListener.java | 130 + src/tm/utils/BrowserControl.java | 127 + src/tm/utils/DecimalNumberVerifier.java | 29 + src/tm/utils/HexStringConverter.java | 90 + src/tm/utils/HexadecimalNumberVerifier.java | 27 + src/tm/utils/XMLParser.java | 91 + src/tm/utils/Xlator.java | 69 + src/tm/utils/mxScrollableDesktop.java | 48 + tmspec.dtd | 85 + tmspec.xml | 235 + 173 files changed, 24901 insertions(+) create mode 100644 .gitignore create mode 100644 META-INF/MANIFEST.MF create mode 100644 TileMolester.iml create mode 100644 TileMolester.jar create mode 100644 languages/language.properties create mode 100644 languages/language_en_US.properties create mode 100644 languages/language_it_IT.properties create mode 100644 languages/language_no_NO.properties create mode 100644 languages/language_sp_LA.properties create mode 100644 languages/language_template create mode 100644 resources/tmres.dtd create mode 100644 settings.dtd create mode 100644 settings.xml create mode 100644 src/TileMolester.java create mode 100644 src/tm/FileImage.java create mode 100644 src/tm/TMBitmapExporter.java create mode 100644 src/tm/TMBitmapImporter.java create mode 100644 src/tm/TMFileResources.java create mode 100644 src/tm/TMPalette.java create mode 100644 src/tm/TMSpecReader.java create mode 100644 src/tm/canvases/TMEditorCanvas.java create mode 100644 src/tm/canvases/TMPixelCanvas.java create mode 100644 src/tm/canvases/TMSelectionCanvas.java create mode 100644 src/tm/canvases/TMTileCanvas.java create mode 100644 src/tm/colorcodecs/ColorCodec.java create mode 100644 src/tm/colorcodecs/DirectColorCodec.java create mode 100644 src/tm/colorcodecs/IndexedColorCodec.java create mode 100644 src/tm/filelistener/GameBoyAdvanceFileListener.java create mode 100644 src/tm/filelistener/GameBoyFileListener.java create mode 100644 src/tm/filelistener/INESFileListener.java create mode 100644 src/tm/filelistener/SegaGenesisFileListener.java create mode 100644 src/tm/filelistener/SegaMasterSystemFileListener.java create mode 100644 src/tm/filelistener/TMFileListener.java create mode 100644 src/tm/fileselection/TMApprovedFileOpenChooser.java create mode 100644 src/tm/fileselection/TMApprovedFileSaveChooser.java create mode 100644 src/tm/fileselection/TMFileFilter.java create mode 100644 src/tm/fileselection/TMPaletteFileFilter.java create mode 100644 src/tm/fileselection/TMTileCodecFileFilter.java create mode 100644 src/tm/gfxlibs/BMPLoader.java create mode 100644 src/tm/gfxlibs/BMPReader.java create mode 100644 src/tm/gfxlibs/GIFOutputStream.java create mode 100644 src/tm/gfxlibs/ImageEncoder.java create mode 100644 src/tm/gfxlibs/PCXEncoder.java create mode 100644 src/tm/gfxlibs/PCXReader.java create mode 100644 src/tm/gfxlibs/PngEncoder.java create mode 100644 src/tm/gfxlibs/Quantize.java create mode 100644 src/tm/icons/Add24.gif create mode 100644 src/tm/icons/Back24.gif create mode 100644 src/tm/icons/Bookmarks24.gif create mode 100644 src/tm/icons/Brush24.gif create mode 100644 src/tm/icons/BrushCursor24.gif create mode 100644 src/tm/icons/ColorReplacer24.gif create mode 100644 src/tm/icons/ColumnDelete24.gif create mode 100644 src/tm/icons/ColumnInsertAfter24.gif create mode 100644 src/tm/icons/Copy24.gif create mode 100644 src/tm/icons/Cut24.gif create mode 100644 src/tm/icons/DecHeight24.gif create mode 100644 src/tm/icons/DecPalIndex24.gif create mode 100644 src/tm/icons/DecWidth24.gif create mode 100644 src/tm/icons/Delete24.gif create mode 100644 src/tm/icons/Down24.gif create mode 100644 src/tm/icons/Dropper24.gif create mode 100644 src/tm/icons/DropperCursor24.gif create mode 100644 src/tm/icons/End24.gif create mode 100644 src/tm/icons/Export24.gif create mode 100644 src/tm/icons/FastForward24.gif create mode 100644 src/tm/icons/Fill24.gif create mode 100644 src/tm/icons/FillCursor24.gif create mode 100644 src/tm/icons/Flip24.gif create mode 100644 src/tm/icons/Forward24.gif create mode 100644 src/tm/icons/Goto24.gif create mode 100644 src/tm/icons/Home24.gif create mode 100644 src/tm/icons/Icon24.gif create mode 100644 src/tm/icons/Import24.gif create mode 100644 src/tm/icons/IncHeight24.gif create mode 100644 src/tm/icons/IncPalIndex24.gif create mode 100644 src/tm/icons/IncWidth24.gif create mode 100644 src/tm/icons/Line24.gif create mode 100644 src/tm/icons/Minus24.gif create mode 100644 src/tm/icons/Mirror24.gif create mode 100644 src/tm/icons/Mover24.gif create mode 100644 src/tm/icons/New24.gif create mode 100644 src/tm/icons/Open24.gif create mode 100644 src/tm/icons/Paste24.gif create mode 100644 src/tm/icons/Play24.gif create mode 100644 src/tm/icons/Plus24.gif create mode 100644 src/tm/icons/Redo24.gif create mode 100644 src/tm/icons/Rewind24.gif create mode 100644 src/tm/icons/RotateLeft24.gif create mode 100644 src/tm/icons/RotateRight24.gif create mode 100644 src/tm/icons/RowDelete24.gif create mode 100644 src/tm/icons/RowInsertAfter24.gif create mode 100644 src/tm/icons/Save24.gif create mode 100644 src/tm/icons/SaveAll24.gif create mode 100644 src/tm/icons/SaveAs24.gif create mode 100644 src/tm/icons/Selection24.gif create mode 100644 src/tm/icons/ShiftDown24.gif create mode 100644 src/tm/icons/ShiftLeft24.gif create mode 100644 src/tm/icons/ShiftRight24.gif create mode 100644 src/tm/icons/ShiftUp24.gif create mode 100644 src/tm/icons/StepBack24.gif create mode 100644 src/tm/icons/StepForward24.gif create mode 100644 src/tm/icons/Swap24.gif create mode 100644 src/tm/icons/TMIcon.gif create mode 100644 src/tm/icons/Undo24.gif create mode 100644 src/tm/icons/Up24.gif create mode 100644 src/tm/icons/Zoom24.gif create mode 100644 src/tm/icons/ZoomCursor24.gif create mode 100644 src/tm/icons/ZoomIn24.gif create mode 100644 src/tm/icons/ZoomOut24.gif create mode 100644 src/tm/modaldialog/TMAddToTreeDialog.java create mode 100644 src/tm/modaldialog/TMBlockSizeDialog.java create mode 100644 src/tm/modaldialog/TMCanvasSizeDialog.java create mode 100644 src/tm/modaldialog/TMCustomCodecDialog.java create mode 100644 src/tm/modaldialog/TMGoToDialog.java create mode 100644 src/tm/modaldialog/TMImportInternalPaletteDialog.java create mode 100644 src/tm/modaldialog/TMModalDialog.java create mode 100644 src/tm/modaldialog/TMNewFileDialog.java create mode 100644 src/tm/modaldialog/TMNewFolderDialog.java create mode 100644 src/tm/modaldialog/TMNewPaletteDialog.java create mode 100644 src/tm/modaldialog/TMOrganizeTreeDialog.java create mode 100644 src/tm/modaldialog/TMPaletteSizeDialog.java create mode 100644 src/tm/modaldialog/TMStretchDialog.java create mode 100644 src/tm/osbaldeston/image/BMP.java create mode 100644 src/tm/osbaldeston/io/PCBinaryInputStream.java create mode 100644 src/tm/osbaldeston/io/PCBinaryOutputStream.java create mode 100644 src/tm/reversibleaction/ReversibleAction.java create mode 100644 src/tm/reversibleaction/ReversibleActionsSelectionAction.java create mode 100644 src/tm/reversibleaction/ReversibleAddBookmarkAction.java create mode 100644 src/tm/reversibleaction/ReversibleApplySelectionAction.java create mode 100644 src/tm/reversibleaction/ReversibleClearAction.java create mode 100644 src/tm/reversibleaction/ReversibleCutAction.java create mode 100644 src/tm/reversibleaction/ReversibleMoveSelectionAction.java create mode 100644 src/tm/reversibleaction/ReversibleNewSelectionAction.java create mode 100644 src/tm/reversibleaction/ReversiblePaletteEditAction.java create mode 100644 src/tm/reversibleaction/ReversiblePasteSelectionAction.java create mode 100644 src/tm/reversibleaction/ReversibleStretchAction.java create mode 100644 src/tm/reversibleaction/ReversibleTileModifyAction.java create mode 100644 src/tm/splash.gif create mode 100644 src/tm/threads/FileLoaderThread.java create mode 100644 src/tm/threads/FileSaverThread.java create mode 100644 src/tm/threads/ProgressThread.java create mode 100644 src/tm/tilecodecs/CompositeTileCodec.java create mode 100644 src/tm/tilecodecs/DirectColorTileCodec.java create mode 100644 src/tm/tilecodecs/LinearTileCodec.java create mode 100644 src/tm/tilecodecs/PlanarTileCodec.java create mode 100644 src/tm/tilecodecs/TileCodec.java create mode 100644 src/tm/tilecodecs/_3BPPLinearTileCodec.java create mode 100644 src/tm/treenodes/BookmarkItemNode.java create mode 100644 src/tm/treenodes/FolderNode.java create mode 100644 src/tm/treenodes/PaletteItemNode.java create mode 100644 src/tm/treenodes/TMTreeNode.java create mode 100644 src/tm/treenodes/TMTreeNodeTransferable.java create mode 100644 src/tm/treenodes/TMTreeNodeTree.java create mode 100644 src/tm/ui/ProgressDialog.java create mode 100644 src/tm/ui/TMAboutDialog.java create mode 100644 src/tm/ui/TMBitmapFilters.java create mode 100644 src/tm/ui/TMPalettePane.java create mode 100644 src/tm/ui/TMPaletteVizualiser.java create mode 100644 src/tm/ui/TMSplashScreen.java create mode 100644 src/tm/ui/TMStatusBar.java create mode 100644 src/tm/ui/TMUI.java create mode 100644 src/tm/ui/TMView.java create mode 100644 src/tm/ui/ViewKeyListener.java create mode 100644 src/tm/utils/BrowserControl.java create mode 100644 src/tm/utils/DecimalNumberVerifier.java create mode 100644 src/tm/utils/HexStringConverter.java create mode 100644 src/tm/utils/HexadecimalNumberVerifier.java create mode 100644 src/tm/utils/XMLParser.java create mode 100644 src/tm/utils/Xlator.java create mode 100644 src/tm/utils/mxScrollableDesktop.java create mode 100644 tmspec.dtd create mode 100644 tmspec.xml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bb4dca6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +build +dist +compile.sh +.vscode \ No newline at end of file diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF new file mode 100644 index 0000000..1db7929 --- /dev/null +++ b/META-INF/MANIFEST.MF @@ -0,0 +1,4 @@ +Manifest-Version: 1.0 +Class-Path: . +Main-Class: TileMolester + diff --git a/TileMolester.iml b/TileMolester.iml new file mode 100644 index 0000000..1a05e40 --- /dev/null +++ b/TileMolester.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/TileMolester.jar b/TileMolester.jar new file mode 100644 index 0000000000000000000000000000000000000000..998932b3a0d54db9fc9dd35b3c8e2f3742348046 GIT binary patch literal 466046 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%0D@(f;UOwjazY>C8g`Q%wW+31q`Z{m(@LdOsd zOP~1{-{ShnVeG^FfdBA8KTgxdDM!yn^5yn!-UG1$7V$-levwQ{SVU<&Yyw?0!*lt^ zKikU0F-2rtJxPmC8=g1Q@hJ=@pQ!XjJa`<3{J>t}yJ7HOL&N^P8fgU6<`rYUl+1SF z9B3{>?%AzQ)@Lw4twxkG)Y8+P)PvY1g1XCe>3y}>H!iX#4dLCot|o89*^ z&)*C)pb7hzH<0r)o-OXL3oc30>AZQ-Xuc2`Ubn1(S5Bd#xjDE$JPERQ!wvDTA;9lP zH~Ruep9w$`2`a&cv$YPqg@RSTl~M)caeps;nXZ=oR3v1f>-UTE@2iLM5{U&TGksqj z+q4VnRNr34xGJwvN*~`GmC#LER)0(!!&y-sccw5RrnsSWtYGVRDsdDFjO&lU-Xy=> z|5#8)2auduFbMlwxs%9)bd9$SOup9CE*&^F;7#>cjzP&E)#Ar6-)IST7PW>hOUXrknI* zQ`jOU+AWMlF8u@ z_BxXCK^KMP?3&U`&W8*16VUSq42aesp!vY(4g4(D3G1ZnN3*LaM#0w4XcmeqvOj(nIG~|GwJmDN{X=V5?87!7`-m@=xOB*Ouv2F=BmU~d6@J0jx zEfQ>M0?E75+v)}90oNGy^G(*AJ~FWt1#Qq>ZsMIPAYHBu*Ci1xBW?2gdXXZRf1$a_ zG5fH~bd&f3Huim}yr$x&-0K5InR0`i{<@S@N*9ulL85;;ei^!XxxMx{8uD|WF=#BXZ&(BT~yK5eGCV2a;hC zE0*(#@?i!dIRP3wCgkvw>8e!6m=qyzJE%yw1}5S8xgYewg&}TC0$36b{ru{9QF(|1 z;Pr|bqE-aFl!Anr1WB{%H4&326ZLWdC+0K!OQFiGO7B^h2y$qO5m^Wq_fe{RI^l`; zTye`f1LkN`S`~q*8Tce2b^TB`D)cfL)WEw~GgOnv7rUNzB;!W@ zs-)J)s9~V}1H1Hgp{@{zckRuR?Np25P4usw%VeGKD&ZTu7^##1v8v^AC^HPqINYFw ztH*m6cF-iH7EOBlHS9?ddKB3Eiek6H(tSKuE9Qh>F}qL;n;#9 z*jPzyl`@PbD|^VYoS>0XPhv4sV;ikyI)v)UA*nDc3q5dxWV!&1A~p%EUFIX$p<;)G z59(^_2Zc+QB0S9s)+82&T73<<7qQ>qX+8)z1}*a)g%+9myCwlbk4}VdXq!)xkF{?o z*6%Iuf4TZ=!`sZF?ou}&xcuY;weJ_n<@F?S51U#z@gQ>{MIpmfI(9sac4>ji*bY&| zxPg|Y2R%4=n*y)iX(^dLV&u$P2&_Lc4B+b9t1Xqz&Jpi)&HS~tShC4Od_0BqDScPD zlNN8`vx8yzRR1G$vSj_whN%(_jkhnE&o4BepqWqc?*lX#B+d#A%K{3qa1-6gE{ROX zjwin%3*rHy$q4@8zV%_qYS&kAmdxI;p(I5j1&a3 zcRF|Th{P9v5OO}$HG+(yd4|~sHS;ut^jI9`GD@EN8c$>knyN_!At(`@x+#VJJ+$dJ z%Al=9Xq1|m{+^8ZH6A@OYp52&dR~B28!~D{4;{yiLE$kix)M(^rVZyqzA(xFF>0?) z^R`O{GCgt&)T)Xjx-{nJ=#M4IBEhpkLupoq#V<3Oa}RN9GZK4Wi6xXhJadn$Mx4*7 zh%`ErTZBdFK4y0cCZez@eY%5`=Q0cDTArCe3$rXHO>asHbq16VTxtRvr5L=X9}Gxy zFdXU1s$Td2F6Pi7G?$<)%8D_ND-aq#=fh@Ta`wFkr|kLq zR{n?Kx+Q$DSJZ>zwnOCu+oJGbGyAZTq!0Gq=>bLaJp_YCj?<(O=80qkFen)JkuZC? z=LK4mj0hcI3^3QjZNRl|Nc+^n%~&En{B;!a9X;4T*)vDjRngmRPPt5T6{KhkDtNv6 zFh8}xu#X&d?>1{i+a)sw&LVxw4kbtbq3CfnFqEWcPA)_J=c=%5KCB7o<6GM57)DkzDP6fsS7)gdrkC>?W+zH82tb$fqnQ4;x3$pT>U~1=Sdf*(Yg^(|KT)-^pI3m#sq)9GH za6I0nTVq`a`PLePq^TQg`}u%NY^Xh+q%W&yf|Y*r(2VPGe^-MU(9d?dOLAUmCYP9V zsfM#eQYzm>Rr!E(I=6KEF6v0mp=x(cbGv0#K+c({(6Q=5OamJ`n!YOP zvqWwp(>`a)ADhwCyITO3N;q_Ak=xa=;`HJ~3#=R3qu~>Z887L?vbLDArJCMl15CR- z-Y}m)W&P@m6tuIY#7_iNeQJN%P(n7~gRx_oX(jOh6PtpvBbC?Sq+?>?(7gD{66d4} z6L-S&>NzR35K^;?C2hN)wq7dC8yu7Koch}(}elu;XUqAmfn zw=9}ip4kSpHn~q=*y?bcgtikgscFVEVOn$cj!N`XPLNxRWl{T*dp86EcqGp-1<3&( zuy<7T&iGf>0VdIRFuQy&(F0aU={hxREEX3of(oFDG;6ucm11I3>_Cgiz}5ulh^=Q< zzD?eardi_$@x3LcH)lCuKXX=%V}rtWZEq#wy-v-phhDbFVzV zqztutSjVy4Vy-k2w({g>li{TI_w4Y7?nqC&Paei;%rzn_CbZ&QO)IDr)(jAH#E~i~ zafWzEfbllJ2|Xh!I1S|=u!s9Z%_8}^7z=F`v)CgRpMfnYu}^CdA2rz3RmbO(R8=^7 zt@OxPHT}kpL6|jIDw^Q9+7k!)_4-hXW!mBZ2^Fg<_iq$|7Rq67CACkeV-@J>#XhNl zZQ%CRn~_vM|H$uj47g`JLKDJ)iE8lTSm8g+MdkI71?O<7YX}CLeJhjmkr#K0i)LIHw^ha!=PD#uW`K-)lB%SK3rB%-WM{ ztDq{!$&u^8R_ZI=^eYv>u4!djKWVysX`9!`tO>y_vP*8`px*cMM4V9{nI=dmYLJt; zcw*uWC-{h(xvFQCT1=V)whGj*UNpW|9p71Irf{mpdi8AeDr{#bbu1Z>7!w~uO?m3m1>@FVPTVf7 zB15=j1(r4K1$fGaB{$rpdEqscQYzj`TGy$A@L1qeM?^1`I%fAc5pwfM;4C?b02j{0bJ)epo(ULB>ycJf*r0v6bMO@I{2>|bJBtaJI)m7-{ej+Xmji(6?;;HR}j z8$!)GMcA^{0dQ1yPTus=A~Uub$NH-s+n#UI5i=ZuB^0AxqH0!TM79stVLNR?(B}P zh9TPpzI;}ty?9-v*jz|9yo>Z0e_gl7#~!Io6vkk+uanb~f-kxn9@RjErHUMQeHnjH zRf45xkrTh+aQsg+GyOth%{sPuiv_!BaKnI6$w8D1HOn4L((2Zxr1r(kzPU^30>Ek7 zuEfY(VNCK>CrR%X<>Dgjk=mj?*WhWMInX!nV{=G6_O~J`iGYBZ-s;^|Vc+lfrI>j@ z54;UYl`}P#4rs)&jjcD!G~5LV>tXs1kd0qg^Y_nP>9mrKpV@XSQ9OL`74gdE8Yfe$ z0CtTvX-rw|$j67(KF6X*FslWeB9VGhxbf`#-oWG3fY%H=if<)lZCoBq$n{bXls)r~9ShQ0T28@Q z3D;O>%&3PcX*txxsw%so3VXzhD>1Rp@F$WN6!OVliDEXd*Fzs&Et$}bC>1&Kzz;62 z4T86E&nq5^NNINzMR>i>(5|CdBoAAl*=QmGo-p^*hTrO-rC7g#-|}8LNk0G!sI7VK zoW)sSr4oD%;EDohS{bc4G&Nc7W?%}LYza>uTn|mfU94MS)tUFS)3~EKj|Dl85a=gq zIDHUyqjSj$J|EFcqCBY-4+?WjUE)Qi-R6;R%iylwsV~wO$BE)a4SDC88KF*-xmX`n zs%Kc|`}z?ePf`yHG>ST9j*c=9;<6nOiaCO!6R)Q%x{f2C`Je6ul*A7#t?{p!zuj5# zJE7&bU`n419L>VaBc&RAR7!1>-Lc4PZJb0N?P9#*+)t+DQa?E#=5)GE=RSu!wNC5` zhdbx6S6Fx-sbfCi40(W8qUkYKaaUX@xyc>YX#*z znfk>>E>3c!JA(R{!WxG4(F&F^x33q+157@On%~!*4LaI*9~)h{Xv<*T`4&C)r3vbD zPFMN8+^eW{j?-$uZLO5zNNA&WYv}WVrPd2rcID>s!>#nGMv=Ga{U-+WbwN2O?w+ST z+S#yyrYKircyYEJeWV~8$VFeo*m)H@9ctC~(UnedG;*{`n9_!5ce;}YT_vA|(`Y|P zzBPtEq+6YLh<`jFLPHeQ2aa^5N+A7$)ZE+Jpu}sv-zAEZ(&kUT*aq9J9c(GXvl$nx z3h$<;cM5Ieft2TjmAc}Ayn&Sxn|Zm^!JnUJ;4L{*6;+QXuj0aA51XM}z}`{VGpD$- zqrSqR0FJ8^ZrKRI3|=!`rYy#LVXZ z_Uy2q{Iu3)whue^Q(5L$r}=)>8n*)@n`aBlSbZFoKn&pz>n1zc2Zqan&p`l&rDf61 z;0M#@Glvv2PA>XjpP~(?czEPc@rY}NGP=xk$zZ%=;SExz4X1z#`qT``o?C05YbXvt zyPzm?=|pW0+I__}o|}F%=PL5aH2TKI>2cWoaXK|2eez0C{fLrkUFdjZqUYqD-UwRh z@f+$2ha-W3a_$^v-NSo$LY9mX7mr#-Tn^FclKST?_5O%*9BvK~PtMW2bw?oS7%;Zv zs|-0}X}!;K;#mIOyO9PN&)LFiEToEc+*)k#CXb87f!m73J?~k)wcK5u+*?jV;aet( z;l=z8C~4yHi$oI#^)ShV2dCDE>&2gc+_9JYO{wQ!^9_Ph|H&x%Uz=0^FSBj3X0Aq- z|BG=h$wO9g345q3*h9}vQ|}wHQ;&)l6>1<+B*q?L7#Rj1*fT&0RaKYpJZ?j%{~rA& zHf6a`%4@#Av5`EqfnMEj{yuhbQdO#GPI}FUeXff=)3MO!VJaVR|HkojNmFjhJ{R$l z*>?0k$(DWBv31wB{<1$f^^G$uM^iDE1vK1FmOnc{patp!0mkDx!%wao$bg3Pxt+)p zA5^D5nP_JWp_5?84V{%hkGEG2HtHZ3ZHPD{CIB`6O$eNnxILl482a9a;ki~fBd(}Q z{8^nwyJzX(1XInzm~>XVrwpN!{G%w8nVmw$#4xz-)=|2*i74Y~n;BMHW!M5b02V}_ zgWu{#`e%b!kG(qpL;yR}E^u7c;y2}R4#v+qVx(wt!}Aj5;jsFqpb5(PVHEyG)hrArQeQ?!tAV@Hr-(0E6N9@We6VqpW2 z-zINaB$QvuGGT<;>wBma2hR!--tcm&qFP3KT%%!MzFXTnkB2%1t?n@lOMa{;@W$e< zxg(G>$9B>wV3k>eg#v^$&K}@185JQy0~<_htFfXrT!Ag9P$Gy?0Q&KPkk5_1ZB&@+H7CDMQQCvY$eQXo6rsl#HQ|vHsKxY^5 zWE#-;eSjd{Wn=+5D+9FDMhxMk4;;?6_PX%eaC-=P^9Vc_Ft^I%R_B8@paAVVIsfa0ST>vjB3!Nx}d%=?u~k`8>Tv{SP#vyFUUH)NQ!4hxDRO zf~BOhC#+XP%g=1rOV5T|f;ko0dQ1&8A1}h=eW(hH+=B}h6iIP3i z)#FQ;-~mMJnO?x^_u}dY@QzjH5^EXAM|X2uZ}!V26=jUepR3G|?KDsGWR%J<5r3J> zqxyY0kG(D%)zw{z#;5iZm5d(B1C8AiAT=;$Lc)+Xch&#da5v>)K$hy>+R804tKR%=Pa+X#v3JyQSN026R+f zZ(q#Mht1Czkc~qbUp#US#aZrscEz-4T9hp`d+azW1Dh;{CI(&?E@SQb-eSFgg&G!v zM=XaxJsK!dK1!$`Wp?N$J#24P z-+>%LOOZ*3wqxH_!*o>R$|4^%SPc@a1`Ez8RT}Jxhnq{QER@z8FS{77iG(*r;c0vJ zj7Oq)9P~}T>)Mmp86azJYc_njWbipxvqZXm{0_Qm7x;*-$pQW&v?6w-cVEY(0PY0t zA>v~skG7zV-y+?E+kqP+vgnHuHX%aeHK}!D8oEdEDcmN~laxmuGQZok6{UKmc3H$B z#Q$;{#NSW%b3REYCcJ%=;lEvKqLx!cszy&Zu9RbpuT<|{yPP3fsq$kl7*6tF9g(N* z3APZqeQ%S-y}J23c-i^BXnMTM9=z%(&&3|WkINwOHwD6xfbjWSTimaAOtbR+13tm4 zuOG3i!~@@m4f>K+^VSW`gD1|71d?YgPu=q6p~4FFwa^u!yyjKcgza;t99^@k6kkI$ zm%mq9T9NVk?|bU|K6w=_T(ZHhC zFW=<_vRw(S6XU6oJ7CJXgS57hWhK{sl%@t8OEPU`hC9Yb+s}2_8^*Q=Q#DI3m{ywj zHF@ITEd0KWW)7}9Aofj0{i`Mcb&5q@s2==)MM(&QN9bevVSYtGUO0{ATN{6kd`FIY z2Oi=bC$yCt&tDLKtu&&qF!Fp&Z}Q+P`aDcyukTsZAs8{abO9wy`~ zKP*cS{B(}2FA=mq$r2~EPQuC5VPKHA`u3&n|2 zj=#9~(Eo>K(qnvRnj7mTWLa-9Sl&h|*G-h_w~@E>VEAI#IMDyau;GvHbx{J+0B5e( zGSQ+md@KK=nPS5(xV~tncQX}|yDGqU^uLm=r(ZNv^*=O|PdoiT44WEpWggNl9U1W# z!xm`fU-B=8jor845s-m+Y5Ct7w)qzaharppF+c0;vN@@LFl9+dr|Js7Ch;S0XSveG zKP{raMt%)9072JUo6e{Blx#Rx_Z>r)k(aa5yJ-t$Lv<66g-R@L^cDml1s>b25o^YO zY$GaH#-v);U$ACjTj{To*eU82)fqxgxYlADYy z1xH7=B`7ljo=8R;@2|(biD&RHaJ!|fBsw~A}uCjF4Ro32nj^nqn`gsQ`X*V8^Hm>wq-BAOq5g6rt`ds8YmMh;MEqh5Zl`BK@x<)G%4A5def#gGkJM&h?)|g%)?LgAsGB?2j~zo&kPQi0|0HlV+b=qpbdXJl$j$C7mIfgDpSdg( zZ>3Up6Pjt_FfN;{T64+s1#syzJO+^V%lc-K-z08pr@jYmo1EP=WX0vylzNLj&V2!k z`ZCjsU%+BVjK@E~qUgpm=3f5CE8IT>n5UY02tFGg0udVLm z3$LrJ5_wz?$X-o%%HW2&@wkdWTyKFv2vKi|!9}8Kq+3HI0;F5Tx@|lodg?vn{0_Ds zpk5;0I-xm`yNNGJ4}7#_%cEaSvN;J6=e(^)*q09tgx>J%;XTt)n;3yFMBS+UF|Cqj z&#!8ep`VGPfAV`YJzK(CRR>dm7i^B+9kAksZUUZe;V+TlHIbNTx2#C|7`JemPqL?Y z5BqZbS4s@;;O)xL<*I%BsonJ*)bm9KHb*lu@HPZy%q+EuG3=5Zh5gaZGWx<~UA#rZ z18{g3%@S^D94BkpVu8U+ga^Oeb`rcE0p6)utgoOhqBP!ho_&; zW?((Y>l-|N#QbadioctR-jy+~PS$^6pPj7LXJPZhX=wuo`7_5Ft*M!hC_L|=YUq_CdPsTZ3B_N|mJLK{&<|wA3TX%GxM^=YcXQhR*3hM@SogUO~{aWN*U?tQ&{Fn+Q zVPBwaUp(atkph{D3r?!(>qm?Ta0azqNoV=Wf8)@LBgAdDy5m&5Bn2r?=6RdGwG(O zXj@TV_D>o3w3nn52mlNmQc!%NCQz=LxICb2F;^IqWU^|GskqiyW!v9sPOz&}IJ7MK ztU^xh`$%D+XzCo`v1w_3Z!sZ_&zcy5scC7D4mi!y*ez*r1V_;pI<|#$nC`8&_V)7< zU5OSDgwY>Bdp*WKvqnB~D}(~#5wyQ^LrPzY*+&p=T#-u_5^oW&fuCE8+Qv$d_i1{G}`;NAmiZ=u4+~T)Wm! z|D`&Wd)=TnU4?O1%nPlPID;(0jDY%XtjOshmB_+xZevIGct~R%G7dHTw&(0tyiDjn zW1(v$L0{DM#p{M@fxAjP`2^8jS4BYlDj}max4%@obAiE|VOY#rU?ss^-$GX zfaO>eFE6OQ>-?OUseZIh&q5X{ve!ryGMsublzL7Ghr2B64#?B3nsW;uFk*P`Sw$4} zvohZuL7#Y>a*qvF0{mQ;`x^BG7A9uagnH_#R=P*n%yH9{q(8bhDI;#KfHxPn*z4y= znH4@AjnapmW>Fr8zkqKH;JC^cC*~=Qj#kS^{pue$tsJ!nMxSCv%1S#D;fZc_sJxnG zVXgXS=;}`Z4N2vh&=cXN=q6UqUU3|u?b{nXV!#c?0*t4Vm`m1+uH4hs?`}?$kL6n` z8n@z=M_k#GGA+jLIod-#gD&gcH+>Ww?-_V*?^F>&;Rm9<;0LJtG1S9$F_7X76+|q& zpX}(=IdT9ukyW>j(r!qQi-bxVMwc+RLi1R47!lQO@VXb>BcsmhtCE%_XQq2=t zkei~bEtAF8eyM^)p*g3XDE+bY4VP-!EXd0F0$A#u&oi^xMufBTlAu_5N8;TqpG?jJ z)pMDmXOd4m3|y&>Jgzsnn^=#A*MQ$48DlZ z#ZsiQ3%mGPR!`JU5VjGoE_x{dKfgu^a9dgI$_CDKUf!b!wF67T-?r42HCj(gew7Uu-6`6?f}{m!(>s=j;e zXC!uK|F2If>r?B>Y`!6j!VK_!Lm7oZGG>o zT`g_qoN2D!;3}9E>z^JLpB_hrCN8pQSiLtdxM&<~s(tO>iP=qk=+CZimVTqTHUF{C^RwnFWk zB_&irjBaufYm&UNw}@*Jlr>GV&R7|B0D7_zB!MLn1Q?4~ezP2{{YR}G!=|Wnltd*j z<7LERitqbxWZ(-1`+e6(1RO z{4GViLOkd(F2X(I)-Ne3?`A*}@cw(i75rS7r`P zE6*8jU=uQxs}COk6hU$IsW~PK!8#1l#_h(I*4X^331aN@`NDDl&-KK*b5@n-2xn{E zRj?bXX)IaTEACq7K0>c~21HDd=xjSu(HWVH@;jsOX0-AGtwyEYfD~(>nu~xq^^a*N zs^8EMP}bUnazco!!z`~CC=@9wZIGS_o8GK^gFu#YlrcT;jXacl@+M;X=&^fJ=09NS zPP*zI81(~Nd(nS_0R|u*uqiyzoi;|l{zxYUfxQm~`@m@Rn5*#Pbeg#_PHZ0=Y8^vO zJY!_1Q38t7mET_{+hHitNe+T(NVpF+HEUS;s&1FXJnuO@8ERP&bNV7z3^KfIwzC7o zlK=8H=VUop8mEyf8mg~+BC({fCA%a4b}gE`$JW+RZeC{dvX**sT_P{vTTok3<;+x6 zRzi_sOE#hQAjzqrtbiiN8Lvmf#XSt0rtzdGS9hnOpJFR+~x(P(yFOpT-)7a02;HL-F%We$q-OpF=cx@VptnYnRwiotDz zGb@-*h%A(fZiE{^t&_!SM{8;rPYh}8qjo)8rIH(19}FuF8OZUAB|)eCg=+C<>o`2b zO6<_Fn-C>VbU?W!sK?LuyS;Q6j_8PO#Xx)(>KrH~zXIQ@Ccg?9>MX-`NVF*4fZh((#p~rTxIvD$F76pSFa_WH0XoL3cZ;_=rU&13yI9bx{&x#x7I7TT%a@_` z9`k?N9s5roz<> z9Q%zZZWF?zeO1;?A5x>DNvZ0wv}vgVLa$1#%8kvc(v}v#N$p(Gy2}cI`l(UR_BPYw z+LRrtZ*$w;ynCPj-iLX6!h73mFA)MCL_t1^c{a+vjKQ(3vAc??O=#q|P_>dn(~UK% zx40--H+9xE)N6P6g?iqO)~O!(fhQsR$Y2b#Z>|xSF9k9C=*Z;UTSB8WTq`2>1#N`TgXR5NIDFKoCp5 z!krQ-E75XD{`;L{XnZwAdgUGk2LaIn76Qea(n!)dZ<)S*s`SEFX)yUx4a!M*(h|_MmDt_qKMCZRW2lPT)3b*Q=Wjndhc=ly4IG=O_e-Ur}pkGr`U+lr` zsbAs(-5|BBDNIDtgFIQRM4%`^$>N$ceON)wWZmB1mWqNeN|9JTlCj`jg5M#&+D+Hw z=H1S{tn!1*EYv5tyc#zl;TYIRYr_Pp=2oO7U?4yKfG|WO}tT_z>+%7=op3d_& zx$OPL+b45pZQN3t?`i;`hZ_-S*dr=RodkG>uD+K<(? zD_+4mnw8f5Q_5ZW^d0)_!fH;fHT<|tLg<9s*4ios2wJSeq7R>X^8~t75>@m(h^$K@ z54s)E-}0Pcr&cEOSudG-)Y94Xnr<(5Hv?URGlGi$K8U#4jxZ6;O#<4zWT+Wekr-bv zTe*Q(u6I{19oMIe1=VV7hRpP+aCM8j`$S|2rq8EdZePQ*yMoIys?YD5${x11m!&Pk z?i^RB%agzN6L2>a{ZS2*df{K;89)Ar0ZocWvMZc6zWs z!~UX})dQl?US47Ubavv_u(0Cxhk2JehOr@tib@aXnLzoPgREo-m2akx)3|$!X|iGgWTDK>2|gBQ+?Fb!kR|ELYtfU~3JP{zoz( z#yd94P`V|WGwY~YkGibaNRB`~cXA~S*RK+D&HAcQ=OvTGd{8s-aA)%m2}108Dax&At#EhNIlP_t3s>3_9XP7P(_jR@kxL`ZNj(dtj>)%kc-G1eySz>Dq({YKyElNSUn>cb4ua&_r0Cyx7PLc`F(xO+M5Dm*&~j*Kw_KBueMI3x}W{VGz7oeU23NOC;_ipvBi zo={QMr4w{EXk*teTd_-XQMbVZb7F4!1}EDIYbP80xY+yT`TUPyV+;@SjO0lpI{qVB zL^)w_rGs4{fpIxcM{0=#VT;G$p<;?QTh15&bY;>RF}LcbmgFWkE;M1U0vlvAW??w@ zB{bpa9vDwYGLV8EG@QbG$XCi}@~UJ!b2oR-IKpJ|n1;Hzgsvm$nppp|k9KY{W zT+BG`gBsF}By*kc#9%fUPu}p#I3Z(ubKr5u1mNjfE?{gTWTt1P-@HnCZ#_-RNzv@z zyo{Da!5^r^gnlxelg;UFogR2V+S1w8ZFccWwHuHr9{!037eC#EOEUzE8wK*IM-5cM z4KYofCa`hQ2w2nz*-vx5DOn?{>?_k4$G0(@t{iCN_?~iyu~s#4z4ysbAm+gIRPRc_ z#AjL*8OV(4t=N|~$baLcs(w=x7cWF0SRj0Zx2Ib;LcMb9Yy~#g8kdxhg!%|u@Pc0$ zn_EcU;*8m_UJhtCPSs`&tjBl#P-INHr&IwtJc!{iPxrBKr$YC+lN(Xt$%F;nLKRyP znRN$QIx)cfQ07Ha-ZyB+m8mi~8!|{8uALF11H@m#*XzX(%PcJI7--?j6d0h(S6^yC zc>D^|AsQ({X`*#vsKAv;G)R`OwgqxXt3v}8MQkhZWJ-c8(I?U)Qk&q-x`Hf`CLB>1 zhq+T(;fqxn&dIhHq2K{kK{hBR@0f)@m{tS4A;;6~j(+lm7~A4NbMhP;l9zMdVmO`A zA1~++pKgqfcKt^2f+%r@GzZ*d1MRyT9P#JJ9r&vIz*-Zw?OJw(2Hg(`bz(tVLF9L( zc;YHu^=qC z@r&kfFdz3FxlrWi`FMm=b~M{@r)QhoBkYE#b)@x*-fyt+dT|~|whA#E;`REpoe}Nl z*WJVTdc87Hu1idIf|7K+Grs~&Z;~1{a!U@@qTcTfKB@y8b!T=C?#?Pj#elV(Omu^_ zH1zO1>fKhIDW>>9=dlA86-6mco_n+@3vt85#E?{K)2fWFZr_e;JsU(-oVFH8Pu@y^ zlTZ;A$j2;4*qw)ozK&{uuB$uM_eleID$}>cgIZ3RX=!+BV^3dz2IqVY(69;?FoB8^ zRx9{YO!%;3hF}r?aAQ%C169t1 zpj_@RfR28w9kXg9VmRu=(~=Ka05SkR$+v-zqwLM~{Ya_4dxu zLus9@lRM9p<#z9YaUZ%G2amJ?zJJ9~#C~KRZ(kJ%BIy6qtMvcBKk53UH4TkzEgE&K#e90Qtzz2kw0i+D z!MC?tzk3Pn!UNeMmeY~*p}~@D>kXq3Y3HP3cPoGlRAbrZ|3pv4;Cwy*M2`Qr+H!NG6l|d?5K{fqIf!K>08nj^`wEP|1|0PKEC+uLJ)El!WydjrSfJFHG z=9hFkF*pMHgDmYoy3F_KN&0Wv8db))PIOkOZj3?4bb32QL0}M3@X44~z`6RIF&+$$nd{345s{Fu(du@DAAcx*)9^8}tj8H_<1?rThuObq*-0vTSKr-CaAcGh=-dts%Y zled0*5RN2XARHN_vdR9b*<2g|j3`*H>)%r#bIO`09yQ!r%*S*knXGQ-S+=zxyO1sM zrkQfVxTFKn3Iw$kL4!b#-ivt~X^fq9W&SbUOV%$sFZubqR5Ltfk%UTm#*jORT`SA{ z8K^;GeTkSN{Q`0L6}wy&;Wiw2F!{fz(lkDoMP4|MH{mw~4~#eXV)- ze`4nU@3s?|f5(mHX6`nYM*maU$$!k6|8=6cq?o*mvxAGXvNOQc(DvW=MU}Rf_X4nq z|2|{8JH^B;Q6K-p?k8lrO+StrEFu(1ua!i+$j_fgZSfWo{bmLJi%K|EO-<8Ji)#Yy5Qa%*^ITnVdD8PDdC% zdr>*O5+e75t~fqdB!c2txW+eNL5$x7<*;*&;U9j0PLh3vAVTH_bx_nTY#Fsq=e4tF z8(dhesb8iX0Aqj`CoBNV9n&4_1@nM$mL!}xlrS8@8J8F zKDSMmUBZgBL?W_Rb8qRU=FLki3(eKqSeDhsEd3*0MzXTf^Y!U(?MthMLzcM&!;@(> z@k;SEWmt`@)>d_Nb($#CCxLfL%o0C0V3YuW6IM~|fOO=LcT?wkJ z)Mr}fIM!C$Da#^f=T?MvPR7RP<>{g5iO?V-*h@7?Rv&4TJ)mDa8r@y$q~j--r;s8+6zgB=BRi^Qu5cO;5~djI$AcF0zwnt+X`dfC0hf z>=LCftq?D_X(X<%F@=mzcr?{i=oO zD$Syof)8IGZAm)@9e!26p9H4(>9_(}AkPKwlc}M>`slugLYwg|fNNTRkuUcm+`6A^ zsxCsd^+)`hZ6iS$#&?)gG)ZNaDNnoTByx8+pqHn4wGF|Anqd13*_5a&`oU@N-fbxn z;~(a_i(u4*yBMSl3)uvkO{BQ$qm{6TkCo$KkwaW{6q!JmBXCbmP694{tHX~i7%BB4jCFV6Xa3nU!H%0;p!_4fqg z2~*SXvcxz^)tuTtcMQzE>{UqZo8zIMHsr{(7V)ny)Q}=5XrfBfG7r*puxzg*hgR$o z!lB!ASQF{MGgM^3kVWdA0#O;ffcfl<$*eo6vT{_RX(i@7^-(fuE%1Z+K|!@uB0DIz|o?m z#`ITcb7YP%>?R@}nG&89BIz=4SyP>FJ$jjm%9b z&d^#_o~8M%7BHwynF$n?K)mVRHbgdT`QaA_h|(A>_Tjgd^pQ?fCBir3x)Xu7IT%Mm zAWC*UdBO?Z*#&Fj?}joziX|-FtpVvf!|{hC)}YCVkr?}|Hq-m3t?byoG)?LaXX?$< zVuD#+J1&W^jR)iQb=tKPT6UjABfB;6ccgO4nupp;^YWjfh0Z^1gVY*3M8i%{Rq~e} z`{|g8eOd*Lg+XsE)T#11L@_pF1jhG@KUP;5F=KSUxe`&abpX+m^Kty~3v)U|5uSYo zdz|NMP88XB#d=)l_aA~YJ`=s<0oRmQe?q-_4!5pbpIM%L<^3Gy{T#3TPU7s|^gXv^ z{qiw39*DXQirG)5D_<&Z2BDZxagJzBGGw}%DXLCYTR7x1uhF}VDzqOWd<*$oFcGut z>S9#G>n5gW{5nppokL_{+eLL?+fFq-r)2d@zOIUbbL0`b%S$o8f0TkX?V0_*uo>6ZOqUb%0cqf)~BEX8lE4c7>D`Z33mb$_pdV4 z)o&Y>K}R8%y?CjaWAx0|{D#Q8uisB)LU5^T}*2YML6O*1Q)9jK1EV^ zFk`VLJorvRPXL(hZt@)eKB$!QV{tdwJKHQ@^%Bh=(twV22=&L|e3!1-s#(73O&y=v zOGhWj5YLG*g6I1ecv)`neMR@tS^NRG`BnZ}S>oP6HitRf0|dX z*t9bl7k!6u{g!QNSl7=dp1jPwx>m0k*KsDE#2Wr|uU@gPXH1}%X*WSEa0sxMoI1fw z_8Gsby?uWp?v)whf~(?HAq4sqZkFMPx7>EX(gvKl0;Om0BCoEqb&QhO*|3T!0FLr+ukaQ>vIU6nG74>i^+o7I0Ko%Ld(hz$7 z#jD*?@eN^4UM8lvSR2tQ+I~;vWz!_+cs_(z;<<3PxY8YD&05e)7yYtpcz$dQWoGN! z8cu@+0;$CzrAY~thOfYC$sVJ^w)|8wG$pGnzf3jNA?$NIk~1wKo;5rZ(Xey}U0XKp zKIXLW0kDVakX3(WOjd7&Y`|6V5K(oi7w-cYpjR?T@Z=5VtEFm^z$Nc>>xAH&4U48N zM%go_dVx(!Y{P!xuui)&(Vr0#sT=B(1YM4+F+>erkxA^_L~4T&qmBV|A?QXc-ZaGXe|&rzRn+m4GBE52MJGY-JSX38>9Xhu}(@{L*?% z*DmUdUxqEa?b(2^&3=bd?t$urx}IRz3d660EoY_DmA=b`)3{&EEL|&%Qu7N36j``b zu6GNRgf^P!cQikEAbZf}Nzy_5EH89-3$!$>351@%$t_LZJXL8p;w)`MsJ0N(UF8BY z=MiH?FbTU51-l^8V}AnFh(VTSDQt5G8Y8X>*gSt|UMQLr4kOa{fVT|yokBTyAfw99 zf>KoC3$Z>*FDS+p9!o|P9oAjjl!#6P4v%$)a2 z+lPCjDghswQ$?=B5xc01=OK*XeJIdp#Er22h|-kwL@=MCD9YzVioNM%%8CO$--K-P z8D~S4SBMKSQPCX}Y9r`jI$Cu&fGxq=I@EwcxPIa%;}k`W!idf(Mkj6zfHhMbWkk|0zRa@t)0Gh(7eRkmp3h**j&Tc9geOyLM=j$mrnNSZHl zcr(TH19k2I(zMG>6chaXhL3uGg0QD@*xqDfKFygFv=a|u^AIm#vcpJnBE!RdY1l{C z5FTNCGZ-<#M=D+PJ!kjS!0dsLL|Tp?21Gm)4y}L%hI9N*Ii1#FQf_|>H$b7La;`+( z0XZY$lVbAlYGWv&&b%Z}TXa+02^(y@vaA#?zooInV>1g3-mZ4wr(gpiY_@W-g_9v(Hw%DPJoB*?9Glu% zU(^`5nTA0&RYb@36PJw$m+gB{N$RKp4(82ot}GXA(u$x;P0Lau4&$Vw-8Bw@sj*xe zd_rwgL`CYniKySJW6lC;bhWWx`lB?dTlmaS#}E#E%0%HeMzzCmisYO=2rhn*$;;*R z6vN*A01yD<8t6e8}@VzKLOZ$M<^JDM za}Zg2ZzW4F2&P$74{&+L>TY^l()a_SWPMe${m9mAGR ztc|O1w$*t=jih^Df0e&=_sCi@L#W{D@EvC6%#_s&dGb8Z1~$Ho8TtV69l8^EjOb7N zQj(Nq21okfB}PUym&{f)R^FfohK7r^nD6O2cu}E^5DwNAxoB+|X+pbmE<;heMO!P8VVmZNe-sKyDVRmFpMwyhXlmB7^~Dq~PGc%2w) zTr!rmf6>z1JC9A>%Wxl)=O2-)fC(4)5lQp=YrJx*cwypxQUeX^M)NR>V$&ddfy#P$ zUZ<-vY!SgX6e}O;nR`%FsPZ89UP%ypmv*80M-(a4p??!c>x2MG6x#AN*zcmDvdcEb zVu#l@%?_F`?eLK@qM-~?!G?ZxU7Ed>CtTOz=h9q4h%dG;-|#@~eD-thj^&Am@8x#{x}`EP&iKP6gXmTwKFUNkic`l`7j*Zt?`7R$h0vyPZLhDkF z8nBnP=%Vl73NE*ips6`Fix|_Grv_i#I4FeI9UtxnN9vxV9&a0-p@iZG=flgl6NSIV z%l70YOz3w2UJ+x!@lp;w!KPbmTC^Hvkxs!1V8#N?RzBRGtrg03?wNaBH_=v!;Vq$$ zxOcGCehmu|UorO}IR!S~S1Y$-Qo-;^>I+EGek#R6ydH~elBLqbymOsEL%8T(ss>eT zQTEm-Kzv#XyE&;r+clC~W7~Rn0cx~3 zYvn=ZHOW28DxJ>KkU?v$5O?_sR07L+U@DuilO=PLj%{*s$>jXUo=266cCQDhWm7zY zyYHUAQ(7X&UKu|Xs7`8~K&dDBBgF6=d+5cxd@_kUE-4iCL0JxCd0~Gg(8#+kEibZR zDSUsa)LZpt+RZea8|Sao*S6tV?+|nSk~!m{kL};cL(HtFzrBa^!7t4=1Lq%T%M;OX zBk3PlLp-jik{WH6J=f|zIG^!?`$#VH!EUfgMyT#qK~m?5xPDI+A9fBp09 z3@&Zzt*l3@s)%!%@$Z@xBANq=t&SDinj_3Cs#w&mOR&HECKih2%gr;IT5dy8mwu-n z%4b!@?^F-HPgZ3loC1k(SyADc3L$yKnpu28Umwd4hInaDML}u6vL)&EC2^ES-?3$I zi(lwL6g~{<8k2B~ohzsGPpxXy2 zM-in}dDq|$X6%ChcIWh6uzGHquuY;4AQ|=iM6D<7lP$&@A(E3)vX)}vOe1D8l^jiZ zL{obIe!(IHwq{#9eTmh%oy$+|9yPo}=-bteQ3|gG9}iTr6&oNdH>^$StB=Ru@C~;T z&hsi$v*#9Z*{Imx0%Xs1z|Tf1%mA2IdEq~8Tw*km%1 zu#1?{S`^EV@f5rZa*u@PH4HV5?l{{MaN}U_{oaC1E1vT6jo{(f6W|(SHdr5g4xpM0 zlG!y`1MkgF!b$`9iK?-ifBw3bizlPdFxs+BQj3FlIaG_PE5v(X91Z)^i*-YaR{$+C|L|iyOU4 zm<-&Ua@$Na#yMV>Yc!rNonjNqW?N3wBuH~Ag^As@uO99q$ny$>;7wC?5@Z`_JnP~0qBu6tH@EuUIO=2)4I_B~b$P&XV4sTb*{r$&?_IQE-V z!46qAG10P_rbrY3okdtewOZ?A;2G+0UBpr)IG%pg@Xc$qsQI``{Pe;GC0TGEaDkf7 zqnWV4#U6C~PC0ZgJ0z7iLTI(;3MAATzZ?^8j1@NE4MOK*!>OOE%KU1?6vgMvh&;fB z9&2L}ohnd1_=x_)C!zW3WoA%mn2f`5ywotcxtEKcOz}!|PO~`B?1nu&;moWAlBK(FO|#>)ip@#b5D5b8H4q z8i#z2TiGb|)r}c|BI!Z*RUiDZCI(iI=X+VGv?^-KBz1pirbW>*Beg0ES06T&+$H5r zuesP_eXZCz=F>g>vwo^)j{SG48F+e-k1IF`^?6|8I-(?F{0A#qhItxEqH^6!4Npxs z@+eI2snCzVu6N^jHy@&-!VHuHqXgtZN~ngvtYfTuFL94H9KzX7qYS@>j9Z1FIqtMk zeUql}(2a=~E)Xunr(jcG4k7*NCSE}uz_QLDW<_Gx(PMW|iv~0KQMxvAekMg}wD6iN zBeAKM*Vqgo7Q5)MK8ou2hB$jrwjHWdio+AD>WPKi0Zfu=W>q}ELJoejDEkH-joQy4 zd!UVVRg~%ZW-N_uuIyo-C2bc~-D#~6))Yh?;J2%63Fs$omsA|^tYt2NPJSkH4Ps;vKw+E^P9>U0D`~Iq`TzZfR@@O1ROb^6n>w3e*I5@g)Wns>Uo(ni z;f&*Pc&S2jEl~Rh@%5GtcbR}#d`q-sEJ%t8$5Pxf{l*OPQF1H-XX3bzUZXI13s{b| z^U|Gd^9Bj4KFJ2(2)3?qq-{aP9(|^DfpD{TRb4w}A5lpXpTOiB8tltI zH-waW_&uGPpb&U>+{)!Eh;vB4yCQB8^?~*{Cce8fY?FQX=@p{eo8Q^^HoO*5s31T^vy%NFs9{xr7kDsY9LhaEo|+!ZKxQX zm$3~mF&oV4$}9E0ayW^UQMLGFYcR7!BH<6VlN#%B(RymN_N;E7Gc``eRUYtzRE^DZ z4E>IttP zK*IJukAO?=?YV9DD@w;Jb=CI1)xCS7Pr>AQ(Sdu|JAnB zt1&J97M_au@hmh?ZTjttMwC%K*zz#=TQnPV))dnBMrDg2iUM@TpeeM5Qdyc@_`2wJ z5n@~PV}+KJ;`_nZ1?uKmHKgGWxij@!2k7DFj_~UOcS-`%j@0xQlEJ?XK`H^CoQofz zjD#o3q$}os|5dW8BkxYRi}UT< zt7CrBd2D1L{uG&)vJ;?CBcz%wue&P`4FBrf?EYr!l&I4WjAvlS=;OmYpINgksX5J` zcQgz;g~h>Gl1nIyowsX0kx}1to)=}$qU$(u7OZ;WPJy&aV`F~iKmIu8{`*R>{d)iB zPt7&R3fw>x!;|MN&lA)vO#u*wTr0#ParUYYW~FAw9|P|Mbu5Uf9ToRZK(qxzmE+=& zhHfxQ2p1_|JiI{Y0eY6);g1k*qN7f3CxwQP_dyy$~?#4U^)v8ro zGC>+sVXiE-zw|uBTjS18%`|f$+OOE%_(oB3+)XL03SHNdKdRCWCYBg&byT%g){IHF z1K)}>7Z9)puA@F?So9vhHA+2S4vH@>@Da!##2^H7k_hQRjUj#$dyTc?+px2i3S+nt z;fFn_3cJp;cIk4RYPv2)x73}~VObt> zGL#z&ihz~WPcm>m>_^*6gE2x}imfhwF#C2ZBt;Reot!8g(RZY=cC z8s&cSt2q;SI9*yz?spGHp%~-eQ1{uilhA;b>H_j<@*!%O0kCL%+U%yXnWl)&(DcI& zwsv2(clS(hp`WuQ>i%TOK?9GSj&hk{B}H+wY*QnGJ7Vpech2(E%F9k_(@Og%QJX>c zp>V!o3wAUdeZk(g+F@z;cV*$2^LwVbrQluKdAAGp>FG1xmkv{1l}E<^osCaV%= z_eb$~r#=EG@f%0rnMnTk$Z1RtT&8sI(TxlDp~HOKyul`tQcyHEc$|t&Av2#jG*x7| zXw4OlO36C}|H{IG2OE)~PXwfynZ2DF@)xBUm1$J=v)(y86$)rPB9MF3?mT}Mg+91 z2WU-(;MHw0?7Bic+h&cQK(7EM_+1qCx5|?tHtjdut&CA4T?t%+J;@Gu2N)9Jk^?~Majasmf70SLcsKqIhr^_iw$8l1wHfe(XOSMhzli2`dcINQq=s50`)E!Ec`%8sP(0(Cy$P^<$9w}!Exh?m6Hj}Q(u!}8 zfj`LFWGvmDq-iQ!Dtg?3X7J)1-ndiG#QiBO-3YpW{VigGNLP6Q9G$hXTG6K5VYk z*jpE`@jT_ZT=N}!@L#pRzCD)515JsC}8hsC1q{?uRAVOcQM~nvb66`moNuw;&nCm0t2-nF@V`Z*G6fqK^UaOTz_V!_A z%Fi5QHeqaLr$|KKe=37uqn)iN?JuOx1?Rf zxh(y2KQS^rKUx&%NsTD|2zO%VtsVV1^CK};y!Gsx$$@XfcBw>X3#-^GEFE+jwPvYd zdk`9EX5g=OOd~7FhsToU4}ZEA)(Q!%32G6%g3lHq%*)9ZH!DBy99)u8I<|zXg|tzy zvBI>lhw5Twnb%<>h>2a2B6!}21VS3Tj5uisb)w?@`9N}3lnAp^S86>Z1@#j?Z7~DZ zg3}ImEuqyw^eXp!H2#Ggk7}Y+$&%0`c8KNg#JY(FQ82Y2a@r2m-CGfY=-I1X>O!3$ z=XKkGaI0gAIUe*mPhnpqkhl<8!CfPPqj{iy9M-;@W3Jmuhj@F9V2o#cmvxb}aQsTJ z&82aix%t45y!3XO(M1z^=~d_s$k>|Sg^Z020D?6ZbnS)mRl)SM z4-Y95<}KycHg3g!C1B~Sey>Q4(VG&+`JA(OOD?GiD^phO3iNeo%5%1g(L!dy)Im|R!*eK5+M|svfGR&;9mYJj z7z>!n#X_WvWh`@Y%tbE$a2woC4$gXMI&_MuP5iy(Rbdu}2uB^;z}W>0{2*RRrW(#_ zk*WlqX%ShcOu;xOrqy$4Uo$=-4v$}pgIg6p&qzZW(bFUGfM;i6$Ijs`YJQVKC^_QZ zikg9j9m|hu22Qv<+m+_0`{*f~WByu1zEb0Qnt_ha`~->`dQSM^8xaE0ec^bN6gXf5 zU7`E?%80cLzvd;lr0X8Y_83BGBHz2+8~YK?wMq2~U;*Jm%26-+Mxn?EEa9n0=4T;a z{#|KVA%v$CI1*#e zeVh^N+kTR#XYV$SeS`|F8QgI|iPkprL^={Qpd4zO6&WjWPd zBkxJ=I@HQ}alGc_6O%>$A4A#~!aR?PHk;88n59>qxHteJ{1GnRAQ(?n45UGglm2+g zeQM?BT=|bcR{Q)Pc@5vxzgNeY@X(B+*mAqq0l7DLc}CHV{IUgeuUGR7Yc}DC-sM^j z=BxVgeCZi^**AHi)it5t$Nz}^*x1O~$4|BfhHIM6I8Ja z7^BmVI)b`6eJcQ_;sTP;uj~2g5dDn0DH8B~@^@FLF#7{JZNPvuu{(^uJ4iED)CV4% z+SYtRoiN`SdesH_`q+e5IV+4g_@c*H`HOBpdb?{~Ote)qwHUS@Qb)QADFB)ze}|0i8%kAurvRn4B>r z3P$nm4cgt&Hknf@cg}dNrv)soc-%Q>6tdtO`YL5Sza?b6;6OuMlN@0h2>jJ@4V{Ud z7J;ixr@P)Mdq>U2_ZnNd{`Vf2T736S`wy}mu4A5^SKs4+8hyXd5-K1KnDn^OZbZ+4 z=vYtXQ5Ahl&jpd31KB+DTUeN!-8CulS#Q8k&f!LZgEb4!$79(%llEV{ue8atfZID> zp25aO**uF|;AEFBrYkXQ6#bmhXkMT3Xer&@t@N#oeE^K?N07;j47q{nE!pxL4Y`5& zEgHGO5+DkL=&d^M3%;TW(XrJ-levrB1`J1Mqa&+zbA5Y$Th_W7SUr8*fMf`f0!SYi>Tn0^{yK;wt{_ReBx0ZS3<*6&iq!QkV@Z*yN;*Zrw(KtTL<31v6PNpa@hYo7 zuzPTRJ27jsG>~X0Q?xwFg|#^lUljJDFC6y1Xt!nAZid?8I#ShP;ays>zOO=Wo1HF=W2iHOVn~t6L@<;r~Ir^RPz)& zF6mJF`$7-oGZ-Y3yYj`^05tdQy~Zz9mMfw{j$ zJnf{-a+kw%w(qq~g^+Wy=qxR68;PYo+{ZR?UmZT9yr*D7(t&qeeH_y(f@0bqgy5iq zZ^$$&0%$3T(I;kdQ&r)&kAx)uh!5P}7#n12MKcLT+gwO8TGmE3LbqgV8vm#h%ti&IKPSbAEcCZC)bVnX$-7IAv`?6a zgR0=pP>(7_IfcL&*soy+B(SdKp7Ad&-0sXCAOOXndy3%ZrWxxsb=Dy*EIoEJaG3RB~>B$ zmWJ)Ien9WjHHJxNJEpkCNIZ;h413c^dY z=g3J;I9uURxDn}1WvggxPYqfLdt5GAqRiJi!LGbkqw0QK&PkiPn?sGHe5yuW&xkckA#CxS<6bn&aBx{Tls`-)F0j0W2TBBWcBl*Zj{4u8* ziQMds7jGbj)sxx2uMpbi_XCbL@zK0!%wMX*BNxgHL=Nf@$sQiqfh=pnor@!tqEE&@ z=z13Uu{6qZu#MeS{KDaXyX{|$e$(j*5^vczJ^yKu`GKVL@=_==F+M&!wl`Zo>|gM8p%67WF?i7~-J34^@`t_PwKg`wRS$UoMrRM34P5&LGK>Y56 z?)#)9Vj*l6Ww?%N!krjp$vgvkvd{~9Biy!>vo9I@Ez(QSk_z9klF+**AKIZfT?Th# zl`8IaEX1 zXj9$pjIUIf{3YIKvSM>_WSWUkWSlH1yBCtw5h$eHYfhUH#PdPlS3{_sP}Jwz#BE2w z=kp>>;QqXm;MN~#I)E6KBnRei9&Z~2odzSI;HT&$Kh8}MZY^(Wm7}Bcj1SWldl@V% zr`w%kZ#6VAT8tl0PUU*x>-O#pBC1ClHFyRr4?^QK`)1wV@UT67Y1I-*{b(#|i$w6c zIaG5;3NyLYukncfKrmmYp0p7BxDFTY5e6@1MZYHP(p@B`X8;Dbs<1z92tBu$6k``waZDJHn!kOss z$_~Ug1we8W8E=yK3@W^z3>mFpROE@eG5m9$A#R~IbkwnzGfZOmfRie(&t+e#i#Bh7 zW}mZ%B2T@#8P*wFO47S3r10J$tD7=x(0J~NIlyOQ^wx~pPo7S#oYA;R4273 z6YBE&Ox*_3I#{NU;C&HIdnq7L4@4PUcSI(9YKIPFi;i<9cq zou!hXkM%Vzj@R=L`&y(1KNPcl9n_Q7`n+YheK)jxoLfFr$N`+#0CVj6&igF>tdv;&fqZvgP;}{(b5E{;8Qob z>^L4$wP)uTjU4~DO_gDG>{ioc4XN2mcz~iYC=R`AaRx5AZGY#8W#f@AXsdbl($(u= zkF7gkWf9N}5`l;>OlV)Bt}#Bb>d9YGvbI*ZqY1ea5|EzJ*wbVhDr@VB8{teF{?| zt-Saq-S1TGhz5yf&tb6p;m%C{v^0P)-JsS(2uCG)6nn2wM$=SH;`Hb`*hq9OI_^X1 zc?O%IZ|&N+Y0djW?drVL0+jM&Wcw_)-hd!mM3e?4*$Hwcvh3mXLvlbxmsA%yNA&fC zJ3wWPXge);-_NU&Hc7`c^CD^TkR2;+<2QG^h<(D=t#`YOeNt;#=QGH2DU*T`zEMbB z;G8}+Z;m)xR8{l)&jTbpf)xOiA@($-dNy(6)A&V8oI?Gu1kBs7vZ)9p(rKy)uwS6C zJyi+JoH7xblk~xDLn=g?}iH6z2Nw%oS1M3|VQ4x-zj*C$%lF98VR(`>68|+ap75!770R0^0eP zyUYK3W$lX!{xe!~bG5Sl+rk>@zyD0s%*4vh$X4FX&e+UZ-OSm_-0HtZQEtkU%Gg4v zd~_#$oS=~6qVtyc;EbGJ0z<_Uz~$1$Q@|5q?jTL8%u|YUMGX@Yrs-&%Ra=NO(W=XT zeil3XNX|`|pg%q4Y&_-sYJJ^^pEUsD?JJFwkvz>9>Vk&BUcg3oqur~BGpj0dlvArY zhujZ~%hpt@)WK%PZh%$E9zeR~5+O|9GJ!-n(4-Uah=bR03TEFN7|aTCSJL%WefA2*N3h<96i2dr0&(aW{m=v)JfGYlTdtKdId_%LzX z&o_6s{2GKNzQ0)H_*QxqW1RDWPQ@~j+^%5wv&pbc)@cHQ1QjLYPxAv`GdNZHN?3-c zIMEGS|CTE)s~{(y56AaR{=r3vp_zO*q(Zp8c+D|{0t69%4%HKC?#(I zlX47+Sk`25M-TeP{h25;D znp3&cozB31Cf2e5&ZSBW*4|$#0bCC(&tUW5Z&du z`>2XN68s2eNCDsj&Vm3A%{`<<%(xD5s^h?a48AW}iO0-5r7M;}iWZ%?H=yy>{POV6VYXD)V(3!W+kIvr#FCtlr!N z4=%98rO?U+M^4pFS11*x%&28!Y&sGYeFo|E{h&{yH{{l8Mi`@p*pU6+$U302QP2vp zjOBIwQ}4x~w)E7QRQ=C(;~UBIs<)pu`6aXMi_3l3JJ44qp5m#JmG1+1_S=mebj5-HQq5fvB?u%WsOTrO{q2;<(u2eTm8< z7gOXI7a5&m4T{=}?l-(y?0Vnrf5e8y(O&G@*X}LLUt@#l-(y44%=2rN*2>;O#KGR( z%-Qw7(v#gXgk#EY>|wyQub?wz0bcjqZeu@VP^KhIu^93ZL?mMAp$N`I!X(isNfaz& z5MvQz+Il3WxYdl+kTGN~Vg=L)VkKgBGIo-)$mvMB2*41iv5YZ|v5hf~u})!NhNP{8 zt%5AEJ0W%?UgY?Y{Lsu0{ZP%2y(kJ(Xoj>b$;6PWF*s9lhS(JO5#scaZege;*%4AF zirtWJVXmeiE$Jg6I+72v50VecE8;8iE7B_p1R?}71QG;FIAS<*I8r!@1fm481d;^G zDB>vcDAFhj1tJA91ri0yPsE?dKaqZ-SRh&;TOe7W93vhhA0r*3U?5^3V<2Imq$8#y zrz1s2PDav1&_q^7R7ToF*hHR3oJZnB;6!FeWJl^mkPRvCtM9Y#yYIvA%kR@0V>xj+ zAviHO5jY6|fB=L5L;xcI5gdJ0muMfUdI490384izy|;UkN{8s zEC3h)4FCtg1AqWf)aPjSGa5pM5e>q_@-SZv)dd-mi7;PG)kPU$ge}2#GGC0;@eJa_ z`Y^MGvBCNG~bit}$JICxaFujc%H2ypE?P(pTM` zyLHy$wyW(LJa9I~JF71*?CSKoQ0z3W-CMFfd~9yz8>qJNY%5ylOT9dr8ax{0o~}$; zx_CBZuj$z*J1eIjugqP#B=qP>YrK8u{^evZ*XCw z*zn3yx$vDXcMm*b?NoH>&@1K|q+ialO1GS8kYTgfFw1hWtv}N3)OE?zE8yCxS=2Su zu%d6OWW!iv%Zk3#o+fk8JyPz}cgft!*RtiXrfh{#9%u8!}g*HGRH zuQh`uej^53{Dw>x#f8~)@?+Eym5qIQm;||l`b0t%k4%6w(AXz zEQAZ2>F~$cBa&D3yL!K$e};Nie60m6`5Ot?erzaYFIjlXc4|Mfdjr&VEg`fj2*IWU_B@FY6Hh@9Z)Gmae2*FHus?vEPeTd zE#KV>j@w3KF~4H3H2*+=V9D>j^Bc_%51Wtwkb8n;_{#Zy5pjpV-Xr>#4(LBQxu%?~ zqLH(UnKS9XE|mDG*r@yxMCIEMRuT5p6if&g2ZjBOgy<`X6slazB9>WR^z3A{f=wQu zRU9NBBaniXJAeH_Ioer{LQR;tcG2xIyXEtEv1QQP`wmnWRT$+j>%NCyiYi+vY0Mmp z#kHfs1TLc8Xk}W$LXqo*2BRrEn36~aHVLhcTE$$dJZ zfHRYLV{k{3O?>8q@7%fjnm5a6mBQO=p2yvSb)(YQ<>uM+?3esIVIp!sN_h~f`RC45JJ#Z5j2XO zXDBBE4g$T*c39WXNIPFTy_KZ}?<@#&>h)n!RwgDB+GWE*Yh;3rMkvL2X=hV9j?9ZDxwXnO z)MlAHx}*n@>@!}&?f!^f9PvJaR`^hCd5+I&f)|97z(?d@KH{gQSvDVOM)ciFfS=NB(@4H zUg(DtSO|F@Qsou`V4vxBXzk+H3rsF{n6tApeJjCbWpd0-|~ zzTa%jam@TT@9;1~lv!=R+P=xLo(RXjLZel(;4#xlztNx&M8XL4#WQasBkK{`t#A9d z%$#;#zQ24tgVsf-(lTc_?-4q*T45w-)GvRTph3XEV!6<`8GSjEn-4f|j0vU>&WQ2F z1${SwD5Spcj@0%E*-V$t0ts8%H#~Vk6RALE0~M(uPvx`;Um@;kLIgJ`6K6Y`E>)c_ z$_PizVpzU<2DwgoAOV}CNTswDlcxNo))3-S@cS1-e|N;XlOC=V4d*Y4P`XNqR)Pv| zL@VMvXcrtdTv~6(`a>f~Erg;mFU^*kcwD}|{6c6R*zI~{;u=t0n}SoU4{|*;jxM|m z{FfA(ZB(Yg0YbSj(|Prik^Ml3hW^+-==XFHgHhidaw+wsv}mKbchhPjp=9EcSdF>` z9^_f{Sfq6p*PsgHmIi$P#&7~EyDkzf?{7XLXX(uAsZWU`nEj(vXHP#%KMRf`xy5d* zZb!xx62?GtsjQoLk2>2`&hvTvzhsLLkc<%WT;X3#JpHf7mWcnIiT^+T*nf%ERpb;< zlu-Fs=mgn!d1;ro(`}%m>1^`c>Ws<+$qo{RVV1s^&Og#^uzVqdu~k88qB#;w!jc4>p;X(zMxKKw@Xvc%ds3wRV$6FO;3*YZNUoLk8!tR?Sz)@g zTd{TS@RMfvI;26L=e2s^Kg*CEx3)_^7_&XP@dLhtb-mxDlV=PCF7s0|^UWhoUCx#v zxElitd~B`p?8Asd-z*}@YodCjV3zQF*w`F{>Se?jkph(bQIu15TO@=EIL3UoZw9F% z2`;^%9ln?WwUiApPLOyJ(jh87{f%lOW?w!2kj4zP!DkKrP}!427xK8IEv57Md#tXm z_9fv0+l0S<++<{Y#L#bj^L(4a*FTcHNvN5Ud)-6)dVT`o+H$0`jt4IJ+K}T5J3z%m zCUM|1BvD{V1uCS$ViV{IgD6p{Eu~#`{T}!k7pd6erq* z=IC9ZxjX+vB~^!RlK59dR{ym>^wkCbUybhn`KbP9EXJzpXyB-!e#q0~VuwWw(k+RX zfN_U}oXRaKTM-FL<$|sgE_mZ5G391WnaYu;^}KTEPX3lLcpyXTOzU~*hxm+VsNTs0 zij`Vv(8~0iSxa{?nAtwAJ?{PdwhKK0l`|3wO23~(oQ~E`4Dbhb8rJWFi1MWbBo3)X zibdMIKYIcdX=3-eZ7P~-;c1XIAXh@gP<1j@Q5|)xZ>6jzj6qp)tu(*eE?Ki)gbD7j zjk*Pq1(xx5k|0ico9P&?y6Se$Rb8%qv@~mwQRuh6fv;d~`5O8;V8vNf@u>MYE#JRI z0dAbfDSg;XmT1^)T5xEgVbMV<@AbAT!hw)mN%<2Qd0Y@Bt1ie?1ZrVfyJA^fYm88I zuI98r^<1?x_mz$kjR z@Jc7X0;plX?{LI7q?TQJ-Kgbul)dr5O(dG9?c5y;j4(VhOTv7fbq6t?l?OGRwGE3q zg@J!|&@?T$R+w$9+`wr@pgyvu)KM_5XY+hB&~~`utCRUwTXNT<)u6G}`h7e5Eb)f% zyIUoy=SR`!v!%o;Sj8=4F1Qec?yJ#^9cY?P;c?S;&&LX&5WCI@!j|mk6fq3}(|g|8 zjgqnZ8l-G5JS!8$r$%I>NUu%L^&gxxof>NShOKc4z6B~>RU){CuWfj%8s=j{*^@@T z>RRXlAbG{5rY&hlfgH^lmno==tUf8e6&umuz`=rbf7MozWMYf$iWR$7+Jt$Z<8qH7 z{ZfINUSlAz7m(WSQBv~fq;dmPVK_Xiq@Sc3k4*dJ6o|dfBscI@24guxP;6EaAr%3? zSVta`7z0E|f5bH-%C#cWnC21tKS8}{CuFL^ydRmsVlW5be;)f6Yyr)eM*Lj9lMJzm zQmw|CQ6jzX3_@C<$}7bhge~FbYJ`2}esE6N%s0)1q)9Q2tc&8RLfIofst<%|6XV;Z z-DfEKl3da_$ve}Kmi~d9z2TWvh(|<=AsJB+D@iPkSfZbdk0G3Kb8(%Mq?c$-&fZ+t0_r=z=+(xw0io*m%bdsLs%4;MucN#n;n&%c2IX~LRF3slmO4eEa<@D zku!66iiT1gMD?LWJ$?>*@H2ov*`w^g+GBYMFjA)=3ul>#6Vt{bLIW^0L%5;G^JArj zL;8W=|5MypnrL3u_mu(KzXXo|y~G~x-?Mw`8Zbv0VhvOVt3$6!7XzLL%U`QCK{)}>g^j4+U@ z`kM)1+<{aek+?i(-gr_*vZ7dh=W=u7c-#K{#Cl11>FdQ2nij|J^XCAo&jHt?Nb-MaM{pRnXm|Hs!FTvfph-37W-xXeyP{rTz zy?=(AXFfTpecdaKJ@+J@Uo*<&q38F^XipX#*a;7znyF?=~j7 z)I7^PKAzwrV6>QN&5GweY4sm%S`yb!c3=dM+D>l^5dLwcrb>is)m zt*N^!9m(Cqqb^(x6vEdey6oD=-(~BP<4K;5XKND24#yz-ELrzJqF&ck z_%gYKE~&v4e@T|~)Y1p0Ez#9CKBA{EZ1+^sN`21Qts4h{k2=>S9B=cx7%KF;akI}w zMPxc9bdI(X_0A7T)aYSnoT$8OQy)mfLW-*2Cy!XybbRSp!?)J5Fgfo)E3Q>e!&;le zXYjky@mzWv)W&9}fff!8w=rYTuGbtjKB`MXdzTBT8iRcEJu6Oz5*?>~YVP!1M3c&P zQ1y6DYHT1R&T{6U>mNmhXIPl|XmmQUUjBa?NImlWy7NsvqdEDfGAf$6|_Ht@=`OUC}#J`@IlyL3qigrKk63W3;{XmYHSrA5Uob0xwSVb`c=lFd6jT`MTpc zfny+s=Yw+!p2BLMA1Y89R3$Sg_2^QxD%sa2^C0f!Ie@OvTh9PALcF+lglru}(A(Hk zQ!(ao;~a+7d?$}P64wRTopwtzcweEb1q${)cti{3$SiZ;(()DT3)?F}P0rYQDl-w( zrLo|nPu~&Yc zRnaZ2`VDrp7P5~m;dSl$2?#U$_kqhRqbRe)W3J4O9iVB~^!LHJpTRV2OSp$WA9GBN zITbSnaupkzByqZkO5asyj67wKZJQ9&@6+M$bMOvadkTy0(q?@KhtE0w<{M$Vhqq~a zp?GxR-^pl{Pt)8_agD9ked0LeVrYq2Zj- zHrAxGSRmRa84(TX?mwfct6s9QjPh@ablEsCM1-TPdymTMVfOwM_@{``tMwRj{o+el zkbg^Gl>eT-zJ^?1+d+RB#mlLn2qF5RB-u868OM_Qf}$$Q3TnQo2dOFvMN#e(QC%fp zAg0;6t7JowQUnC|0@>%ai%tgrUi&OIn-vEs8UC{I>pH!9D)sPxdwGHDL$N)<94U^Y z{OT3hjGbikSA}hGUm42xcX4aYA&uzaJ=K+|Ke3sz9by*ZwAf6_g%#LdeJ9erq3vgE zu;?`I-716ZouYwfs_!^S>y$HMGHvh~eGAEcQ_b2JZCmiA>8M>IuGJ=$PSQBP_GBp| z6@m30w|P~oH>s3w>?|ClQ)vuWvRxr>C4!%A`XtlH1QyK*zoCsTzpW|C{9&py@Cl$+*N z%@8*JN!CKUopL5y3nleBfbvHTH$6Q;I6!u;eq8xbjS$nm6aF?ZOCHQk~ zWzxM>+n-)<4Nh;uI7gdX$~Nu#fQ_KzCLDVh7s(MJ3E+E}BcH|o#S4tX`_2dj8lWOONZYfd$p(l}xg^O_BQpsTqyjmCl-1#wzlQ{j zyh|Xu!*Nh!TuABT>47<!-wjml#tvf=Ou-y zX2p~QlN_2hM)M~;6+@n(N5r@tCl|CH0>R<>qRc19Lv|9U;uWn56d3Tbb1X1-Hb zWMpCCye=bVs7S&>VMt6!FuoE11m@sDnQJ7NZ5LjXYgUD1ym~l)cCsh#@zCt-C-9bo3aYhQR zRP-+?xFt{do+(6T=JBX{)HXdQe{mmk}l9IUibfRCD&} z<5rG?nj)(iwgqH`E4y5H>W_e+_E?rDK;xrfvqx!vuVxM3Z)3)R2;SNzzEIm&P;c7Io3@C z-ZQ64&N*S3y$cc8+&q|i8coX4nD)+yC>hy!t%}LS{+W*WEm$6k=0x}`fkg{iYolTx zS8oUzDsv6>*bYXF&V=-rN*D;G5&L{QF~opG7DPD++HoXHVBvq#uqrBap&1v)eAxn&cu1%7Y;bX+KW~bV(WW~#P$?8_>g6j#Yy5gce^+s{piVx(Nsx@m(DBMpyVN?T= z=K<{WC!P@36`l&Cuk3yu8I}FENAkP#DpR@AkM{xiW8+RA3++{AqLQ^gdqF=G8y za00YVV9gjYa`Mh&#i|S`0KdRyh{`ji1&aC-92B!N$G@UYdoqA6>jqQHu7$+b zSTynmryiMTFV+!en4~q|Nn5!*Ab5dyqNd1~)Nvnt;!ZO~Vi=Y>G*mAC!#%>Zh7i;4 zy}!4*;DZ@m%$|64_qz8)rDpT#DZub<3W>lYFkS{g+-AtM1<`W0%Z+hwzu=_EO9{~!+(K?f0{uzd<^RadkcN|rtwg4Fz;g; z1a_H8jlp4hk9s1b1c}s@yXYogc3syTE*XmKNchA0Lm$m ze(o|KmhIM)@|$WbUc1QB&-iplBuzmF-24K{=6F3mlxp+S3(L$YtRqlu%XDSrJvz6V z+=p~$;cp1T61rZ^u#(9}XwjoGLTqHuk@J23u|##za07xxclnGZ0Y zmlC;o1T(VtyHt-N#ev7fM9Fv7Gh(kriTB*t>MBtMn}ZR$Ky7i`Rb|yrCgSFA8i%56 z$_J@(tf(INlc3Ex0W>v&wQ!uTlk_iIoteO`?C5aMSzuig#kB>ps)E)JNj7O6f69Vz$t+^QEU^RF1f9;YHgsIM4^YPny&fAjc#{h`Ix-kmovc%Kug zBBX#io2AN%9VB4_gFIkW|ERaFrxo5gwk8mFD)3LRe=3e753z`{ubt%VuX)6OPnf<0 zg#YAu7e`wo7fX5zD|1wJ2vy{53~*6Fv7uO;%?#`|XNWeZy|J87pJfDzax1VlN7J_E z#knTg>bVA8v^F+2X1Zzc^|=Y@Z1(r3fMcF(-{ZX3E3T)U>+PrZHZC3QP!K`aT@N52 zVqmc#B4|b=FDFuP@(Sv3#Z(o=#C}7fLQPWK=pd6s${1?o;6ENFb=1`6jQN?xr1)Ts zNh149j5M&Y@xoa}DY34HH(!RK!TrWe>X^k`;%J`%K~BOE+?B+Vn8h&S+we3N;c8?? zjHI;Wh)^&?V~K8x-?%B69|;(HG*QuL6ox930GJpwUK)i#pZ33Z1Dt5M3?P~%X~{9; zqlSut02z|JoDCVl`- zWPF7W2pZaPXo8qwapU@aPuoKQ&3BqOxRw`*x*pOh1}q%e0r2GdL{iy9f&J)M((?529(7Lxb&Qqp1szfeQ`u zIQ85J^}>X8Z@3!ixOFXBrtPsTd2$zIUcn=LplLece$RVK!XWlS_ziWWr!BQU#XPiF zqq0KN0Qo*3k~CKpnf!sEbzs!Hdb^nxo-vj*+1T$A z84s_hTMxN=j497QaeGm;c9-+|M096}w#qmSjX$?IS)N(Cr0l0RR!Q=diXWgo?5v%% zh?bc>JBW@+;@Ic9qGi78tRmOUELE&QnoP&cQwPt9wB#izuB{Chu$q2u?X!?RM3}6g z{I(`qiR>_|jiHP)%*8jr$+AiI$52rJxrfE*F@1p68sWKF*{>7f;6SQv4_d@V1$kpM@tMR=rP) z>7S3wt0xD$qCw(=L1dM|eS~3hi|}DnJV`l$Hv@I-ZcgT&n=zv00+cEfuVc%|2Z_7a z__+{@gV_|*ExO5@vSbsPRC*!PpReC zG&o`3KYs)?0)4*(>WMDzaOQf$&8QMO0d2Kv11cA*@%SnP=)^P0c{5MA1^lru6^qZ7 zx0tmGu2=B6wLWg;rymdI6SKCC!3*hBI@5Pj_=kV)Sm{VFwXazET>P38A$tF?c!#HB zhbWG7E39$5U>Gbu!dm8w%K9GwO+d20p&5i!8?1F*8?Rome%P_!IC6Ml zh@gP#k#*q;A0Vk*g2ec~91)Y%^>0J@fNmDbs9I;E{t|N77$S8qHA2Yv{Q6#l;wA;1 z^A)Z`PFrleHM03$I9$A=;e8-$+kVy*N8RMne}UdZEo(pW001c0JR4okXYNS+`LU(} z1t|myMHSGs8c7c5M+Z*KI_ZZWTb8V8ID~2x4CRwY1k3`X#efkOj0to`(Q4aPku+Wz z6oqAWjUx>}TdRfPxxmO`+Z(km>M1Nti)xx&kh4+(r^#8#X|t=4dKUhAywYDCQlOFL zF)5}eOk0Y!T&cgNqesm*oz-|Nyf$mSR)6in*~BY__v+1Nf-3B{ra#Zxe*Lm^(T@H& zRcddp!j$*k9k_wM9ZP0@_B{KwtgKDh^=s3f@4s9x!EcOIc$k0VbUXOA=#I`?coTK@ znJ+|*!cDIB?|fR=KdN5=-~FL7T48srQfdjlZ?IKNH*KqFzgn6{%D8r|T)dbDQGxi9 znynpkNZknM?4prih*?s0_t;d5sd1ZI>MM@BF(&_xj2YDq2$arAhw!8c8X`F2h*;0k zh2=ZCC3F?&u>5a+vIC0!1UbtOI0t#}H2&XrpvY)Fwb=^VG%x zfU_L>dG?2=&=918zrIiurr^q9i2SXgLL?Fd=;6=UJx#d}gPsucRT8$F<}kW5AH|>@ zEKOCX&A5ou#`($T3yJmXtEGWAQ7_rf>V?{BMw|Ct^b%S;FNdB;>UOI-@w@Al#>#K} zY|To>j+mF_D%jr3s(w&RuRi&T>BZIZIe)*#V?Teya=yb8^!NVVu87;~9PLH%V86X4 zYcvq0McKV!nEKFUe(-_2`BJ69FAH*OyMaY#_uGu~(Y=Hquk z7ieU|gSCrC9;wx$-603lChq65oo*j`AHMg7(YWq2=DVSrFC)f+VqYH}`+z8S1)h;J z;BN6j&L}GQuTd>$B;OE*mH=EhOJ5nIk}PNMGLc{reWzchuF<9R5e!um1)!pJ4J zX(Y9+S48xJd=M>GYU}O-Nul8sbnf2htI!S84piGb_6X{G@9L~GGn8qPNmd7 zq@GB-ta0jUHrW^Wb3&)^TSJHGxuE^OqkvaTR69i=R3;>0I9K7fH+}nejd=EpowF<2 zY}jNtbx2j$vB{~Er7+AP^;GbSj!+|CEzOEq3&22BI8!(EG%#Sj5eUWrMj12ED;|KUq9;Hp+rjM9|tCQteySuN?c3D>zOjSqqcI(V@*ih_a9H^CU^nNQ!zxEC6& z^H9WNJo_X;Ty3uv#N;%dkreept)<-1KAkM!sBZx65H$;ymaV=Yld4`A4u?IVQc zwVVfBo_IRo9uk7g*Vb=>5sxq=;&8kl?HtjcW

dPDL}0z>%!DL~N*_=N_gsNrmY< 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%0DkB3f!gZt=)le*z% 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≪uj)4r_+QRHL&dOtL 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≠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

rrbbyfWm*}XOr6)hk@9F^(jQ#Y~8wbAq{xc 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 Xm4m}e@a}AfJcmJP@YKjk{LlXf_(bn& literal 0 HcmV?d00001 diff --git a/languages/language.properties b/languages/language.properties new file mode 100644 index 0000000..e0fc9a4 --- /dev/null +++ b/languages/language.properties @@ -0,0 +1,215 @@ +################# Default English translation by Kent Hansen ################## + +# File Menu + +File = File +New = New... +Open = Open... +Reopen = Reopen +Close = Close +Close_All = Close All +Save = Save +Save_As = Save As... +Save_All = Save All +Exit = Exit + +# View Menu + +View = View +Statusbar = Statusbar +Toolbar = Toolbar +Codec = Codec +Zoom = Zoom +In = In +Out = Out +1_Dimensional = 1-Dimensional +2_Dimensional = 2-Dimensional +Block_Size = Block Size +Full_Canvas = Full Canvas +Custom_Block_Size = Custom... +Row_Interleave_Blocks = Row-interleaved +Block_Grid = Block Grid +Tile_Grid = Tile Grid +Pixel_Grid = Pixel Grid + +# Edit Menu + +Edit = Edit +Undo = Undo +Redo = Redo +Cant_Undo = Can't Undo +Cant_Redo = Can't Redo +Cut = Cut +Copy = Copy +Paste = Paste +Clear = Clear +Select_All = Select All +Copy_To = Copy To... +Paste_From = Paste From... +Apply_Selection = Apply Selection +New_Selection = New Selection + +# Image Menu + +Image = Image +Mirror = Mirror +Flip = Flip +Rotate_Right = Rotate Right +Rotate_Left = Rotate Left +Shift_Left = Shift Left +Shift_Right = Shift Right +Shift_Up = Shift Up +Shift_Down = Shift Down +Stretch = Stretch... +Canvas_Size = Canvas Size... + +# Navigate Menu + +Navigate = Navigate +Go_To = Go To... +Go_To_Again = Go To Again +Add_To_Bookmarks = Add To Bookmarks... +Organize_Bookmarks = Organize Bookmarks... +Bookmarks = Bookmarks + +# Palette menu + +Palette = Palette +Edit_Colors = Edit Colors... +Format = Format +Size = Size... +Import_From = Import From +This_File = This File... +Another_File = Another File... +Add_To_Palettes = Add To Palettes... +Organize_Palettes = Organize Palettes... + +# Window Menu + +Window = Window +New_Window = New Window +Tile = Tile +Cascade = Cascade +Arrange_Icons = Arrange Icons + +# Help Menu + +Help = Help +Help_Topics = Help Topics +Tip_of_the_Millennium = Tip of the Millennium... +About_Tile_Molester = About Tile Molester + +# Tools + +Selection = Selection +Dropper = Dropper +Brush = Brush +Line = Line +Flood_Fill = Flood Fill +Color_Replacer = Color Replacer +Mover = Mover + +# Navigation button tooltips + +Page_Back = Page Back +Page_Forward = Page Forward +Row_Back = Row Back +Row_Forward = Row Forward +Tile_Back = Tile Back +Tile_Forward = Tile Forward +Byte_Back = Byte Back +Byte_Forward = Byte Forward + +# Messages + +Save_Changes_To = Save changes to +Load_File_Error = Error loading file: +Save_File_Error = Error saving file: +Load_Bitmap_Error = Error loading bitmap: +Save_Bitmap_Error = Error saving bitmap: +Save_Settings_Error = Error saving settings: +Load_Settings_Error = Error loading settings: +Save_Resources_Error = Error saving resources: +Load_Resources_Error = Error loading resources: +File_Write_Error = Can't write to file: +Palette_Read_Error = Error reading palette data: +Parser_Config_Error = XML parser configuration error: +Parser_Parse_Error = Error parsing XML: +Parser_IO_Error = XML parser IO error: +Out_Of_Memory = Out of memory. +Drugs_Message = Stay off the drugs, OK? + +# Built-in File Filter Names + +All_Supported_Formats = All Supported Formats +All_Files = All Files (*.*) + +# Bookmark/palette organization + +Create_In = Create In: +New_Folder = New Folder... +Rename = Rename +Move = Move +Delete = Delete + +# Confirmation button captions + +Yes = Yes +No = No +OK = OK +Cancel = Cancel + +# Endianness + +Endianness = Byte Order +Little_Endian = Intel +Big_Endian = Motorola + +# Dialog titles + +New_File_Dialog_Title = Create New File +New_Folder_Dialog_Title = Create New Folder +Open_File_Dialog_Title = Open +Save_As_Dialog_Title = Save As +Copy_To_Dialog_Title = Copy To +Paste_From_Dialog_Title = Paste From +Go_To_Dialog_Title = Go To Offset +Stretch_Image_Dialog_Title = Stretch Image +Block_Size_Dialog_Title = Set Block Size +Canvas_Size_Dialog_Title = Canvas Size +Add_To_Bookmarks_Dialog_Title = Add To Bookmarks +Organize_Bookmarks_Dialog_Title = Organize Bookmarks +Add_To_Palettes_Dialog_Title = Add To Palettes +Organize_Palettes_Dialog_Title = Organize Palettes +Edit_Colors_Dialog_Title = Edit Colors +Palette_Size_Dialog_Title = Change Palette Size +New_Palette_Dialog_Title = Create New Palette +Import_Internal_Palette_Dialog_Title = Import Internal Palette +Open_Palette_Dialog_Title = Import External Palette + +# Incremental Canvas Size + +Decrease_Width = Decrease Width +Increase_Width = Increase Width +Decrease_Height = Decrease Height +Increase_Height = Increase Height + +# Input field labels + +Folder_Name_Prompt = Folder Name: +Description_Prompt = Description: +Offset_Prompt = Offset: +Size_Prompt = Size: +Columns_Prompt = Columns: +Rows_Prompt = Rows: + +# Other + +Empty = Empty +Offset = Offset +Mode = Mode +Radix = Radix +Hex = Hex +Dec = Dec +Absolute = Absolute +Relative = Relative \ No newline at end of file diff --git a/languages/language_en_US.properties b/languages/language_en_US.properties new file mode 100644 index 0000000..e0fc9a4 --- /dev/null +++ b/languages/language_en_US.properties @@ -0,0 +1,215 @@ +################# Default English translation by Kent Hansen ################## + +# File Menu + +File = File +New = New... +Open = Open... +Reopen = Reopen +Close = Close +Close_All = Close All +Save = Save +Save_As = Save As... +Save_All = Save All +Exit = Exit + +# View Menu + +View = View +Statusbar = Statusbar +Toolbar = Toolbar +Codec = Codec +Zoom = Zoom +In = In +Out = Out +1_Dimensional = 1-Dimensional +2_Dimensional = 2-Dimensional +Block_Size = Block Size +Full_Canvas = Full Canvas +Custom_Block_Size = Custom... +Row_Interleave_Blocks = Row-interleaved +Block_Grid = Block Grid +Tile_Grid = Tile Grid +Pixel_Grid = Pixel Grid + +# Edit Menu + +Edit = Edit +Undo = Undo +Redo = Redo +Cant_Undo = Can't Undo +Cant_Redo = Can't Redo +Cut = Cut +Copy = Copy +Paste = Paste +Clear = Clear +Select_All = Select All +Copy_To = Copy To... +Paste_From = Paste From... +Apply_Selection = Apply Selection +New_Selection = New Selection + +# Image Menu + +Image = Image +Mirror = Mirror +Flip = Flip +Rotate_Right = Rotate Right +Rotate_Left = Rotate Left +Shift_Left = Shift Left +Shift_Right = Shift Right +Shift_Up = Shift Up +Shift_Down = Shift Down +Stretch = Stretch... +Canvas_Size = Canvas Size... + +# Navigate Menu + +Navigate = Navigate +Go_To = Go To... +Go_To_Again = Go To Again +Add_To_Bookmarks = Add To Bookmarks... +Organize_Bookmarks = Organize Bookmarks... +Bookmarks = Bookmarks + +# Palette menu + +Palette = Palette +Edit_Colors = Edit Colors... +Format = Format +Size = Size... +Import_From = Import From +This_File = This File... +Another_File = Another File... +Add_To_Palettes = Add To Palettes... +Organize_Palettes = Organize Palettes... + +# Window Menu + +Window = Window +New_Window = New Window +Tile = Tile +Cascade = Cascade +Arrange_Icons = Arrange Icons + +# Help Menu + +Help = Help +Help_Topics = Help Topics +Tip_of_the_Millennium = Tip of the Millennium... +About_Tile_Molester = About Tile Molester + +# Tools + +Selection = Selection +Dropper = Dropper +Brush = Brush +Line = Line +Flood_Fill = Flood Fill +Color_Replacer = Color Replacer +Mover = Mover + +# Navigation button tooltips + +Page_Back = Page Back +Page_Forward = Page Forward +Row_Back = Row Back +Row_Forward = Row Forward +Tile_Back = Tile Back +Tile_Forward = Tile Forward +Byte_Back = Byte Back +Byte_Forward = Byte Forward + +# Messages + +Save_Changes_To = Save changes to +Load_File_Error = Error loading file: +Save_File_Error = Error saving file: +Load_Bitmap_Error = Error loading bitmap: +Save_Bitmap_Error = Error saving bitmap: +Save_Settings_Error = Error saving settings: +Load_Settings_Error = Error loading settings: +Save_Resources_Error = Error saving resources: +Load_Resources_Error = Error loading resources: +File_Write_Error = Can't write to file: +Palette_Read_Error = Error reading palette data: +Parser_Config_Error = XML parser configuration error: +Parser_Parse_Error = Error parsing XML: +Parser_IO_Error = XML parser IO error: +Out_Of_Memory = Out of memory. +Drugs_Message = Stay off the drugs, OK? + +# Built-in File Filter Names + +All_Supported_Formats = All Supported Formats +All_Files = All Files (*.*) + +# Bookmark/palette organization + +Create_In = Create In: +New_Folder = New Folder... +Rename = Rename +Move = Move +Delete = Delete + +# Confirmation button captions + +Yes = Yes +No = No +OK = OK +Cancel = Cancel + +# Endianness + +Endianness = Byte Order +Little_Endian = Intel +Big_Endian = Motorola + +# Dialog titles + +New_File_Dialog_Title = Create New File +New_Folder_Dialog_Title = Create New Folder +Open_File_Dialog_Title = Open +Save_As_Dialog_Title = Save As +Copy_To_Dialog_Title = Copy To +Paste_From_Dialog_Title = Paste From +Go_To_Dialog_Title = Go To Offset +Stretch_Image_Dialog_Title = Stretch Image +Block_Size_Dialog_Title = Set Block Size +Canvas_Size_Dialog_Title = Canvas Size +Add_To_Bookmarks_Dialog_Title = Add To Bookmarks +Organize_Bookmarks_Dialog_Title = Organize Bookmarks +Add_To_Palettes_Dialog_Title = Add To Palettes +Organize_Palettes_Dialog_Title = Organize Palettes +Edit_Colors_Dialog_Title = Edit Colors +Palette_Size_Dialog_Title = Change Palette Size +New_Palette_Dialog_Title = Create New Palette +Import_Internal_Palette_Dialog_Title = Import Internal Palette +Open_Palette_Dialog_Title = Import External Palette + +# Incremental Canvas Size + +Decrease_Width = Decrease Width +Increase_Width = Increase Width +Decrease_Height = Decrease Height +Increase_Height = Increase Height + +# Input field labels + +Folder_Name_Prompt = Folder Name: +Description_Prompt = Description: +Offset_Prompt = Offset: +Size_Prompt = Size: +Columns_Prompt = Columns: +Rows_Prompt = Rows: + +# Other + +Empty = Empty +Offset = Offset +Mode = Mode +Radix = Radix +Hex = Hex +Dec = Dec +Absolute = Absolute +Relative = Relative \ No newline at end of file diff --git a/languages/language_it_IT.properties b/languages/language_it_IT.properties new file mode 100644 index 0000000..5ca571a --- /dev/null +++ b/languages/language_it_IT.properties @@ -0,0 +1,215 @@ +#################### Traduzione in Italiano da Gabriele "Karvek" De Luca ##################### + +# File Menu + +File = File +New = Nuovo... +Open = Apri... +Reopen = Riapri +Close = Chiudi +Close_All = Chiudi tutti +Save = Salva +Save_As = Salva come... +Save_All = Salva tutti +Exit = Esci + +# View Menu + +View = View +Statusbar = Barra di Stato +Toolbar = Barra degli Strumenti +Codec = Codifica +Zoom = Zoom +In = Dentro +Out = Fuori +1_Dimensional = 1 Dimensione +2_Dimensional = 2 Dimensioni +Block_Size = Dimensione Blocchi +Full_Canvas = Tutto il Canvas +Custom_Block_Size = Dimensione Blocchi Personalizzata +Row_Interleave_Blocks = Blocchi Rigati +Block_Grid = Griglia Blocchi +Tile_Grid = Griglia Tile +Pixel_Grid = Grigilia Pixel + +# Edit Menu + +Edit = Modifica +Undo = Annulla +Redo = Ripeti +Cant_Undo = Impossibile annullare +Cant_Redo = Impossibile ripetere +Cut = Taglia +Copy = Copia +Paste = Incolla +Clear = Elimina +Select_All = Seleziona tutto +Copy_To = Copia a... +Paste_From = Incolla da... +Apply_Selection = Applica selezione +New_Selection = Nuova selezione + +# Image Menu + +Image = Immagine +Mirror = Specchio Orizzontale +Flip = Specchio Verticale +Rotate_Right = 90° a destra +Rotate_Left = 90° a sinistra +Shift_Left = Pixel a sinistra +Shift_Right = Pixel a destra +Shift_Up = Pixel in su +Shift_Down = Pixel in giu +Stretch = Ridimensiona +Canvas_Size = Dimensione Canvas + +# Navigate Menu + +Navigate = Navigator +Go_To = Vai a... +Go_To_Again = Vai di nuovo a +Add_To_Bookmarks = Aggiungi a Preferiti... +Organize_Bookmarks = Organizza i Preferiti... +Bookmarks = Preferiti + +# Palette menu + +Palette = Palette +Edit_Colors = Modifica Colori... +Format = Formato +Size = Dimensioni +Import_From = Importa da... +This_File = Questo File... +Another_File = Un altro File.. +Add_To_Palettes = Aggiungi a Palette... +Organize_Palettes = Organizza Palette... + +# Window Menu + +Window = Finestre +New_Window = Nuova Finestra +Tile = Tutto lo Spazio +Cascade = Di Seguito +Arrange_Icons = Ordina Icone + +# Help Menu + +Help = Aiuto +Help_Topics = Guida +Tip_of_the_Millennium = Suggerimento +About_Tile_Molester = About + +# Tools + +Selection = Selection +Dropper = Dropper +Brush = Brush +Line = Line +Flood_Fill = Flodd Fill +Color_Replacer = Color Replacer +Mover = Mover + +# Navigation button tooltips + +Page_Back = Pagina Indietro +Page_Forward = Pagina Avanti +Row_Back = Riga Indietro +Row_Forward = Riga Avanti +Tile_Back = Tile Indietro +Tile_Forward = Tile Avanti +Byte_Back = Byte Indietro +Byte_Forward = Byte Avanti + +# Messages + +Save_Changes_To = Salva modifiche a +Load_File_Error = Impossibile aprire file: +Save_File_Error = Impossibile salvare file: +Load_Bitmap_Error = Impossibile aprire bitmap: +Save_Bitmap_Error = Impossibile salvare bitmap: +Save_Settings_Error = Impossibile salvare impostazioni: +Load_Settings_Error = Impossibile caricare impostazioni: +Save_Resources_Error = Impossibile salvare risorsa: +Load_Resources_Error = Impossibile caricare risorsa: +File_Write_Error = Impossibile scrivere su file: +Palette_Read_Error = Impossibile leggere palette: +Parser_Config_Error = Errore di configurazione XML: +Parser_Parse_Error = Errore di parsing XML: +Parser_IO_Error = Errore I/O di XML: +Out_Of_Memory = Fuori limite memoria +Drugs_Message = Non utilizzare droghe, OK? + +# Built-in File Filter Names + +All_Supported_Formats = Tutti i file supportati +All_Files = Tutti i files (*.*) + +# Bookmark/palette organization + +Create_In = Crea +New_Folder = Nuova Cartella +Rename = Rinomina +Move = Sposta +Delete = Cancella + +# Confirmation button captions + +Yes = Si +No = No +OK = Ok +Cancel = Cancella + +# Endianness + +Endianness = Ordine di Byte +Little_Endian = Intel +Big_Endian = Motorola + +# Dialog titles + +New_File_Dialog_Title = Crea nuovo file +New_Folder_Dialog_Title = Crea nuova cartella +Open_File_Dialog_Title = Apri +Save_As_Dialog_Title = Salva come +Copy_To_Dialog_Title = Copia a +Paste_From_Dialog_Title = Incolla da +Go_To_Dialog_Title = Vai a offset +Stretch_Image_Dialog_Title = Ridimensiona Immagine +Canvas_Size_Dialog_Title = Modifica Dimensione Blocchi +Block_Size_Dialog_Title = Dimensione Canvas +Add_To_Bookmarks_Dialog_Title = Aggiungi a Preferiti +Organize_Bookmarks_Dialog_Title = Organizza Preferiti +Add_To_Palettes_Dialog_Title = Aggiungi a Palette +Organize_Palettes_Dialog_Title = Organizza Palette +Edit_Colors_Dialog_Title = Modifica Colori +Palette_Size_Dialog_Title = Cambia Dimensione Palette +New_Palette_Dialog_Title = Crea Nuova Palette +Import_Internal_Palette_Dialog_Title = Importa Palette Interna +Open_Palette_Dialog_Title = Importa Palette Esterna + +# Incremental Canvas Size + +Decrease_Width = Diminuisci Lunghezza +Increase_Width = Aumenta Lunghezza +Decrease_Height = Diminuisci Altezza +Increase_Height = Aumenta Altezza + +# Input field labels + +Folder_Name_Prompt = Nome Cartella: +Description_Prompt = Descrizione: +Offset_Prompt = Offset: +Size_Prompt = Dimensioni: +Columns_Prompt = Colonne: +Rows_Prompt = Righe: + +# Other + +Empty = Vuoto +Offset = Offset +Mode = Modalità +Radix = Radix +Hex = Esa +Dec = Dec +Absolute = Assoluto +Relative = Relativo \ No newline at end of file diff --git a/languages/language_no_NO.properties b/languages/language_no_NO.properties new file mode 100644 index 0000000..2a18400 --- /dev/null +++ b/languages/language_no_NO.properties @@ -0,0 +1,216 @@ +###################### Norsk oversettelse av Kent Hansen ###################### + +# Filmeny + +File = Fil +New = Ny... +Open = Åpne... +Reopen = Gjenåpne +Close = Lukk +Close_All = Lukk Alle +Save = Lagre +Save_As = Lagre Som... +Save_All = Lagre Alle +Exit = Avslutt + +# Redigeringsmeny + +Edit = Rediger +Undo = Angre +Redo = Gjenta +Cant_Undo = Kan Ikke Angre +Cant_Redo = Kan Ikke Gjenta +Cut = Klipp Ut +Copy = Kopier +Paste = Lim Inn +Clear = Fjern +Select_All = Merk Alt +Copy_To = Kopier Til... +Paste_From = Lim Inn Fra... +Apply_Selection = Apply Selection +New_Selection = New Selection + +#Vis-meny + +View = Vis +Statusbar = Statuslinje +Toolbar = Verktøylinje +Codec = Kodek +Zoom = Zoom +In = Inn +Out = Ut +1_Dimensional = 1-Dimensjonell +2_Dimensional = 2-Dimensjonell +Block_Size = Blokk-størrelse +Full_Canvas = Hele Bildet +Custom_Block_Size = Egenvalgt... +Row_Interleave_Blocks = Rad-flettet +Block_Grid = Blokk-rutenett +Tile_Grid = Flis-rutenett +Pixel_Grid = Piksel-rutenett + +# Bildemeny + +Image = Bilde +Mirror = Vend Vannrett +Flip = Vend Loddrett +Rotate_Right = Rotér Mot Høyre +Rotate_Left = Rotér Mot Venstre +Shift_Left = Skift Til Venstre +Shift_Right = Skift Til Høyre +Shift_Up = Skift Opp +Shift_Down = Skift Ned +Stretch = Strekk... +Canvas_Size = Canvas Size... + +# Navigeringsmeny + +Navigate = Navigér +Go_To = Gå Til... +Go_To_Again = Gå Til Igjen +Add_To_Bookmarks = Legg Til i Bokmerker... +Organize_Bookmarks = Organisér Bokmerker... +Bookmarks = Bokmerker + +# Palettmeny + +Palette = Palett +Edit_Colors = Redigér Farger... +Format = Format +Size = Størrelse... +Import_From = Importér Fra +This_File = Denne Filen... +Another_File = Annen Fil... +Add_To_Palettes = Legg Til i Paletter... +Organize_Palettes = Organisér Paletter... + +# Vindusmeny + +Window = Vindu +New_Window = Nytt Vindu +Tile = Flislegg +Cascade = Strøm +Arrange_Icons = Ordne Ikoner + +# Hjelp-meny + +Help = Hjelp +Help_Topics = Emner i Hjelp... +Tip_of_the_Millennium = Millenniets Tips... +About_Tile_Molester = Om Tile Molester... + +# Verktøy + +Selection = Utvalg +Dropper = Hent Farge +Brush = Pensel +Line = Linje +Flood_Fill = Fyll Med Farge +Color_Replacer = Erstatt Farge +Mover = Flytt Fokus + +# Navigation button tooltips + +Page_Back = Side Tilbake +Page_Forward = Side Framover +Row_Back = Rad Tilbake +Row_Forward = Rad Framover +Tile_Back = Tile Tilbake +Tile_Forward = Tile Framover +Byte_Back = Byte Tilbake +Byte_Forward = Byte Framover + +# Beskjeder + +Save_Changes_To = Lagre endringer i +Load_File_Error = Feil ved lasting av fil: +Save_File_Error = Feil ved lagring av fil: +File_Write_Error = Kan ikke skrive til fil: +Palette_Read_Error = Feil ved lesing av palettdata: +Load_Bitmap_Error = Feil ved lasting av bildefil: +Save_Bitmap_Error = Feil ved lagring av bildefil: +Parser_Config_Error = XML parser konfigurasjonsfeil: +Parser_Parse_Error = XML parsefeil: +Parser_IO_Error = XML parser IO feil: +Save_Settings_Error = Feil ved lagring av innstillinger: +Load_Settings_Error = Feil ved lasting av innstillinger: +Save_Resources_Error = Feil ved lagring av filressurser: +Load_Resources_Error = Feil ved lasting av filressurser: +Out_Of_Memory = Tom for minne. +Drugs_Message = Hold deg unna dop, okei? + +# Innebygde filfilternavn + +All_Supported_Formats = Alle Støttede Filtyper +All_Files = Alle Filer (*.*) + +# Bokmerke/palette-organisering + +Create_In = Lagre i: +New_Folder = Ny Mappe... + +Rename = Gi nytt navn +Move = Flytt +Delete = Slett + +# Confirmation button captions + +Yes = Ja +No = Nei +OK = OK +Cancel = Avbryt + +# Endianness + +Endianness = Byte Rekkefølge +Little_Endian = Intel +Big_Endian = Motorola + +# Dialog titles + +New_File_Dialog_Title = Opprett Ny Fil +New_Folder_Dialog_Title = Opprett Ny Mappe +Open_File_Dialog_Title = Åpne Fil +Save_As_Dialog_Title = Lagre Som +Copy_To_Dialog_Title = Kopier Til +Paste_From_Dialog_Title = Lim Inn Fra +Go_To_Dialog_Title = Gå Til Filposisjon +Stretch_Image_Dialog_Title = Strekk Bilde +Block_Size_Dialog_Title = Sett Blokk-størrelse +Canvas_Size_Dialog_Title = Canvas Size +Add_To_Bookmarks_Dialog_Title = Legg Til i Bokmerker +Organize_Bookmarks_Dialog_Title = Organisér Bokmerker +Add_To_Palettes_Dialog_Title = Legg Til i Paletter +Organize_Palettes_Dialog_Title = Organisér Paletter +Edit_Colors_Dialog_Title = Redigér Farger +Palette_Size_Dialog_Title = Endre Palettstørrelse +New_Palette_Dialog_Title = Opprett Ny Palett +Import_Internal_Palette_Dialog_Title = Importér Intern Palett +Open_Palette_Dialog_Title = Importér Ekstern Palett + +# Inkrementell Canvas Size + +Decrease_Width = Mink Bredde +Increase_Width = Øk Bredde +Decrease_Height = Mink Høyde +Increase_Height = Øk Høyde + +# Input-felter + +Folder_Name_Prompt = Mappenavn: +Description_Prompt = Description: +Offset_Prompt = Posisjon: +Size_Prompt = Størrelse: +Columns_Prompt = Kolonner: +Rows_Prompt = Rader: + +# Andre + +Empty = Tom +Offset = Posisjon +Mode = Modus +Radix = Tallbase +Hex = Heks. +Dec = Des. +Absolute = Absolutt +Relative = Relativ \ No newline at end of file diff --git a/languages/language_sp_LA.properties b/languages/language_sp_LA.properties new file mode 100644 index 0000000..898fe0e --- /dev/null +++ b/languages/language_sp_LA.properties @@ -0,0 +1,215 @@ +################# Traducción al Español por Magimaster 2 (Billy Esquivel) ################## + +# File Menu + +File = Archivo +New = Nuevo... +Open = Abrir... +Reopen = Volver a Abrir +Close = Cerrar +Close_All = Cerrar Todo +Save = Salvar +Save_As = Salvar Como... +Save_All = Salvar Todo +Exit = Salir + +# View Menu + +View = Ver +Statusbar = Barra de Estado +Toolbar = Barra de Herramientas +Codec = Codec +Zoom = Acercamiento +In = Cerca +Out = Lejos +1_Dimensional = 1 Dimensión +2_Dimensional = 2 Dimensiones +Block_Size = Tamaño del Bloque +Full_Canvas = Cuadro Completo +Custom_Block_Size = Definir... +Row_Interleave_Blocks = Fila-Entrelazado +Block_Grid = Maya en Bloques +Tile_Grid = Maya en Mosaicos +Pixel_Grid = Maya en Pixeles + +# Edit Menu + +Edit = Editar +Undo = Deshacer +Redo = Rehacer +Cant_Undo = Imposible Deshacer +Cant_Redo = Imposible Rehacer +Cut = Cortar +Copy = Copiar +Paste = Pegar +Clear = Borrar +Select_All = Seleccionar Todo +Copy_To = Copiar en... +Paste_From = Pegar Desde... +Apply_Selection = Apply Selection +New_Selection = New Selection + +# Image Menu + +Image = Imagen +Mirror = Espejo +Flip = Voltear +Rotate_Right = Rotar a la Derecha +Rotate_Left = Rotatr a la Izquierda +Shift_Left = Desplazar a la Izquierda +Shift_Right = Desplazar a la Derecha +Shift_Up = Desplazar Hacia Arriba +Shift_Down = Desplazar Hacia Abajo +Stretch = Ajustar... +Canvas_Size = Canvas Size... + +# Navigate Menu + +Navigate = Navegar +Go_To = Ir A... +Go_To_Again = Ir Otra Vez +Add_To_Bookmarks = Crear Registro... +Organize_Bookmarks = Organizar Registros... +Bookmarks = Registros + +# Palette menu + +Palette = Paleta +Edit_Colors = Editar Colores... +Format = Formato +Size = Tamaño... +Import_From = Importar Desde +This_File = Este Archivo +Another_File = Otro Archivo... +Add_To_Palettes = Añadir a las Paletas... +Organize_Palettes = Organizar Paletas... + +# Window Menu + +Window = Ventana +New_Window = Nueva Ventana +Tile = Mosaico +Cascade = Cascada +Arrange_Icons = Orcanizar Íconos + +# Help Menu + +Help = Ayuda +Help_Topics = Temas de Ayuda +Tip_of_the_Millennium = El Consejo del Milenio... +About_Tile_Molester = Acerca de Tile Molester + +# Tools + +Selection = Selección +Dropper = Gotero +Brush = Pincel +Line = Línea +Flood_Fill = Rellenar +Color_Replacer = Reeplazar Color +Mover = Posición + +# Navigation button tooltips + +Page_Back = Página Anterior +Page_Forward = Página Siguiente +Row_Back = Fila Anteriro +Row_Forward = Fila Siguiente +Tile_Back = Mosaico Anterior +Tile_Forward = Mosaico Siguiente +Byte_Back = Byte Anterior +Byte_Forward = Byte Siguiente + +# Messages + +Save_Changes_To = Salvar cambios en +Load_File_Error = Error cargando archivo: +Save_File_Error = Error salvando archivo: +Load_Bitmap_Error = Error cargando mapa de bits: +Save_Bitmap_Error = Error salvando mapa de bits: +Save_Settings_Error = Error salvando preferencias: +Load_Settings_Error = Error cargando preferencias: +Save_Resources_Error = Error salvando recursos: +Load_Resources_Error = Error cargando recursos: +File_Write_Error = No se puede escribir el archivo: +Palette_Read_Error = Error leyendo los datos de la paleta: +Parser_Config_Error = Error en la configuración del analizador de XML: +Parser_Parse_Error = Error analizando XML: +Parser_IO_Error = Error IO del analizador de XML: +Out_Of_Memory = Sin memoria. +Drugs_Message = Di no a las drogas, ¿OK? + +# Built-in File Filter Names + +All_Supported_Formats = Todos los Formatos Compatibles +All_Files = All Files (*.*) + +# Bookmark/palette organization + +Create_In = Crear en: +New_Folder = Directorio Nuevo... +Rename = Cambiar Nombre +Move = Cortar +Delete = Borrar + +# Confirmation button captions + +Yes = Sí +No = No +OK = OK +Cancel = Cancelar + +# Endianness + +Endianness = Orden de los Bytes +Little_Endian = Intel +Big_Endian = Motorola + +# Dialog titles + +New_File_Dialog_Title = Crear Nevo Archivo +New_Folder_Dialog_Title = Crear Nevo Carpeta +Open_File_Dialog_Title = Abrir +Save_As_Dialog_Title = Salvar Como +Copy_To_Dialog_Title = Copiar a +Paste_From_Dialog_Title = Pegar Desde +Go_To_Dialog_Title = Ir al Offset +Stretch_Image_Dialog_Title = Ajustar Imagen +Block_Size_Dialog_Title = Tamaño del Bloque +Canvas_Size_Dialog_Title = Tamaño del Cuadro +Add_To_Bookmarks_Dialog_Title = Añadir a Registros +Organize_Bookmarks_Dialog_Title = Organizar Registros +Add_To_Palettes_Dialog_Title = Añadir a Paletas +Organize_Palettes_Dialog_Title = Organizar Paletas +Edit_Colors_Dialog_Title = Ediart Colores +Palette_Size_Dialog_Title = Cabiar Tamaño de la Paleta +New_Palette_Dialog_Title = Crear Nueva Paleta +Import_Internal_Palette_Dialog_Title = Importer Paleta Interna +Open_Palette_Dialog_Title = Import Paleta Externa + +# Incremental Canvas Size + +Decrease_Width = Disminuir Ancho +Increase_Width = Aunmentar Ancho +Decrease_Height = Disminuir Alto +Increase_Height = Aumentar Alto + +# Input field labels + +Folder_Name_Prompt = Nombre del Directorio: +Description_Prompt = Descripción: +Offset_Prompt = Offset: +Size_Prompt = Tamaño: +Columns_Prompt = Columnas: +Rows_Prompt = Filas: + +# Other + +Empty = Vacío +Offset = Offset +Mode = Modo +Radix = Radián +Hex = Hex +Dec = Dec +Absolute = Absoluto +Relative = Relativo \ No newline at end of file diff --git a/languages/language_template b/languages/language_template new file mode 100644 index 0000000..817c359 --- /dev/null +++ b/languages/language_template @@ -0,0 +1,213 @@ +#################### Language template for Tile Molester ##################### + +# File Menu + +File = +New = +Open = +Reopen = +Close = +Close_All = +Save = +Save_As = +Save_All = +Exit = + +# View Menu + +View = +Statusbar = +Toolbar = +Codec = +Zoom = +In = +Out = +1_Dimensional = +2_Dimensional = +Block_Size = +Full_Canvas = +Custom_Block_Size = +Row_Interleave_Blocks = +Block_Grid = +Tile_Grid = +Pixel_Grid = + +# Edit Menu + +Edit = +Undo = +Redo = +Cant_Undo = +Cant_Redo = +Cut = +Copy = +Paste = +Clear = +Select_All = +Copy_To = +Paste_From = + +# Image Menu + +Image = +Mirror = +Flip = +Rotate_Right = +Rotate_Left = +Shift_Left = +Shift_Right = +Shift_Up = +Shift_Down = +Stretch = +Canvas_Size = + +# Navigate Menu + +Navigate = +Go_To = +Go_To_Again = +Add_To_Bookmarks = +Organize_Bookmarks = +Bookmarks = + +# Palette menu + +Palette = +Edit_Colors = +Format = +Size = +Import_From = +This_File = +Another_File = +Add_To_Palettes = +Organize_Palettes = + +# Window Menu + +Window = +New_Window = +Tile = +Cascade = +Arrange_Icons = + +# Help Menu + +Help = +Help_Topics = +Tip_of_the_Millennium = +About_Tile_Molester = + +# Tools + +Selection = +Dropper = +Brush = +Line = +Flood_Fill = +Color_Replacer = +Mover = + +# Navigation button tooltips + +Page_Back = +Page_Forward = +Row_Back = +Row_Forward = +Tile_Back = +Tile_Forward = +Byte_Back = +Byte_Forward = + +# Messages + +Save_Changes_To = +Load_File_Error = +Save_File_Error = +Load_Bitmap_Error = +Save_Bitmap_Error = +Save_Settings_Error = +Load_Settings_Error = +Save_Resources_Error = +Load_Resources_Error = +File_Write_Error = +Palette_Read_Error = +Parser_Config_Error = +Parser_Parse_Error = +Parser_IO_Error = +Out_Of_Memory = +Drugs_Message = + +# Built-in File Filter Names + +All_Supported_Formats = +All_Files = + +# Bookmark/palette organization + +Create_In = +New_Folder = +Rename = +Move = +Delete = + +# Confirmation button captions + +Yes = +No = +OK = +Cancel = + +# Endianness + +Endianness = +Little_Endian = +Big_Endian = + +# Dialog titles + +New_File_Dialog_Title = +New_Folder_Dialog_Title = +Open_File_Dialog_Title = +Save_As_Dialog_Title = +Copy_To_Dialog_Title = +Paste_From_Dialog_Title = +Go_To_Dialog_Title = +Stretch_Image_Dialog_Title = +Canvas_Size_Dialog_Title = +Block_Size_Dialog_Title = +Add_To_Bookmarks_Dialog_Title = +Organize_Bookmarks_Dialog_Title = +Add_To_Palettes_Dialog_Title = +Organize_Palettes_Dialog_Title = +Edit_Colors_Dialog_Title = +Palette_Size_Dialog_Title = +New_Palette_Dialog_Title = +Import_Internal_Palette_Dialog_Title = +Open_Palette_Dialog_Title = + +# Incremental Canvas Size + +Decrease_Width = +Increase_Width = +Decrease_Height = +Increase_Height = + +# Input field labels + +Folder_Name_Prompt = +Description_Prompt = +Offset_Prompt = +Size_Prompt = +Columns_Prompt = +Rows_Prompt = + +# Other + +Empty = +Offset = +Mode = +Radix = +Hex = +Dec = +Absolute = +Relative = \ No newline at end of file diff --git a/resources/tmres.dtd b/resources/tmres.dtd new file mode 100644 index 0000000..bf24b42 --- /dev/null +++ b/resources/tmres.dtd @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/settings.dtd b/settings.dtd new file mode 100644 index 0000000..1481fcf --- /dev/null +++ b/settings.dtd @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/settings.xml b/settings.xml new file mode 100644 index 0000000..8335b68 --- /dev/null +++ b/settings.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/TileMolester.java b/src/TileMolester.java new file mode 100644 index 0000000..28a438a --- /dev/null +++ b/src/TileMolester.java @@ -0,0 +1,52 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +import tm.ui.TMUI; + +/** +* +* Tile Molester main class. +* A quite pointless class really. The application is very UI-centric, +* so the TMUI class evolved into the real application backbone. +* This class just gets the show started. +* +**/ + +public class TileMolester { + +/** +* +* Constructor. +* +**/ + + public TileMolester() { + new TMUI(); + } + +/** +* +* Starts up the program. +* +**/ + + public static void main(String[] args) { + new TileMolester(); + } + +} \ No newline at end of file diff --git a/src/tm/FileImage.java b/src/tm/FileImage.java new file mode 100644 index 0000000..2c1af4a --- /dev/null +++ b/src/tm/FileImage.java @@ -0,0 +1,221 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm; + +import tm.treenodes.*; +import tm.ui.TMView; +import java.io.File; +import java.util.Vector; + +/** +* +* A FileImage object represents a file that has been loaded into the editor. +* +**/ + +public class FileImage { + + private byte[] contents; + private File file; + private Vector views = new Vector(); + private static int fileNum=0; + private boolean modified; + private TMFileResources resources; + +/** +* +* Creates a FileImage from a file on disk. +* +* The contents of the file have already been read into buffer contents. +* +**/ + + public FileImage(File file, byte[] contents) { + this.file = file; + this.contents = contents; + this.resources = null; + setModified(false); + } + +/** +* +* Creates a blank FileImage of the requested size. +* +**/ + + public FileImage(int size) throws OutOfMemoryError { + file = new File(System.getProperty("user.dir") + (fileNum++)); + this.resources = null; + try { + contents = new byte[size]; + } + catch (OutOfMemoryError e) { + throw e; + } + // fill with zeroes + for (int i=0; i 0 && i < s.length() - 1) { + ext = s.substring(i+1).toLowerCase(); + } + return ext; + } + +/** +* +* Converts an Image to a RenderedImage so that it can be fed to the JPEG encoder. +* +**/ + + public static RenderedImage convertToRenderedImage(Image img) { + BufferedImage bi = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_RGB); + Graphics2D g2d = bi.createGraphics(); + g2d.drawImage(img, 0,0,img.getWidth(null), img.getHeight(null), null); + return bi; + } + +} \ No newline at end of file diff --git a/src/tm/TMBitmapImporter.java b/src/tm/TMBitmapImporter.java new file mode 100644 index 0000000..2e2b543 --- /dev/null +++ b/src/tm/TMBitmapImporter.java @@ -0,0 +1,130 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm; + +import tm.tilecodecs.*; +import tm.canvases.TMTileCanvas; +import tm.osbaldeston.image.BMP; +import tm.gfxlibs.*; +import java.io.File; +import java.io.FileInputStream; +import javax.swing.*; +import java.awt.*; +import java.awt.image.*; + +/** +* +* Allows a bitmap to be loaded and converted to a tile canvas. +* +**/ + +public class TMBitmapImporter { + +/** +* +* Static method that takes a file, tries to load the file as a bitmap and +* convert it to a tile canvas. The file extension is used to determine what +* bitmap format to use when loading the file. +* +**/ + + public static TMTileCanvas loadTileCanvasFromFile(File file) + throws Exception { + Image img = null; + String ext = getExtension(file); + // use proper decoder based on file extension + if (ext.equals("bmp")) { + // use BMP decoder + BMP bmp = new BMP(file); + img = bmp.getImage(); + } + else if (ext.equals("pcx")) { + // use PCX decoder + try { + img = PCXReader.loadImage(new FileInputStream(file)); + } + catch (Exception e) { + throw e; + } + } + else { + // use Java's decoders + ImageIcon icon = new ImageIcon(file.getAbsolutePath()); + img = icon.getImage(); + } + if (img == null) { + throw new Exception(); // couldn't load the image + } + + int w = img.getWidth(null); + int h = img.getHeight(null); + int[] pixels = new int[w * h]; + + // grab the pixels + PixelGrabber pg = new PixelGrabber(img, 0, 0, w, h, pixels, 0, w); + try { + pg.grabPixels(); + } catch (InterruptedException e) { + throw e; + } + if ((pg.getStatus() & ImageObserver.ABORT) != 0) { + throw new Exception(); + } + + DirectColorTileCodec codec = new DirectColorTileCodec("", 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000, ""); + // copy to a new canvas + int cols = w / 8; + int rows = h / 8; + byte[] bits = new byte[cols * rows * codec.getTileSize()]; + TMTileCanvas tc = new TMTileCanvas(bits); + tc.setGridSize(cols, rows); + tc.setPalette(null); + tc.setMode(TileCodec.MODE_1D); + tc.setCodec(codec); + int w2 = tc.getCanvasWidth(); + int h2 = tc.getCanvasHeight(); + for (int i=0; i 0 && i < s.length() - 1) { + ext = s.substring(i+1).toLowerCase(); + } + return ext; + } + +} \ No newline at end of file diff --git a/src/tm/TMFileResources.java b/src/tm/TMFileResources.java new file mode 100644 index 0000000..2aa6fd1 --- /dev/null +++ b/src/tm/TMFileResources.java @@ -0,0 +1,358 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm; + +import tm.colorcodecs.*; +import tm.tilecodecs.*; +import tm.treenodes.*; +import tm.utils.*; +import tm.ui.TMUI; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.w3c.dom.Node; +import java.io.File; +import java.io.IOException; +import javax.xml.parsers.ParserConfigurationException; +import org.xml.sax.SAXException; + +/** +* +* Holds resources for a file image. +* Resources include bookmarks and palettes. +* +**/ + +public class TMFileResources { + + private FolderNode bookmarkRoot; + private FolderNode paletteRoot; + + private FileImage fileImage; + private TMUI ui; + +/** +* +* Create initial resources for the specified fileimage. +* +**/ + + public TMFileResources(FileImage fileImage, TMUI ui) { + this.bookmarkRoot = new FolderNode(ui.xlate("Bookmarks")); + this.paletteRoot = new FolderNode(ui.xlate("Palettes")); + fileImage.setResources(this); + } + +/** +* +* Loads resources for a fileimage from an XML document. +* +* Resources are in an XML tree structure like so: +* +resources +* +resourcetype1 +* +resource1 +* +resource2 +* +resourcetype2 +* .... +* +resourcetype3 +* +**/ + + public TMFileResources(File file, FileImage fileImage, TMUI ui) + throws SAXException, ParserConfigurationException, IOException { + Document doc = null; + try { + doc = XMLParser.parse(file); + } catch (SAXException e) { + throw e; + } + catch (ParserConfigurationException e) { + throw e; + } + catch (IOException e) { + throw e; + } + + if (doc == null) return; + this.fileImage = fileImage; + this.ui = ui; + + Element root = doc.getDocumentElement(); + bookmarkRoot = parseBookmarks(root); + paletteRoot = parsePalettes(root); + + fileImage.setResources(this); + } + +/** +* +* Parses the bookmarks into a tree of TMTreeNodes. +* Bookmarks are in an XML tree structure like so: +* +folder1 +* +bookmark1 +* +bookmark2 +* +folder2 +* +folder3 +* +bookmark1 +* ... +* +**/ + + public FolderNode parseBookmarks(Element root) { + Element e = getChildTag(root, "bookmarks", 0); + FolderNode bookmarkRoot = new FolderNode(ui.xlate("Bookmarks")); + if (e != null) { + // parse bookmarks into tree + NodeList children = e.getChildNodes(); + for (int i=0; i\n"); + sb.append("\n"); + sb.append("\n"); + + sb.append(bookmarksToXML()); + sb.append(palettesToXML()); + + sb.append("\n"); + return sb.toString(); + } + +/** +* +* Return XML representation of bookmarks. +* +**/ + + public String bookmarksToXML() { + StringBuffer sb = new StringBuffer(); + sb.append(" \n"); + TMTreeNode[] children = bookmarkRoot.getChildren(); + for (int i=0; i\n"); + return sb.toString(); + } + +/** +* +* Returns XML representation of palettes. +* +**/ + + public String palettesToXML() { + StringBuffer sb = new StringBuffer(); + sb.append(" \n"); + TMTreeNode[] children = paletteRoot.getChildren(); + for (int i=0; i\n"); + return sb.toString(); + } + +/** +* +* Gets the default resource filename for the given file. +* Currently, this is [filename-extension+".xml"] +* +**/ + + public static File getResourceFileFor(File file) { + // determine name of XML resource file based on filename + String name = file.getName(); + int i = name.lastIndexOf('.'); + if (i != -1) { + name = name.substring(0, i); + } + name += ".xml"; + return new File("./resources/"+name); + } + + private Element getChildTag(Element e, String Tag, int i) { + return (Element)e.getElementsByTagName(Tag).item(i); + } + +} \ No newline at end of file diff --git a/src/tm/TMPalette.java b/src/tm/TMPalette.java new file mode 100644 index 0000000..122635c --- /dev/null +++ b/src/tm/TMPalette.java @@ -0,0 +1,457 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm; + +import tm.colorcodecs.*; + +/** +* +* Custom palette class. +* +**/ + +public class TMPalette { + + // the default 256-color palette + public static final int[] defaultPalette = { + 0x000000, 0xA04020, 0xD0A050, 0xF0F080, 0x860033, 0x0073BF, 0xFFCF00, 0xB4EBEF, + 0x000093, 0x00FF51, 0x00ACFF, 0xA411BC, 0x000000, 0xF28C59, 0x9F00B6, 0x00DC83, + 0x090021, 0xFFFFFF, 0xFF9F00, 0xFF0003, 0xFFAFC2, 0xF0004B, 0xE136FC, 0x6D0473, + 0x000300, 0xFFF94B, 0x9FA300, 0x636000, 0x000000, 0xF05CF9, 0xEF6B84, 0x00FF5D, + 0x000000, 0x99E200, 0xFF2F4C, 0x5EFFD6, 0x002D24, 0xFFFF00, 0x4AC234, 0x4838F5, + 0x4300D6, 0xFF0000, 0xE8890B, 0x00FC84, 0x004066, 0xFFD200, 0xBBD96B, 0xFF0067, + 0xFF6900, 0x330059, 0xFFFF4B, 0x1BACFB, 0x5EAAE3, 0x4F5DF9, 0xB12A8E, 0x6DF674, + 0xEB07E3, 0x9EB76E, 0xEE5FD6, 0x2BF8BA, 0x723338, 0x5D063C, 0xDC9C6F, 0xAA2B12, + 0x176599, 0xC6671B, 0x61EC0D, 0x820194, 0x978F12, 0x77EAB5, 0x4A9936, 0x099FAF, + 0x956558, 0x0FD972, 0xF24CA5, 0x47F7A2, 0x067996, 0xA1ABB4, 0x633056, 0xE02D81, + 0x2A5836, 0x9DCAE0, 0x65C043, 0xC4B9D5, 0x11A983, 0xF6DB7D, 0x8742B1, 0xB17615, + 0x218E7A, 0xF1577E, 0x943F95, 0xEADDED, 0xC0D74E, 0xA84090, 0xA79252, 0xF8EE81, + 0xBCCD29, 0x0EA376, 0xE5A101, 0x284457, 0xB5512D, 0x2FC653, 0xEBA13F, 0x2DFDA6, + 0x479061, 0x41BBDC, 0xC53597, 0x5F4CBE, 0xBF6749, 0x78AE54, 0xB5BD0C, 0x7641F9, + 0x69B4F7, 0xD7049F, 0x7A487F, 0x52AD20, 0x6E7F52, 0x5A9633, 0x607DDB, 0x02355C, + 0xF07278, 0xE8DE01, 0xA19835, 0xA0B90E, 0x98EE91, 0xBC46BD, 0xBD67CE, 0xE87CA2, + 0x7B6CFB, 0x0ACF97, 0xD3682E, 0x5CFB6A, 0x243CA9, 0xE943F2, 0x1D736F, 0x26F742, + 0x7A8E1A, 0xE708FD, 0x4006EB, 0xA2AEF0, 0xF085CB, 0x22DDC2, 0xEB03CB, 0x879218, + 0x5E0F42, 0x3E2F83, 0x73880A, 0x56707B, 0x9526A4, 0xA23E37, 0x2959BE, 0xB115E2, + 0x29F61D, 0xCA4BC2, 0x234876, 0x2DC7E5, 0xC735C2, 0xF41484, 0x6B7D1D, 0x1C4FAD, + 0x79AAC3, 0xA90949, 0xF4CD7B, 0x7BD0AE, 0x25EA81, 0x2B5E23, 0xB50961, 0x53DC47, + 0xF58C41, 0x41DCE8, 0x423AA4, 0xDE3864, 0x2A45A6, 0x011F57, 0x75A7B4, 0x621B26, + 0xDE88C0, 0xC05A68, 0xE9AE99, 0x81E7B6, 0x514F2C, 0x9E72A6, 0x5EF1C2, 0xF7175A, + 0xFD219A, 0x8EF152, 0x2171FC, 0x502258, 0x88C63A, 0x1945F8, 0x3CAA21, 0xD7A067, + 0x52CCF2, 0x4CE400, 0x43CC98, 0x1EDCF4, 0x076F0E, 0xB79188, 0xAF0F2B, 0x0AD644, + 0xD85343, 0xB6ECA3, 0x0662BB, 0x5A816A, 0x26A60E, 0xC21E72, 0xDFC212, 0x286621, + 0xF6FAD6, 0x2BA27D, 0x5F6F12, 0x306F18, 0xF80C80, 0x1066A7, 0xAC784C, 0x9275FA, + 0x28C6D3, 0x2C85D8, 0x8EF002, 0xE12571, 0x7A8AFB, 0x2B6B5E, 0x73862A, 0x44E76F, + 0x9DCDF8, 0x375493, 0xEA65D1, 0xD745F0, 0x3352E7, 0xD648A3, 0xDC30AD, 0x920FD5, + 0xE9572A, 0x35A93C, 0x9BFCA9, 0x37F35D, 0x143E89, 0x7FA505, 0xD85EFA, 0x63DF30, + 0xC8CCB8, 0xDD0EA2, 0x1F28D4, 0xDF6DB3, 0xEDD7A7, 0x909954, 0x88BE41, 0x9DBCA7, + 0x1B3801, 0x91A0A0, 0xCFD4F6, 0x76CDD7, 0x6D318A, 0x22D03B, 0x7750D3, 0x553080 + }; + + private static int palNum=0; + + private String id; // unique ID for this palette + private int[] entries; // stored in native format + private int[] rgbvalues; // corresponding RGB values + + private ColorCodec codec; // used to convert from/to native/RGB format + private int endianness; + private boolean direct; // Mewster: I SUPPOSE it means a palette has been loaded from another file + private int offset; + + private boolean modified; + +/** +* +* Creates a new palette with given format and size. +* +**/ + + public TMPalette(String id, int size, ColorCodec codec, int endianness) { + this.id = id; + this.codec = codec; + this.endianness = endianness; + this.direct = true; + this.offset = 0; + entries = new int[size]; + rgbvalues = new int[size]; + // set all entries to zero + for (int i=0; i= entries.length) { + System.out.println("Entry doesn't exist"); + return 0; + } + return entries[index]; + } + +/** +* +* Gets a palette entry's 24-bit RGB value. +* +**/ + + public int getEntryRGB(int index) throws ArrayIndexOutOfBoundsException { + int val = 0; + try { + val = rgbvalues[index]; + } catch (ArrayIndexOutOfBoundsException e) { + val = 0; + } + return val; + } + +/** +* +* Gets the palette entry as a byte array. +* +**/ + + public byte[] getEntryBytes(int index) throws ArrayIndexOutOfBoundsException { + byte[] bytes = new byte[codec.getBytesPerPixel()]; + codec.setEndianness(endianness); + try { + codec.toBytes(entries[index], bytes, 0); + } catch (ArrayIndexOutOfBoundsException e) { + return bytes; + } + return bytes; + } + +/** +* +* Gets index of rgb value _relative_ to startIndex. +* +**/ + + public int indexOf(int startIndex, int rgbval) { + for (int i=0; i entries.length) { + // copy all old entries + for (int i=0; i> 16; + int targetG = (argb & 0x0000FF00) >> 8; + int targetB = (argb & 0x000000FF); + int bestEntry=0, bestDiff=1000000; + for (int i=0; i> 16; + int g = (val & 0x0000FF00) >> 8; + int b = (val & 0x000000FF); + int diff = Math.abs(targetR - r) + Math.abs(targetG - g) + Math.abs(targetB - b); + if (diff < bestDiff) { + bestDiff = diff; + bestEntry = i; + } + } + return bestEntry; + } + +/** +* +* Convenience method for getting the actual RGB value of the closest matching +* entry, instead of the palette index. +* +**/ + + public int closestMatchingEntryRGB(int startIndex, int colorCount, int argb) { + return getEntryRGB(startIndex + closestMatchingEntry(startIndex, colorCount, argb)); + } + +/** +* +* Returns the palette entries as a byte array. +* +**/ + + public byte[] entriesToBytes() { + byte[] bytes = new byte[entries.length * codec.getBytesPerPixel()]; + codec.setEndianness(endianness); + for (int i=0; i tag) + + readDirectColorFormats(); + readIndexedColorFormats(); + + readPlanarTileFormats(); + readLinearTileFormats(); + readDirectColorTileFormats(); + readCompositeTileFormats(); + + readFileFilters(); + readPaletteFilters(); + readFileListeners(); + } + +/** +* +* Reads the directcolor format tags and creates directcolorcodecs for them. +* +**/ + + private static void readDirectColorFormats() { + NodeList directColorTags = tmspec.getElementsByTagName("directcolor"); + for (int i=0; i x2) { + x1 = selX2; + x2 = selX1; + } + if (y1 > y2) { + y1 = selY2; + y2 = selY1; + } + int dim = getScaledTileDim(); + g.setColor(Color.white); + g.drawRect(x1*dim, y1*dim, (x2-x1+1)*dim-1, (y2-y1+1)*dim-1); + } + } + +/////////////////////////////////////////////////////////////////////////////// +// Drawing/tool-related + +/** +* +* The mouse was clicked inside the canvas. +* +**/ + + public void mouseClicked(MouseEvent e) { + e.getClickCount(); + } + +/** +* +* Mouse entered the editor canvas. +* Switch to the proper cursor according to the current tool. +* +**/ + + public void mouseEntered(MouseEvent e) { + setToolTipText(""); + int tool = ui.getTool(); + if (tool == TMUI.SELECT_TOOL) { + setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR)); + } + else if (tool == TMUI.ZOOM_TOOL) { + setCursor(zoomCursor); + } + else if (tool == TMUI.PICKUP_TOOL) { + setCursor(pickupCursor); + } + else if (tool == TMUI.BRUSH_TOOL) { + setCursor(brushCursor); + } + else if (tool == TMUI.LINE_TOOL) { + setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR)); + } + else if (tool == TMUI.FILL_TOOL) { + setCursor(fillCursor); + } + else if (tool == TMUI.REPLACE_TOOL) { + setCursor(brushCursor); + } + else if (tool == TMUI.MOVE_TOOL) { + setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + } + } + +/** +* +* The mouse exited the canvas. +* +**/ + + public void mouseExited(MouseEvent e) { + // TODO: remove statusbar coords text + } + +/** +* +* Initiates relevant tool action. +* +**/ + + public void mousePressed(MouseEvent e) { + // disable the keyboard events while a mouse action is in progress + view.setKeysEnabled(false); + // +// if (tool != TMUI.SELECT_TOOL) { + maybeApplySelection(); +// } + // get the current tool + int tool = ui.getTool(); + // get pixel coordinate + int x = (int)(e.getX() / scale); + int y = (int)(e.getY() / scale); + + if (tool == TMUI.SELECT_TOOL) { + // figure out starting (x,y) tile coords + selX1 = x / 8; + selY1 = y / 8; + // + isSelecting = false; + repaint(); + } + + else if (tool == TMUI.ZOOM_TOOL) { + if (e.getButton() == MouseEvent.BUTTON1) { + ui.doZoomInCommand(); + } + else { + ui.doZoomOutCommand(); + } + } + + else if (tool == TMUI.PICKUP_TOOL) { + // get pixel under cursor + int color = getPixel(x, y); + if (e.getButton() == MouseEvent.BUTTON1) { + // set as foreground color + ui.setFGColor(color); + } + else { + // set as background color + ui.setBGColor(color); + } + } + + else if (tool == TMUI.BRUSH_TOOL) { + drawColor = getDrawColor(e.getButton()); + drawLine(x, y, x, y, true); + redraw(); + lineX1 = x; + lineY1 = y; + } + + else if (tool == TMUI.LINE_TOOL) { + drawColor = getDrawColor(e.getButton()); + drawLine(x, y, x, y, false); + redraw(); + lineX1 = x; + lineY1 = y; + lineX2 = x; + lineY2 = y; + isDrawingLine = true; + } + + else if (tool == TMUI.FILL_TOOL) { + // get pixel under cursor + int color = getPixel(x, y); + // get draw color + drawColor = getDrawColor(e.getButton()); + if (drawColor != color) { + // fill! + filledColor = color; + // fillRecursive(x, y); + floodFill(x, y); + commitDrawingOperation("Flood Fill"); // i18n + } + } + + else if (tool == TMUI.REPLACE_TOOL) { + // get pixel under cursor + int color = getPixel(x, y); + drawColor = getDrawColor(e.getButton()); + // replace all occurences of color + for (int i=0; i= canvasWidth) { + x = canvasWidth - 1; + } + if (y < 0) { + y = 0; + } + else if (y >= canvasHeight) { + y = canvasHeight - 1; + } + + if (tool == TMUI.SELECT_TOOL) { + isSelecting = true; + // update selection + selX2 = x / 8; + selY2 = y / 8; + // + repaint(); + } + + else if (tool == TMUI.ZOOM_TOOL) { + } + + else if (tool == TMUI.PICKUP_TOOL) { + } + + else if (tool == TMUI.BRUSH_TOOL) { + drawLine(lineX1, lineY1, x, y, true); + redraw(); + lineX1 = x; + lineY1 = y; + } + + else if (tool == TMUI.LINE_TOOL) { + if (isDrawingLine) { + if ((x != lineX2) || (y != lineY2)) { // only if coordinates changed... + // "erase" old line + drawLine(lineX1, lineY1, lineX2, lineY2, false); + // draw new line + drawLine(lineX1, lineY1, x, y, false); + lineX2 = x; + lineY2 = y; + redraw(); + } + } + } + + else if (tool == TMUI.FILL_TOOL) { + } + + else if (tool == TMUI.REPLACE_TOOL) { + } + + else if (tool == TMUI.MOVE_TOOL) { + Point p = e.getPoint(); + int dx = p.x - moveMousePoint.x; + int dy = p.y - moveMousePoint.y; + + TMView view = (TMView)ui.getDesktop().getSelectedFrame(); + JScrollBar hsb = view.getScrollPane().getHorizontalScrollBar(); + JScrollBar vsb = view.getScrollPane().getVerticalScrollBar(); + int newXpos = hsb.getValue() + dx; + int newYpos = vsb.getValue() + dy; + + if (newXpos < hsb.getMinimum()) newXpos = hsb.getMinimum(); + else if (newXpos > hsb.getMaximum()) newXpos = hsb.getMaximum(); + if (newYpos < vsb.getMinimum()) newYpos = vsb.getMinimum(); + else if (newYpos > vsb.getMaximum()) newYpos = vsb.getMaximum(); + + hsb.setValue(newXpos); + hsb.revalidate(); + vsb.setValue(newYpos); + vsb.revalidate(); + view.getScrollPane().revalidate(); + view.revalidate(); + + moveMousePoint = new Point(p); + } + + // update status bar coords + currentCol = e.getX() / getScaledTileDim(); + currentRow = e.getY() / getScaledTileDim(); + ui.refreshStatusBar(); + } + +/** +* +* Terminates relevant tool action. +* +**/ + + public void mouseReleased(MouseEvent e) { + // get the current tool + int tool = ui.getTool(); + + if (tool == TMUI.SELECT_TOOL) { + if (isSelecting) { + // end selection + isSelecting = false; + if (selX1 > selX2) { + // swap + int temp = selX1; + selX1 = selX2; + selX2 = temp; + } + if (selY1 > selY2) { + // swap + int temp = selY1; + selY1 = selY2; + selY2 = temp; + } + + makeSelection(selX1, selY1, selX2-selX1+1, selY2-selY1+1); + + view.addReversibleAction( + new ReversibleNewSelectionAction(selectionCanvas,this) + ); + + } + else { + // encode selection, if there is one + } + if (hasSelection()) { + selectionCanvas.maybeShowPopup(e); + } + } + + else if (tool == TMUI.ZOOM_TOOL) { + } + + else if (tool == TMUI.PICKUP_TOOL) { + } + + else if (tool == TMUI.BRUSH_TOOL) { + commitDrawingOperation("Brush"); // i18n + } + + else if (tool == TMUI.LINE_TOOL) { + drawLine(lineX1, lineY1, lineX2, lineY2, false); + // draw the final line + isDrawingLine = false; + drawLine(lineX1, lineY1, lineX2, lineY2, true); + commitDrawingOperation("Line"); // i18n + } + + else if (tool == TMUI.FILL_TOOL) { + } + + else if (tool == TMUI.REPLACE_TOOL) { + } + + else if (tool == TMUI.MOVE_TOOL) { + } + + // enabled keyboard events again + view.setKeysEnabled(true); + } + +/** +* +* The mouse was moved within the canvas. +* +**/ + + public void mouseMoved(MouseEvent e) { + // get the current tool + int tool = ui.getTool(); + // get pixel coordinate + int x = (int)(e.getX() / scale); + int y = (int)(e.getY() / scale); + + if (tool == TMUI.PICKUP_TOOL) { + // get pixel under cursor + int color = getPixel(x, y); + int r = (color >> 16) & 0xFF; + int g = (color >> 8) & 0xFF; + int b = color & 0xFF; + setToolTipText("R:"+r+" G:"+g+" B:"+b); + } + + // update status bar coords + currentCol = e.getX() / getScaledTileDim(); + currentRow = e.getY() / getScaledTileDim(); + ui.refreshStatusBar(); + } + +/** +* +* Non-recursive algorithm that performs flood fill, starting at location (x,y). +* +**/ + + public void floodFill(int x, int y) { + Vector seeds = new Vector(); + seeds.add(new Point(x, y)); + while (!seeds.isEmpty()) { + Point p = (Point)seeds.remove(0); + x = p.x; + y = p.y; + if (getPixel(x, y) == drawColor) continue; + setPixelTraceable(x, y, drawColor); + + // find left side, filling along the way + int left = x-1; + while ((left >= 0) && (getPixel(left, y) == filledColor)) { + setPixelTraceable(left--, y, drawColor); + } + left++; + + // find right side, filling along the way + int right = x+1; + while ((right < canvasWidth) && (getPixel(right, y) == filledColor)) { + setPixelTraceable(right++, y, drawColor); + } + right--; + + // check row above + y--; + if (y >= 0) { + for (int i=left; i<=right; i++) { + if (getPixel(i, y) == filledColor) { + seeds.add(new Point(i, y)); + } + } + } + + // check row below + y += 2; + if (y < canvasHeight) { + for (int i=left; i<=right; i++) { + if (getPixel(i, y) == filledColor) { + seeds.add(new Point(i, y)); + } + } + } + } + } + +/** +* +* Replaces color with drawing color. +* This isn't used anymore because it's recursive at the pixel granularity, +* which caused stack overflows when filling moderately large areas. +* See the above method for a non-recursive implementation. +* +**/ + + private void fillRecursive(int x, int y) { + // bounds check + if ((x < 0) || (y < 0) || (x >= canvasWidth) || (y >= canvasHeight)) return; + + // color check + if (getPixel(x, y) != filledColor) return; + + // replace color + setPixelTraceable(x, y, drawColor); + + // call recursively + fillRecursive(x+1, y); + fillRecursive(x-1, y); + fillRecursive(x, y+1); + fillRecursive(x, y - 1); + } + +/** +* +* Draws a line from coordinates (x1,y1) to (x2,y2) in the pixel buffer, +* using the current draw color. +* +**/ + + private void drawLine(int x1, int y1, int x2, int y2, boolean trace) { + int dx = x2 - x1; + int dy = y2 - y1; + double delta; + if (dx != 0) { + delta = (double)dy / (double)dx; + } + else { + delta = 100000.0; // infinity + } + if (delta > 1.0 || delta < -1.0) { + delta = (double)dx / (double)dy; + // step in y direction + if (dy < 0) { + double i = x2; + for (int j=y2; j<=y1; j++) { + if (trace) + setPixelTraceable((int)i, j, drawColor); + else + xorPixel((int)i, j); + i += delta; + } + } + else { + double i = x1; + for (int j=y1; j<=y2; j++) { + if (trace) + setPixelTraceable((int)i, j, drawColor); + else + xorPixel((int)i, j); + i += delta; + } + } + } + else { + // step in x direction + if (dx < 0) { + double j = y2; + for (int i=x2; i<=x1; i++) { + if (trace) + setPixelTraceable(i, (int)j, drawColor); + else + xorPixel(i, (int)j); + j += delta; + } + } + else { + double j = y1; + for (int i=x1; i<=x2; i++) { + if (trace) + setPixelTraceable(i, (int)j, drawColor); + else + xorPixel(i, (int)j); + j += delta; + } + } + } + } + +/** +* +* Sets the pixel at coordinate (x,y) in the canvas to the specified value, +* and signals that it has been modified. +* +**/ + + protected void setPixelTraceable(int x, int y, int argb) { + // mark the tile as modified + tileModified(x/8, y/8); + + setPixel(x, y, argb); + } + +/** +* +* Marks the tile at location (col,row) in the grid as modified. +* +**/ + + private void tileModified(int col, int row) { + Point p = gridCoords[row][col]; + if (!modifiedTiles.contains(p)) { + modifiedTiles.add(p); + // save original pixels + copyTilePixelsToBuffer(col, row, tempPixels, 0); + IntBuffer ib = IntBuffer.allocate(8*8); + ib.put(tempPixels); + modifiedPixels.add(ib); + } + } + +/** +* +* Copies the pixels for the tile at location (x,y) in the grid to the +* specified buffer, starting at the specified offset. +* +**/ + + public void copyTilePixelsToBuffer(int x, int y, int[] buf, int ofs) { + int pixOfs = (y * 8 * canvasWidth) + (x * 8); + for (int i=0; i<8; i++) { + for (int j=0; j<8; j++) { + buf[ofs++] = pixels[pixOfs++]; + } + pixOfs += canvasWidth - 8; + } + } + +/** +* +* Copies the pixels in the buffer to the tile at location (x,y). +* +**/ + + public void copyBufferToTilePixels(int x, int y, int[] buf, int ofs) { + int pixOfs = (y * 8 * canvasWidth) + (x * 8); + for (int i=0; i<8; i++) { + for (int j=0; j<8; j++) { + pixels[pixOfs++] = buf[ofs++]; + } + pixOfs += canvasWidth - 8; + } + } + +/** +* +* Commits a drawing operation: Encodes all the affected tiles, +* sets modified, eventually adds to Undo buffer, redraws tiles +* +**/ + + private ReversibleTileModifyAction commitDrawingOperation(String name) { + return commitDrawingOperation(name,true); + } + + private ReversibleTileModifyAction commitDrawingOperation(String name, boolean undoable) { + // Undo-stuff + BookmarkItemNode bookmark = view.createBookmark(""); + + Point[] pts = new Point[modifiedTiles.size()]; + int[] oldPix = new int[pts.length * 8*8]; + int[] newPix = new int[pts.length * 8*8]; + + for (int i=0; i cols) { + w = cols - destx; + } + if (desty + h > rows) { + h = rows - desty; + } + + // Undo-stuff + for (int i=0; i> 1) * (blockLineSize << 1); + tileX <<= 1; + if ((mode == TileCodec.MODE_2D) && (tileX >= blockWidth)) { + relOfs += blockLineSize; + tileX -= blockWidth; + } + if ((tileY % 2) == 0) { + // even tile (0, 2, 4, ...) + relOfs += tileX * getTileIncrement(); + } + else { + // odd tile (1, 3, 5, ...) + tileX++; + relOfs += tileX * getTileIncrement(); + } + } + else { + relOfs += (tileY * blockLineSize) + (tileX * getTileIncrement()); + } + + int absOfs = relOfs + offset; + // range check + int limit = 0; + if (mode == TileCodec.MODE_1D) { + limit = bits.length - codec.getTileSize(); + } + else { + limit = bits.length - getRowIncrement(); + } + if (absOfs <= limit) return absOfs; + return -1; + } + +/** +* +* Gets the stride. +* +**/ + + public int getStride() { + return (mode == TileCodec.MODE_1D) ? 0 : blockWidth-1; + } + +/** +* +* Turns the block grid on or off. +* +**/ + + public void setBlockGridVisible(boolean showBlockGrid) { + this.showBlockGrid = showBlockGrid; + } + +/** +* +* Gets the visibility status of the block grid. +* +**/ + + public boolean isBlockGridVisible() { + return showBlockGrid; + } + +/** +* +* Sets the block dimensions. +* +**/ + + public void setBlockDimensions(int blockWidth, int blockHeight) { + this.blockWidth = blockWidth; + this.blockHeight = blockHeight; + } + +/** +* +* Gets the block width (in # of tiles). +* +**/ + + public int getBlockWidth() { + return blockWidth; + } + +/** +* +* Gets the block height (in # of tiles). +* +**/ + + public int getBlockHeight() { + return blockHeight; + } + +/** +* +* Sets row-interleaved state. +* +**/ + + public void setRowInterleaveBlocks(boolean rowInterleaved) { + this.rowInterleaved = rowInterleaved; + } + +/** +* +* Gets row-interleaved state. +* +**/ + + public boolean getRowInterleaveBlocks() { + return rowInterleaved; + } + +} \ No newline at end of file diff --git a/src/tm/canvases/TMPixelCanvas.java b/src/tm/canvases/TMPixelCanvas.java new file mode 100644 index 0000000..9600936 --- /dev/null +++ b/src/tm/canvases/TMPixelCanvas.java @@ -0,0 +1,467 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.canvases; + +import javax.swing.*; +import java.awt.*; +import java.awt.image.*; + +/** +* +* Provides a surface where decoded graphics data can be rendered. +* This is an abstract class: Subclasses are required to implement the +* unpackPixels() and packPixels() methods for decoding and encoding +* graphics data, respectively. +* Pixels must be decoded to 32-bit ARGB format (see implementation details below). +* +**/ + +public abstract class TMPixelCanvas extends JPanel { + + protected int canvasWidth; + protected int canvasHeight; + protected double scale; + + protected byte[] bits; // encoded data buffer + protected int offset; // starting offset in buffer + + protected int[] pixels; + protected MemoryImageSource source=null; + private Image image; + private DirectColorModel colorModel; + + private boolean showPixelGrid=false; + +/** +* +* Creates a pixel pane using bits as the graphics source. +* +**/ + + public TMPixelCanvas(byte[] bits) { + super(); + this.bits = bits; + setOffset(0); + setLayout(null); + colorModel = new DirectColorModel(32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000); + setBackground(Color.gray); + setCanvasSize(0, 0); + setScale(1.0); + } + +/** +* +* Creates a pixel pane of the specified size and using bits as the graphics source. +* +**/ + + public TMPixelCanvas(byte[] bits, int canvasWidth, int canvasHeight) { + super(); + this.bits = bits; + setOffset(0); + setLayout(null); + colorModel = new DirectColorModel(32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000); + setBackground(Color.gray); + setCanvasSize(canvasWidth, canvasHeight); + setScale(1.0); + } + +/** +* +* Sets the size of the canvas in pixels. +* +**/ + + public void setCanvasSize(int canvasWidth, int canvasHeight) { + this.canvasWidth = canvasWidth; + this.canvasHeight = canvasHeight; + + // create canvas image and initialize stuff + pixels = new int[canvasWidth*canvasHeight]; + source = new MemoryImageSource(canvasWidth, canvasHeight, colorModel, pixels, 0, canvasWidth); + source.setAnimated(true); + image = createImage(source); + + setScale(scale); + } + +/** +* +* Sets the offset into the buffer from which tile data is unpacked/packed. +* +**/ + + public void setOffset(int offset) { + this.offset = offset; + } + +/** +* +* Gets the offset. +* +**/ + + public int getOffset() { + return offset; + } + +/** +* +* Sets the scale. +* +**/ + + public void setScale(double scale) { + if (scale < 1.0) scale = 1.0; // minimum + else if (scale > 32.0) scale = 32.0; // maximum + this.scale = scale; + + // set size + int scaledWidth = (int)(canvasWidth*scale); + int scaledHeight = (int)(canvasHeight*scale); + setSize(scaledWidth, scaledHeight); + } + +/** +* +* Gets the scale. +* +**/ + + public double getScale() { + return scale; + } + +/** +* +* Subclasses required to implement this method. It is responsible for +* filling the canvas with pixels, by decoding data starting at +* &bits[offset]. +* +**/ + + protected abstract void unpackPixels(); + +/** +* +* Subclasses required to implement this method. It is responsible for +* encoding the canvas's pixels into some format. +* +**/ + + protected abstract void packPixels(); + +/** +* +* Paints pixels and grid(s). +* +**/ + + public void paintComponent(Graphics g) { + super.paintComponent(g); + g.drawImage(image, 0, 0, getWidth(), getHeight(), null); + // draw gridlines if necessary + if (showPixelGrid) { + drawPixelGrid(g); + } + } + +/** +* +* Draws pixel grid. +* +**/ + + private void drawPixelGrid(Graphics g) { + if (scale < 8.0) return; // don't show it for scales less than 8 + g.setColor(Color.gray); + // draw horizontal lines + for (int i=1; i=0; j--) { + setPixel(i, j, pix[ofs++]); + } + } + packPixels(); + setScale(scale); + } + +/** +* +* Rotates the canvas 90 degrees right (clockwise). +* +**/ + + public void rotateRight() { + int[] pix = getPixels(); + setCanvasSize(canvasHeight, canvasWidth); + int ofs = 0; + for (int i=canvasWidth-1; i>=0; i--) { + for (int j=0; j=0; x--) { + setPixel(x+1, y, getPixel(x, y)); + } + setPixel(0, y, p0); + } + packPixels(); + } + +/** +* +* Shifts the canvas one row up. +* +**/ + + public void shiftUp() { + for (int x=0; x=0; y--) { + setPixel(x, y+1, getPixel(x, y)); + } + setPixel(x, 0, p0); + } + packPixels(); + } + +} \ No newline at end of file diff --git a/src/tm/canvases/TMSelectionCanvas.java b/src/tm/canvases/TMSelectionCanvas.java new file mode 100644 index 0000000..7a30b19 --- /dev/null +++ b/src/tm/canvases/TMSelectionCanvas.java @@ -0,0 +1,354 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.canvases; + +import tm.TMPalette; +import tm.tilecodecs.TileCodec; +import tm.reversibleaction.ReversibleMoveSelectionAction; +import tm.ui.TMUI; +import javax.swing.*; +import javax.swing.event.*; +import java.awt.*; +import java.awt.event.*; + +/** +* +* A tile canvas that can be moved around. +* +**/ + +public class TMSelectionCanvas extends TMTileCanvas implements MouseInputListener { + + private TMUI ui; + private static JPopupMenu selectionPopup = null; + + private int dx; + private int dy; + private int oldX; + private int oldY; + +/** +* +* Creates a selection canvas by copying the specified tile grid. +* +**/ + + public TMSelectionCanvas(TMUI ui, TMTileCanvas canvas, int x1, int y1, int w, int h) { + super(null); + this.ui = ui; + if (selectionPopup == null) + initSelectionPopup(); + addMouseListener(this); + addMouseMotionListener(this); + setMode(TileCodec.MODE_1D); // all copied data is stored in 1-Dimensional mode + setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); + setVisible(false); + // create buffer to hold tile data + byte[] selbits = new byte[w * h * canvas.getCodec().getTileSize()]; + // init the canvas + setBits(selbits); + setGridSize(w, h); + setCodec(canvas.getCodec()); + if (canvas.getPalette() != null) { + setPalette(new TMPalette(canvas.getPalette())); + setPalIndex(canvas.getPalIndex()); + } + + // copy pixels + for (int i=0; ibits as the encoded tile data source. +* +**/ + + public TMTileCanvas(byte[] bits) { + super(bits); + this.cols = 0; + this.rows = 0; + } + +/** +* +* Creates a tile pane of the specified size, and with bits +* as the encoded tile data source. +* Doesn't work quite right? +**/ + + public TMTileCanvas(byte[] bits, int cols, int rows) { + super(bits, cols*8, rows*8); + this.cols = cols; + this.rows = rows; + } + +/** +* +* Sets the tile mode. This determines how tile data is interpreted. +* Valid modes are MODE_1D and MODE_2D. +* +**/ + + public void setMode(int mode) { + this.mode = mode; + } + +/** +* +* Gets the mode. +* +**/ + + public int getMode() { + return mode; + } + +/** +* +* Sets the codec that's used for decoding+encoding individual tiles. +* +**/ + + public void setCodec(TileCodec codec) { + this.codec = codec; + } + +/** +* +* Gets the tile codec. +* +**/ + + public TileCodec getCodec() { + return codec; + } + +/** +* +* Sets the palette that's used for mapping colors when bitsPerPixel <= 8. +* +**/ + + public void setPalette(TMPalette palette) { + this.palette = palette; + } + +/** +* +* Gets the palette. +* +**/ + + public TMPalette getPalette() { + return palette; + } + +/** +* +* Sets the palette index. +* +**/ + + public void setPalIndex(int palIndex) { + this.palIndex = palIndex; + } + +/** +* +* Gets the palette index. +* +**/ + + public int getPalIndex() { + return palIndex; + } + +/** +* +* Sets the size of the tile canvas. +* +**/ + + public void setGridSize(int cols, int rows) { + setCanvasSize(cols*8, rows*8); + this.cols = cols; + this.rows = rows; + } + +/** +* +* Encodes the specified tile. TODO +* +**/ + + public void packTile(int x, int y) { + int pixOfs; + int bitsOfs, pos; + // encode single atomic tile + bitsOfs = getTileBitsOffset(x, y); + if (bitsOfs >= 0) { + // copy pixels + pixOfs = (y * 8 * canvasWidth) + (x * 8); + pos = 0; + if (codec.getBitsPerPixel() <= 8) { + int colorCount = codec.getColorCount(); + int colorIndex = palIndex * colorCount; + // map RGB values to palette indices + for (int p=0; p<8; p++) { + for (int q=0; q<8; q++) { + pixdata[pos++] = palette.indexOf(colorIndex, pixels[pixOfs++]); + } + pixOfs += canvasWidth - 8; + } + } + else { + // non-palettized: color is actual 32-bit ARGB value + for (int p=0; p<8; p++) { + for (int q=0; q<8; q++) { + pixdata[pos++] = pixels[pixOfs++]; + } + pixOfs += canvasWidth - 8; + } + } + codec.encode(pixdata, bits, bitsOfs, getStride()); + } + else { + // not valid tile, do nothing + } + } + +/** +* +* Gets the number of columns in the tile grid. +* +**/ + + public int getCols() { + return cols; + } + +/** +* +* Gets the number of rows in the tile grid. +* +**/ + + public int getRows() { + return rows; + } + +/** +* +* Decodes tile data to pixel buffer. +* +**/ + + public void unpackPixels() { + if (codec == null) return; + int[] decodedTile; + int pixOfs = 0; + int bitsOfs, tileOfs, pos; + int colorIndex = palIndex * codec.getColorCount(); // only valid for palettized codecs + int bpp = codec.getBitsPerPixel(); + int stride = getStride(); + // render grid of atomic tiles + for (int i=0; i= 0) { + decodedTile = codec.decode(bits, bitsOfs, stride); + // copy pixels + tileOfs = pixOfs; + pos = 0; + if ((bpp <= 8) && (palette != null)) { + // map palette indices to RGB values + for (int p=0; p<8; p++) { + for (int q=0; q<8; q++) { + pixels[tileOfs++] = palette.getEntryRGB(colorIndex + decodedTile[pos++]); + } + tileOfs += canvasWidth - 8; + } + } + else { + // non-palettized: color is actual 32-bit ARGB value + for (int p=0; p<8; p++) { + for (int q=0; q<8; q++) { + pixels[tileOfs++] = decodedTile[pos++]; + } + tileOfs += canvasWidth - 8; + } + } + } + else { + // not valid tile, fill with gray pixels + tileOfs = pixOfs; + for (int p=0; p<8; p++) { + for (int q=0; q<8; q++) { + pixels[tileOfs++] = 0x7F7F7F; + } + tileOfs += canvasWidth - 8; + } + } + pixOfs += 8; // next tile column + } + pixOfs += canvasWidth*7; // next tile row + } + source.newPixels(); + } + +/** +* +* Encodes tile data. +* +**/ + + public void packPixels() { + if (codec == null) return; + int pixOfs = 0; + int bitsOfs, tileOfs, pos; + int colorCount = codec.getColorCount(); // only valid for palettized codecs + int colorIndex = palIndex * colorCount; + int bpp = codec.getBitsPerPixel(); + int stride = getStride(); + // encode grid of atomic tiles + for (int i=0; i= 0) { + // copy pixels + tileOfs = pixOfs; + pos = 0; + if ((bpp <= 8) && (palette != null)) { + // map RGB values to palette indices + for (int p=0; p<8; p++) { + for (int q=0; q<8; q++) { + pixdata[pos++] = palette.indexOf(colorIndex, pixels[tileOfs++]); + } + tileOfs += canvasWidth - 8; + } + } + else { + // non-palettized: color is actual 32-bit ARGB value + for (int p=0; p<8; p++) { + for (int q=0; q<8; q++) { + pixdata[pos++] = pixels[tileOfs++]; + } + tileOfs += canvasWidth - 8; + } + } + codec.encode(pixdata, bits, bitsOfs, stride); + } + else { + // not valid tile, do nothing + } + pixOfs += 8; // next tile column + } + pixOfs += canvasWidth*7; // next tile row + } + } + +/** +* +* Paints tiles and grid. +* +**/ + + public void paintComponent(Graphics g) { + super.paintComponent(g); + // draw gridlines if necessary + if (showTileGrid) { + drawTileGrid(g); + } + } + +/** +* +* Draws atomic tile grid. +* +**/ + + private void drawTileGrid(Graphics g) { + g.setColor(Color.red); // gridline color + // draw horizontal lines + for (int i=1; i=0; j--) { + setPixel(i, j, pix[ofs++]); + } + } + packPixels(); + setScale(scale); + } + +/** +* +* Rotates the grid of tiles 90 degrees right (clockwise). +* +**/ + + public void rotateRight() { + int[] pix = getPixels(); + setGridSize(rows, cols); + int ofs = 0; + for (int i=canvasWidth-1; i>=0; i--) { + for (int j=0; j> shift); + shift += shiftStep; + } + return bytes; + } + +/** +* +* Converts bytes from given array to a value, according to current endianness. +* @param offset Where to start reading the bytes that make up the value. +* +**/ + + public int fromBytes(byte[] bytes, int offset) { + int shift = startShift; + int value = 0; + for (int i=0; ibits bits of information. +* +**/ + + private static int getBytesRequired(int bits) { + int bytes = bits / 8; + int extrabits = bits % 8; + if (extrabits != 0) bytes++; + return bytes; + } + + public String toString() { + return description; + } + +} \ No newline at end of file diff --git a/src/tm/colorcodecs/DirectColorCodec.java b/src/tm/colorcodecs/DirectColorCodec.java new file mode 100644 index 0000000..8b11ad0 --- /dev/null +++ b/src/tm/colorcodecs/DirectColorCodec.java @@ -0,0 +1,169 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.colorcodecs; + +/** +* +* A DirectColorCodec translates pixels exactly the same way as +* a direct-color tile codec. +* The composition of a pixel is described by Red, Green, +* Blue and Alpha masks. +* +**/ + +public class DirectColorCodec extends ColorCodec { + + private int rmask; // bitmask for Red component + private int gmask; // bitmask for Green component + private int bmask; // bitmask for Blue component + private int amask; // bitmask for Alpha component + + // how much each component must be shifted to be transformed to a 32-bit ARGB int-packed Java pixel. + // these are pre-calculated in the constructor and used for decoding/encoding individual pixels. + private int rshift; + private int gshift; + private int bshift; + private int ashift; + + public DirectColorCodec(String id, int bitsPerPixel, int rmask, int gmask, int bmask, int amask, String description) { + super(id, bitsPerPixel, description); + this.rmask = rmask; + this.gmask = gmask; + this.bmask = bmask; + this.amask = amask; + // calculate the shifts + rshift = 23 - msb(rmask); + gshift = 15 - msb(gmask); + bshift = 7 - msb(bmask); + ashift = 31 - msb(amask); + } + +/** +* Gets the position of the most significant set bit in the given int. +**/ + + private static int msb(int mask) { + for (int i=31; i>=0; i--) { + if ((mask & 0x80000000) != 0) { + return i; + } + mask <<= 1; + } + return -1; // no bits set + } + +/** +* +* +**/ + + public int decode(int value) { + int r, g, b, a; + // decode R component + r = value & rmask; + if (rshift < 0) { + r >>= -rshift; + } + else { + r <<= rshift; + } + + // decode G component + g = value & gmask; + if (gshift < 0) { + g >>= -gshift; + } + else { + g <<= gshift; + } + + // decode B component + b = value & bmask; + if (bshift < 0) { + b >>= -bshift; + } + else { + b <<= bshift; + } + + // decode A component + a = value & amask; + if (ashift < 0) { + a >>= -ashift; + } + else { + a <<= ashift; + } + + // final pixel + return (a | r | g | b); + } + +/** +* +* +**/ + + public int encode(int argb) { + int r, g, b, a; + // encode R component + r = argb; + if (rshift < 0) { + r <<= -rshift; + } + else { + r >>= rshift; + } + r &= rmask; + + // encode G component + g = argb; + if (gshift < 0) { + g <<= -gshift; + } + else { + g >>= gshift; + } + g &= gmask; + + // encode B component + b = argb; + if (bshift < 0) { + b <<= -bshift; + } + else { + b >>= bshift; + } + b &= bmask; + + // encode A component + a = argb; + if (ashift < 0) { + a <<= -ashift; + } + else { + a >>= ashift; + } + a &= amask; + + // final value + return (a | r | g | b); + } + +} \ No newline at end of file diff --git a/src/tm/colorcodecs/IndexedColorCodec.java b/src/tm/colorcodecs/IndexedColorCodec.java new file mode 100644 index 0000000..b0706b8 --- /dev/null +++ b/src/tm/colorcodecs/IndexedColorCodec.java @@ -0,0 +1,75 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.colorcodecs; + +/** +* +* An IndexedColorCodec translates pixels according to a +* pre-defined array of 32-bit ARGB values. +* +**/ + +public class IndexedColorCodec extends ColorCodec { + + private int[] colorTable; // table of pre-defined ARGB values + + public IndexedColorCodec(String id, int bitsPerPixel, int[] colorTable, String description) { + super(id, bitsPerPixel, description); + this.colorTable = colorTable; + } + +/** +* +* To decode, simply look up the table. +* +**/ + + public int decode(int value) { + if (value < colorTable.length) { + return colorTable[value]; + } + return 0; // undefined + } + +/** +* +* To encode, find the closest match in the table. +* +**/ + + public int encode(int argb) { + int targetR = (argb & 0x00FF0000) >> 16; + int targetG = (argb & 0x0000FF00) >> 8; + int targetB = (argb & 0x000000FF); + int bestEntry=0, bestDiff=1000000; + for (int i=0; i> 16; + int g = (val & 0x0000FF00) >> 8; + int b = (val & 0x000000FF); + int diff = Math.abs(targetR - r) + Math.abs(targetG - g) + Math.abs(targetB - b); + if (diff < bestDiff) { + bestDiff = diff; + bestEntry = i; + } + } + return bestEntry; + } + +} \ No newline at end of file diff --git a/src/tm/filelistener/GameBoyAdvanceFileListener.java b/src/tm/filelistener/GameBoyAdvanceFileListener.java new file mode 100644 index 0000000..40e291d --- /dev/null +++ b/src/tm/filelistener/GameBoyAdvanceFileListener.java @@ -0,0 +1,104 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.filelistener; + +/** +* +* Listener for Game Boy Advance (*.gba) files. +* +**/ + +public class GameBoyAdvanceFileListener extends TMFileListener { + + private static final int[] nintendoLogo = { + 0x24,0xFF,0xAE,0x51,0x69,0x9A,0xA2,0x21,0x3D,0x84,0x82,0x0A,0x84,0xE4,0x09,0xAD, + 0x11,0x24,0x8B,0x98,0xC0,0x81,0x7F,0x21,0xA3,0x52,0xBE,0x19,0x93,0x09,0xCE,0x20, + 0x10,0x46,0x4A,0x4A,0xF8,0x27,0x31,0xEC,0x58,0xC7,0xE8,0x33,0x82,0xE3,0xCE,0xBF, + 0x85,0xF4,0xDF,0x94,0xCE,0x4B,0x09,0xC1,0x94,0x56,0x8A,0xC0,0x13,0x72,0xA7,0xFC, + 0x9F,0x84,0x4D,0x73,0xA3,0xCA,0x9A,0x61,0x58,0x97,0xA3,0x27,0xFC,0x03,0x98,0x76, + 0x23,0x1D,0xC7,0x61,0x03,0x04,0xAE,0x56,0xBF,0x38,0x84,0x00,0x40,0xA7,0x0E,0xFD, + 0xFF,0x52,0xFE,0x03,0x6F,0x95,0x30,0xF1,0x97,0xFB,0xC0,0x85,0x60,0xD6,0x80,0x25, + 0xA9,0x63,0xBE,0x03,0x01,0x4E,0x38,0xE2,0xF9,0xA2,0x34,0xFF,0xBB,0x3E,0x03,0x44, + 0x78,0x00,0x90,0xCB,0x88,0x11,0x3A,0x94,0x65,0xC0,0x7C,0x63,0x87,0xF0,0x3C,0xAF, + 0xD6,0x25,0xE4,0x8B,0x38,0x0A,0xAC,0x72,0x21,0xD4,0xF8,0x07 + } ; + +/** +* +* Detects if this is a Game Boy Advance file. +* The critera are that the extension is gba, that the Nintendo logo +* character data is correct and that the byte at 0xB2 equals 0x96. +* +**/ + + public boolean doFormatDetect(final byte[] data, String extension) { + // verify extension + if (!extension.equals("gba")) { + return false; + } + + // verify Nintendo Logo Character Data + for (int i=0; i> 8) & 0xFF); + data[0xBF] = (byte)(checkSum & 0xFF); + } + +} \ No newline at end of file diff --git a/src/tm/filelistener/GameBoyFileListener.java b/src/tm/filelistener/GameBoyFileListener.java new file mode 100644 index 0000000..27edcda --- /dev/null +++ b/src/tm/filelistener/GameBoyFileListener.java @@ -0,0 +1,156 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.filelistener; + +/** +* +* Listener for Game Boy (*.gb, *.gbc) files. +* +**/ + +public class GameBoyFileListener extends TMFileListener { + + private static final int[] scrollingNintendoGraphic = { + 0xCE,0xED,0x66,0x66,0xCC,0x0D,0x00,0x0B,0x03,0x73,0x00,0x83,0x00,0x0C,0x00,0x0D, + 0x00,0x08,0x11,0x1F,0x88,0x89,0x00,0x0E,0xDC,0xCC,0x6E,0xE6,0xDD,0xDD,0xD9,0x99, + 0xBB,0xBB,0x67,0x63,0x6E,0x0E,0xEC,0xCC,0xDD,0xDC,0x99,0x9F,0xBB,0xB9,0x33,0x3E + }; + + // cartridge types (TODO: add more types) + private static final int ROM_ONLY = 0x00; + private static final int ROM_MBC1 = 0x01; + private static final int ROM_MBC1_RAM = 0x02; + private static final int ROM_MBC1_RAM_BATTERY = 0x03; + private static final int ROM_MBC2 = 0x05; + private static final int ROM_MBC2_BATTERY = 0x06; + private static final int ROM_RAM = 0x08; + private static final int ROM_RAM_BATTERY = 0x09; + private static final int ROM_HUC1_RAM_BATTERY = 0xFF; + + // cartridge sizes + private static final int SIZE_256K = 0x00; + private static final int SIZE_512K = 0x01; + private static final int SIZE_1M = 0x02; + private static final int SIZE_2M = 0x03; + private static final int SIZE_4M = 0x04; + private static final int SIZE_8M = 0x05; + private static final int SIZE_16M = 0x06; + private static final int SIZE_9M = 0x52; + private static final int SIZE_10M = 0x53; + private static final int SIZE_12M = 0x54; + +/** +* +* Detects if this is a GameBoy file. +* The criteria is that the extension is either gb, gbc or sgb and that +* the scrolling Nintendo graphic data is correct. +* +**/ + + public boolean doFormatDetect(final byte[] data, String extension) { + // verify extension + if (!(extension.equals("gb") + || extension.equals("gbc") + || extension.equals("sgb"))) { + return false; + } + + // verify scrolling Nintendo graphic + for (int i=0; i> 8) & 0xFF); + data[0x14F] = (byte)(checkSum & 0xFF); + } + +} \ No newline at end of file diff --git a/src/tm/filelistener/INESFileListener.java b/src/tm/filelistener/INESFileListener.java new file mode 100644 index 0000000..23127f2 --- /dev/null +++ b/src/tm/filelistener/INESFileListener.java @@ -0,0 +1,50 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.filelistener; + +/** +* +* +**/ + +public class INESFileListener extends TMFileListener { + + private static int[] iNES_ID = { 0x4E,0x45,0x53,0x1A }; + + public boolean doFormatDetect(final byte[] data, String extension) { + // verify extension + if (!extension.equals("nes")) { + return false; + } + // verify NES^Z + for (int i=0; i> 8) & 0xFF); + data[0x38F] = (byte)(checkSum & 0xFF); + + // reinterleave data + byte[] block = new byte[16384]; + int blockCount = (data.length-512) / 16384; + for (int i=0; i> 8) & 0xFF); + } + +} \ No newline at end of file diff --git a/src/tm/filelistener/TMFileListener.java b/src/tm/filelistener/TMFileListener.java new file mode 100644 index 0000000..bea82ef --- /dev/null +++ b/src/tm/filelistener/TMFileListener.java @@ -0,0 +1,64 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.filelistener; + +/** +* +* Abstract class that defines the interface for filelisteners. +* A filelistener is an object that is notified when a file has +* been fully loaded into memory, as well as when it is about to be saved. +* At these times it may perform various operations on the data being saved, +* such as repairing checksums. +* The fileformatlistener also has to implement a method that determines if +* the file being saved is indeed of a supported format. This usually involves +* checking the header (verifying ID strings and such). +* +**/ + +public abstract class TMFileListener { + +/** +* +* This method is invoked when a file has been loaded, to give the file +* listener a chance to detect the file format. If it returns true, +* this file listener will receive all subsequent fileLoaded() and fileSaved() +* events for the file. +* +**/ + + public abstract boolean doFormatDetect(final byte[] data, String extension); + +/** +* +* This method is invoked when the file has been loaded (and doFormatDetect() has +* already returned true.) +* +**/ + + public abstract void fileLoaded(byte[] data, String extension); + +/** +* +* This method is invoked when the file is about to be saved. +* +**/ + + public abstract void fileSaving(byte[] data, String extension); + +} \ No newline at end of file diff --git a/src/tm/fileselection/TMApprovedFileOpenChooser.java b/src/tm/fileselection/TMApprovedFileOpenChooser.java new file mode 100644 index 0000000..df39584 --- /dev/null +++ b/src/tm/fileselection/TMApprovedFileOpenChooser.java @@ -0,0 +1,72 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.fileselection; + +import java.io.File; +import javax.swing.JFileChooser; +import javax.swing.filechooser.FileFilter; +import javax.swing.JOptionPane; + +/** +* +* A filechooser that verifies that the selected file exists and +* that it is readable before it lets the user proceed. +* +**/ + + public class TMApprovedFileOpenChooser extends JFileChooser { + + public void approveSelection() { + File file = getSelectedFile(); + // verify that it has proper extension + FileFilter ff = getFileFilter(); + if (!ff.accept(file)) { + String absPath = file.getAbsolutePath(); + if (!absPath.endsWith(".")) absPath += "."; + String[] exts = ((TMFileFilter)ff).getExtensions(); + File tempFile=null; + for (int i=0; i 0 && i < s.length() - 1) { + ext = s.substring(i+1).toLowerCase(); + } + return ext; + } + +} \ No newline at end of file diff --git a/src/tm/fileselection/TMPaletteFileFilter.java b/src/tm/fileselection/TMPaletteFileFilter.java new file mode 100644 index 0000000..63cd899 --- /dev/null +++ b/src/tm/fileselection/TMPaletteFileFilter.java @@ -0,0 +1,88 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.fileselection; + +/** +* +* +* +**/ + +public class TMPaletteFileFilter extends TMFileFilter { + + private String codecID; // color codec + private int size; + private int offset; + private int endianness; + +/** +* +* +* +**/ + + public TMPaletteFileFilter(String extlist, String description, String codecID, int size, int offset, int endianness) { + super(extlist, description); + this.codecID = codecID; + this.size = size; + this.offset = offset; + this.endianness = endianness; + } + +/** +* +* +* +**/ + + public String getCodecID() { + return codecID; + } + +/** +* +* +* +**/ + + public int getSize() { + return size; + } + +/** +* +* +* +**/ + + public int getOffset() { + return offset; + } + +/** +* +* +* +**/ + + public int getEndianness() { + return endianness; + } + +} \ No newline at end of file diff --git a/src/tm/fileselection/TMTileCodecFileFilter.java b/src/tm/fileselection/TMTileCodecFileFilter.java new file mode 100644 index 0000000..9d924ea --- /dev/null +++ b/src/tm/fileselection/TMTileCodecFileFilter.java @@ -0,0 +1,78 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.fileselection; + +public class TMTileCodecFileFilter extends TMFileFilter { + + private int defaultMode; + private String codecID; + +/** +* +* +* +**/ + + public TMTileCodecFileFilter(String extlist, String description, String codecID, int defaultMode) { + super(extlist, description); + setCodecID(codecID); + setDefaultMode(defaultMode); + } + +/** +* +* +* +**/ + + public void setCodecID(String codecID) { + this.codecID = codecID; + } + +/** +* +* +* +**/ + + public void setDefaultMode(int defaultMode) { + this.defaultMode = defaultMode; + } + +/** +* +* +* +**/ + + public int getDefaultMode() { + return defaultMode; + } + +/** +* +* +* +**/ + + public String getCodecID() { + return codecID; + } + +} \ No newline at end of file diff --git a/src/tm/gfxlibs/BMPLoader.java b/src/tm/gfxlibs/BMPLoader.java new file mode 100644 index 0000000..1b08160 --- /dev/null +++ b/src/tm/gfxlibs/BMPLoader.java @@ -0,0 +1,543 @@ +// + +// This code was taken and cleaned up from a + +// Javaworld tips and tricks column + +// + +package tm.gfxlibs; + +import java.awt.image.*; +import java.awt.*; +import java.io.*; +import javax.swing.*; + + +// + +// really just a collection of methods to read a BMP file + +// + +public class BMPLoader + +{ + + + // build an int from a byte array - convert little to big endian + + public static int constructInt(byte[] in,int offset) { + int ret = ((int)in[offset + 3] & 0xff); + ret = (ret << 8) | ((int)in[offset + 2] & 0xff); + ret = (ret << 8) | ((int)in[offset + 1] & 0xff); + ret = (ret << 8) | ((int)in[offset + 0] & 0xff); + return(ret); + } + + // build an int from a byte array - convert little to big endian + + // set high order bytes to 0xfff + + public static int constructInt3(byte[] in,int offset) { + int ret = 0xff; + ret = (ret << 8) | ((int)in[offset + 2] & 0xff); + ret = (ret << 8) | ((int)in[offset + 1] & 0xff); + ret = (ret << 8) | ((int)in[offset + 0] & 0xff); + return(ret); + } + + + + // build an int from a byte array - convert little to big endian + + public static long constructLong(byte[] in,int offset) { + long ret = ((long)in[offset + 7] & 0xff); + ret |= (ret << 8) | ((long)in[offset + 6] & 0xff); + ret |= (ret << 8) | ((long)in[offset + 5] & 0xff); + ret |= (ret << 8) | ((long)in[offset + 4] & 0xff); + ret |= (ret << 8) | ((long)in[offset + 3] & 0xff); + ret |= (ret << 8) | ((long)in[offset + 2] & 0xff); + ret |= (ret << 8) | ((long)in[offset + 1] & 0xff); + ret |= (ret << 8) | ((long)in[offset + 0] & 0xff); + return(ret); + } + + + + + + // build an double from a byte array - convert little to big endian + + public static double constructDouble(byte[] in,int offset) { + long ret = constructLong(in,offset); + return(Double.longBitsToDouble(ret)); + } + + + + // build an short from a byte array - convert little to big endian + + public static short constructShort(byte[] in,int offset) { + short ret = (short)(in[(offset + 1)] & 0xFF); + ret = (short)(ret << 8 | (short)(in[(offset + 0)] & 0xFF)); + return ret; + } + + + + // + + // internal class representing a bitmap header structure + + // with code to read it from a file + + static class BitmapHeader { + public int nsize; + public int nbisize; + public int nwidth; + public int nheight; + public int nplanes; + public int nbitcount; + public int ncompression; + public int nsizeimage; + public int nxpm; + public int nypm; + public int nclrused; + public int nclrimp; + + + // read in the bitmap header + + public void read(FileInputStream fs) throws IOException + + { + final int bflen=14; // 14 byte BITMAPFILEHEADER + + byte bf[]=new byte[bflen]; + fs.read(bf,0,bflen); + final int bilen=40; // 40-byte BITMAPINFOHEADER + + byte bi[]=new byte[bilen]; + fs.read(bi,0,bilen); + + + // Interperet data. + + nsize = constructInt(bf,2); + // System.out.println("File type is :"+(char)bf[0]+(char)bf[1]); + // System.out.println("Size of file is :"+nsize); + + + nbisize = constructInt(bi,2); + // System.out.println("Size of bitmapinfoheader is :"+nbisize); + + + nwidth = constructInt(bi,4); + // System.out.println("Width is :"+nwidth); + + + nheight = constructInt(bi,8); + // System.out.println("Height is :"+nheight); + + + nplanes = constructShort(bi,12); //(((int)bi[13]&0xff)<<8) | (int)bi[12]&0xff; + // System.out.println("Planes is :"+nplanes); + + + nbitcount = constructShort(bi,14); //(((int)bi[15]&0xff)<<8) | (int)bi[14]&0xff; + // System.out.println("BitCount is :"+nbitcount); + + + // Look for non-zero values to indicate compression + + ncompression = constructInt(bi,16); + // System.out.println("Compression is :"+ncompression); + + + nsizeimage = constructInt(bi,20); + // System.out.println("SizeImage is :"+nsizeimage); + + + nxpm = constructInt(bi,24); + // System.out.println("X-Pixels per meter is :"+nxpm); + + + nypm = constructInt(bi,28); + // System.out.println("Y-Pixels per meter is :"+nypm); + + + nclrused = constructInt(bi,32); + // System.out.println("Colors used are :"+nclrused); + + + nclrimp = constructInt(bi,36); + // System.out.println("Colors important are :"+nclrimp); + } + + } + + + + public static Image read(FileInputStream fs) + + { + try { + BitmapHeader bh = new BitmapHeader(); + bh.read(fs); + + + if (bh.nbitcount==24) + + return(readMap24(fs,bh)); + + + if (bh.nbitcount==32) + + return(readMap32(fs,bh)); + + + if (bh.nbitcount==8) + + return(readMap8(fs,bh)); + + + fs.close(); + } + + catch (IOException e) + + { + // System.out.println("Caught exception in loadbitmap!"); + } + + return(null); + } + + /** + + readMap24 internal routine to read the bytes in a 24 bit bitmap + + + + Arguments: + + fs - file stream + + bh - header struct + + Returns: + + Image Object, be sure to check for (Image)null !!!! + + + + */ + + + + protected static Image readMap32(FileInputStream fs,BitmapHeader bh) throws IOException + + { + Image image; + // No Palatte data for 24-bit format but scan lines are + + // padded out to even 4-byte boundaries. + + int xwidth = bh.nsizeimage / bh.nheight; + int ndata[] = new int [bh.nheight * bh.nwidth]; + byte brgb[] = new byte [ bh.nwidth * 4 * bh.nheight]; + fs.read (brgb, 0, bh.nwidth * 4 * bh.nheight); + int nindex = 0; + for (int j = 0; j < bh.nheight; j++) + + { + for (int i = 0; i < bh.nwidth; i++) + + { + ndata [bh.nwidth * (bh.nheight - j - 1) + i] = constructInt3(brgb,nindex); + nindex += 4; + } + + } + + + + image = Toolkit.getDefaultToolkit().createImage + + ( new MemoryImageSource(bh.nwidth, bh.nheight, + + ndata, 0, bh.nwidth)); + fs.close(); + return(image); + } + + + + /** + + readMap24 internal routine to read the bytes in a 24 bit bitmap + + + + Arguments: + + fs - file stream + + bh - header struct + + Returns: + + Image Object, be sure to check for (Image)null !!!! + + + + */ + + + + protected static Image readMap24(FileInputStream fs,BitmapHeader bh) throws IOException + + { + Image image; + // No Palatte data for 24-bit format but scan lines are + + // padded out to even 4-byte boundaries. + + int npad = (bh.nsizeimage / bh.nheight) - bh.nwidth * 3; + int ndata[] = new int [bh.nheight * bh.nwidth]; + byte brgb[] = new byte [( bh.nwidth + npad) * 3 * bh.nheight]; + fs.read (brgb, 0, (bh.nwidth + npad) * 3 * bh.nheight); + int nindex = 0; + for (int j = 0; j < bh.nheight; j++) + + { + for (int i = 0; i < bh.nwidth; i++) + + { + ndata [bh.nwidth * (bh.nheight - j - 1) + i] = constructInt3(brgb,nindex); + nindex += 3; + } + + nindex += npad; + } + + + + image = Toolkit.getDefaultToolkit().createImage + + ( new MemoryImageSource(bh.nwidth, bh.nheight, + + ndata, 0, bh.nwidth)); + fs.close(); + return(image); + } + + /** + + readMap8 internal routine to read the bytes in a 8 bit bitmap + + + + Arguments: + + fs - file stream + + bh - header struct + + Returns: + + Image Object, be sure to check for (Image)null !!!! + + + + */ + + protected static Image readMap8(FileInputStream fs,BitmapHeader bh) throws IOException + + { + Image image; + + + // Have to determine the number of colors, the clrsused + + // parameter is dominant if it is greater than zero. If + + // zero, calculate colors based on bitsperpixel. + + int nNumColors = 0; + if (bh.nclrused > 0) + + { + nNumColors = bh.nclrused; + } + + else + + { + nNumColors = (1&0xff)<< bh.nbitcount; + } + + // System.out.println("The number of Colors is"+nNumColors); + + + // Some bitmaps do not have the sizeimage field calculated + + // Ferret out these cases and fix 'em. + + if (bh.nsizeimage == 0) + + { + bh.nsizeimage = ((((bh.nwidth* bh.nbitcount)+31) & ~31 ) >> 3); + bh.nsizeimage *= bh.nheight; + // System.out.println("nsizeimage (backup) is"+nsizeimage); + } + + + + // Read the palatte colors. + + int npalette[] = new int [nNumColors]; + byte bpalette[] = new byte [nNumColors*4]; + fs.read (bpalette, 0, nNumColors*4); + int nindex8 = 0; + for (int n = 0; n < nNumColors; n++) + + { + npalette[n] = constructInt3(bpalette,nindex8); + nindex8 += 4; + } + + + + // Read the image data (actually indices into the palette) + + // Scan lines are still padded out to even 4-byte + + // boundaries. + + int npad8 = (bh.nsizeimage / bh.nheight) - bh.nwidth; + // System.out.println("nPad is:"+npad8); + + + int ndata8[] = new int [bh.nwidth * bh.nheight]; + byte bdata[] = new byte [(bh.nwidth+npad8)* bh.nheight]; + fs.read (bdata, 0, (bh.nwidth+npad8)*bh.nheight); + nindex8 = 0; + for (int j8 = 0; j8 < bh.nheight; j8++) + { + for (int i8 = 0; i8 < bh.nwidth; i8++) + { + ndata8[(bh.nwidth * (bh.nheight - j8 - 1) + i8)] = + + npalette[(bdata[nindex8] & 0xFF)]; + nindex8++; + } + nindex8 += npad8; + } + + + + image = Toolkit.getDefaultToolkit().createImage + + ( new MemoryImageSource (bh.nwidth, bh.nheight, + + ndata8, 0, bh.nwidth)); + + + return(image); + } + + + + /** + + load method - see read for details + + + + Arguments: + + sdir and sfile are the result of the FileDialog() + + getDirectory() and getFile() methods. + + + + Returns: + + Image Object, be sure to check for (Image)null !!!! + + + + */ + + public static Image load(String sdir, String sfile) { + return(load(sdir + sfile)); + } + + + + + + /** + + load method - see read for details + + + + Arguments: + + sdir - full path name + + + + Returns: + + Image Object, be sure to check for (Image)null !!!! + + + + */ + + public static Image load(String sdir) + + { + try + + { + FileInputStream fs=new FileInputStream(sdir); + return(read(fs)); + } + + catch(IOException ex) { + return(null); + } + + } + + + +public static void main(String[] args) throws IOException + +{ + if(args.length == 0){ + System.out.println("Usage >java BMPLoader ImageFile.bmp"); + System.exit(0); + } + + FileInputStream in = new FileInputStream(args[0]); + Image TheImage = read(in); + JFrame TheFrame = new JFrame(args[0]); + JLabel TheLabel = new JLabel(new ImageIcon(TheImage)); + TheFrame.getContentPane().add(new JScrollPane(TheLabel)); + TheFrame.setSize(300,300); + TheFrame.setVisible(true); +} + + + +// end class BMPLoader + +} + diff --git a/src/tm/gfxlibs/BMPReader.java b/src/tm/gfxlibs/BMPReader.java new file mode 100644 index 0000000..42e50ed --- /dev/null +++ b/src/tm/gfxlibs/BMPReader.java @@ -0,0 +1,305 @@ +package tm.gfxlibs; + +import java.awt.*; +import java.awt.image.*; +import java.io.*; + +// This class provides a public static method that takes an InputStream +// to a Windows .BMP file and converts it into an ImageProducer via +// a MemoryImageSource. +// You can fetch a .BMP through a URL with the following code: +// URL url = new URL( ) +// Image img = createImage(BMPReader.getBMPImage(url.openStream())); + +public class BMPReader extends Object +{ +// Constants indicating how the data is stored + public static final int BI_RGB = 0; + public static final int BI_RLE8 = 1; + public static final int BI_RLE4 = 2; + + public static ImageProducer getBMPImage(InputStream stream) + throws IOException + { +// The DataInputStream allows you to read in 16 and 32 bit numbers + DataInputStream in = new DataInputStream(stream); + +// Verify that the header starts with 'BM' + + if (in.read() != 'B') { + throw new IOException("Not a .BMP file"); + } + if (in.read() != 'M') { + throw new IOException("Not a .BMP file"); + } + +// Get the total file size + int fileSize = intelInt(in.readInt()); + +// Skip the 2 16-bit reserved words + in.readUnsignedShort(); + in.readUnsignedShort(); + + int bitmapOffset = intelInt(in.readInt()); + + int bitmapInfoSize = intelInt(in.readInt()); + + int width = intelInt(in.readInt()); + int height = intelInt(in.readInt()); + +// Skip the 16-bit bitplane size + in.readUnsignedShort(); + + int bitCount = intelShort(in.readUnsignedShort()); + + int compressionType = intelInt(in.readInt()); + + int imageSize = intelInt(in.readInt()); + +// Skip pixels per meter + in.readInt(); + in.readInt(); + + int colorsUsed = intelInt(in.readInt()); + int colorsImportant = intelInt(in.readInt()); + if (colorsUsed == 0) colorsUsed = 1 << bitCount; + + int colorTable[] = new int[colorsUsed]; + +// Read the bitmap's color table + for (int i=0; i < colorsUsed; i++) { + colorTable[i] = (intelInt(in.readInt()) & 0xffffff) + 0xff000000; + } + +// Create space for the pixels + int pixels[] = new int[width * height]; + +// Read the pixels from the stream based on the compression type + if (compressionType == BI_RGB) { + if (bitCount == 24) { + readRGB24(width, height, pixels, in); + } else { + readRGB(width, height, colorTable, bitCount, + pixels, in); + } + } else if (compressionType == BI_RLE8) { + readRLE(width, height, colorTable, bitCount, + pixels, in, imageSize, 8); + } else if (compressionType == BI_RLE4) { + readRLE(width, height, colorTable, bitCount, + pixels, in, imageSize, 4); + } + +// Create a memory image source from the pixels + return new MemoryImageSource(width, height, pixels, 0, + width); + } + +// Reads in pixels in 24-bit format. There is no color table, and the +// pixels are stored in 3-byte pairs. Oddly, all windows bitmaps are +// stored upside-down - the bottom line is stored first. + + protected static void readRGB24(int width, int height, int pixels[], + DataInputStream in) + throws IOException + { + +// Start storing at the bottom of the array + for (int h = height-1; h >= 0; h--) { + int pos = h * width; + for (int w = 0; w < width; w++) { + +// Read in the red, green, and blue components + int red = in.read(); + int green = in.read(); + int blue = in.read(); + +// Turn the red, green, and blue values into an RGB color with +// an alpha value of 255 (fully opaque) + pixels[pos++] = 0xff000000 + (red << 16) + + (green << 8) + blue; + } + } + } + +// readRGB reads in pixels values that are stored uncompressed. +// The bits represent indices into the color table. + + protected static void readRGB(int width, int height, int colorTable[], + int bitCount, int pixels[], DataInputStream in) + throws IOException + { + +// How many pixels can be stored in a byte? + int pixelsPerByte = 8 / bitCount; + +// A bit mask containing the number of bits in a pixel + int bitMask = (1 << bitCount) - 1; + +// The shift values that will move each pixel to the far right + int bitShifts[] = new int[pixelsPerByte]; + + for (int i=0; i < pixelsPerByte; i++) { + bitShifts[i] = 8 - ((i+1) * bitCount); + } + + int whichBit = 0; + +// Read in the first byte + int currByte = in.read(); + +// Start at the bottom of the pixel array and work up + for (int h=height-1; h >= 0; h--) { + int pos = h * width; + for (int w=0; w < width; w++) { + +// Get the next pixel from the current byte + pixels[pos] = colorTable[ + (currByte >> bitShifts[whichBit]) & + bitMask]; + pos++; + whichBit++; + +// If the current bit position is past the number of pixels in +// a byte, we advance to the next byte + if (whichBit >= pixelsPerByte) { + whichBit = 0; + currByte = in.read(); + } + } + } + } + + +// readRLE reads run-length encoded data in either RLE4 or RLE8 format. + + protected static void readRLE(int width, int height, int colorTable[], + int bitCount, int pixels[], DataInputStream in, + int imageSize, int pixelSize) + throws IOException + { + int x = 0; + int y = height-1; + +// You already know how many bytes are in the image, so only go +// through that many. + + for (int i=0; i < imageSize; i++) { + +// RLE encoding is defined by two bytes + int byte1 = in.read(); + int byte2 = in.read(); + i += 2; + +// If byte 0 == 0, this is an escape code + if (byte1 == 0) { + +// If escaped, byte 2 == 0 means you are at end of line + if (byte2 == 0) { + x = 0; + y--; + +// If escaped, byte 2 == 1 means end of bitmap + } else if (byte2 == 1) { + return; + +// if escaped, byte 2 == 2 adjusts the current x and y by +// an offset stored in the next two words + } else if (byte2 == 2) { + int xoff = (char) intelShort( + in.readUnsignedShort()); + i+= 2; + int yoff = (char) intelShort( + in.readUnsignedShort()); + i+= 2; + x += xoff; + y -= yoff; + +// If escaped, any other value for byte 2 is the number of bytes +// that you should read as pixel values (these pixels are not +// run-length encoded) + } else { + int whichBit = 0; + +// Read in the next byte + int currByte = in.read(); + + i++; + for (int j=0; j < byte2; j++) { + + if (pixelSize == 4) { +// The pixels are 4-bits, so half the time you shift the current byte +// to the right as the pixel value + if (whichBit == 0) { + pixels[y*width+x] = colorTable[(currByte >> 4) + & 0xf]; + } else { + +// The rest of the time, you mask out the upper 4 bits, save the pixel +// value, then read in the next byte + + pixels[y*width+x] = colorTable[currByte & 0xf]; + currByte = in.read(); + i++; + } + } else { + pixels[y*width+x] = colorTable[currByte]; + currByte = in.read(); + i++; + } + x++; + if (x >= width) { + x = 0; + y--; + } + } +// The pixels must be word-aligned, so if you read an uneven number of +// bytes, read and ignore a byte to get aligned again. + if ((byte2 & 1) == 1) { + in.read(); + i++; + } + } + + +// If the first byte was not 0, it is the number of pixels that +// are encoded by byte 2 + } else { + for (int j=0; j < byte1; j++) { + + if (pixelSize == 4) { +// If j is odd, use the upper 4 bits + if ((j & 1) == 0) { + pixels[y*width+x] = colorTable[(byte2 >> 4) & 0xf]; + } else { + pixels[y*width+x+1] = colorTable[byte2 & 0xf]; + } + } else { + pixels[y*width+x+1] = colorTable[byte2]; + } + x++; + if (x >= width) { + x = 0; + y--; + } + } + } + } + } +// intelShort converts a 16-bit number stored in intel byte order into +// the local host format + + protected static int intelShort(int i) + { + return ((i >> 8) & 0xff) + ((i << 8) & 0xff00); + } + +// intelInt converts a 32-bit number stored in intel byte order into +// the local host format + + protected static int intelInt(int i) + { + return ((i & 0xff) << 24) + ((i & 0xff00) << 8) + + ((i & 0xff0000) >> 8) + ((i >> 24) & 0xff); + } +} \ No newline at end of file diff --git a/src/tm/gfxlibs/GIFOutputStream.java b/src/tm/gfxlibs/GIFOutputStream.java new file mode 100644 index 0000000..7408180 --- /dev/null +++ b/src/tm/gfxlibs/GIFOutputStream.java @@ -0,0 +1,1010 @@ +/* + Class: org.shetline.io.GIFOutputStream + + Copyright (c) 2000, 2001 by Kerry Shetline, kerry@shetline.com. + + This code is free for public use in any non-commercial application. All + other uses are restricted without prior consent of the author, Kerry + Shetline. The author assumes no liability for the suitability of this + code in any application. + + Note: This code does *NOT* implement LZW compression. While the output + of the compression routine is compatible with LZW, only a simple run- + length compression is performed. The degree of compression as compared + to LZW is not as high, but execution time is faster, and LZW licensing + issues are avoided. Depending on image size and image complexity, the + differences in compression may or may not have practical significance + for particular applications. + + Date Comments + ----------- -------- + 2000 SEP 30 First released version. + 2001 MAR 18 Replaced byte-by-byte specification of 256-color table with + a short code segment to generate the same table. + 2001 JUN 10 Added DITHERED_216_COLORS option. + 2001 AUG 21 Fixed a bug where single-color images would produce an + invalid GIF stream when using ORIGINAL_COLOR mode. GIF color + tables need to have at least two entries, so if the image only + has one color, an unused entry of either black or white is + added to the table to make it a valid length. +*/ + +package tm.gfxlibs; + +import java.io.*; +import java.awt.*; +import java.awt.image.*; +import java.util.Hashtable; +import java.util.Enumeration; + +public class GIFOutputStream extends FilterOutputStream +{ + public static final int ORIGINAL_COLOR = 0; + public static final int BLACK_AND_WHITE = 1; + public static final int GRAYSCALE_16 = 2; + public static final int GRAYSCALE_256 = 3; + public static final int STANDARD_16_COLORS = 4; + public static final int STANDARD_256_COLORS = 5; + public static final int DITHERED_216_COLORS = 6; + + public static final int NO_ERROR = 0; + public static final int IMAGE_LOAD_FAILED = 1; + public static final int TOO_MANY_COLORS = 2; + public static final int INVALID_COLOR_MODE = 3; + + protected static final int BLACK_INDEX = 0; + protected static final int WHITE_INDEX = 1; + + protected static final int[] standard16 = + { + 0x000000, + 0xFF0000, 0x00FF00, 0x0000FF, + 0x00FFFF, 0xFF00FF, 0xFFFF00, + 0x800000, 0x008000, 0x000080, + 0x008080, 0x800080, 0x808000, + 0x808080, 0xC0C0C0, + 0xFFFFFF + }; + + protected static final int[] standard256 = new int[256]; + + protected static int ditherPattern[][] = {{ 8, 184, 248, 216}, + {120, 56, 152, 88}, + { 40, 232, 24, 200}, + {168, 104, 136, 72}}; + + protected int errorStatus = NO_ERROR; + + static + { + // Set up a standard 256-color table. + + int n, j, r, g, b; + + standard256[0] = 0x000000; + + n = 40; + + // 0x33 multiples, starting at index 41 (black stored at index 40 gets replaced with 0xEE0000 + for (r = 0; r < 6; ++r) + for (g = 0; g < 6; ++g) + for (b = 0; b < 6; ++b) + standard256[n++] = 0x330000 * r | 0x003300 * g | 0x000033 * b; + + n = 1; + + for (j = 0; j < 10; ++j) { + // Shades of gray w/o 0x33 multiples, starting at index 1 + standard256[j + 1] = 0x111111 * n; + // Shades of blue w/o 0x33 multiples, starting at index 11 + standard256[j + 11] = 0x000011 * n; + // Shades of green w/o 0x33 multiples, starting at index 21 + standard256[j + 21] = 0x001100 * n; + // Shades of red w/o 0x33 multiples, starting at index 31 + standard256[j + 31] = 0x110000 * n; + + ++n; + + if (n % 3 == 0) + ++n; + } + } + + public static int writeGIF(OutputStream out, Image image) throws IOException + { + return writeGIF(out, image, ORIGINAL_COLOR, null); + } + + public static int writeGIF(OutputStream out, Image image, int colorMode) throws IOException + { + return writeGIF(out, image, colorMode, null); + } + + public static int writeGIF(OutputStream out, Image image, int colorMode, Color transparentColor) throws IOException + { + GIFOutputStream gifOut = new GIFOutputStream(out); + + gifOut.write(image, colorMode, transparentColor); + + int res = gifOut.getErrorStatus(); + + gifOut.close(); + + return res; + } + + public GIFOutputStream(OutputStream out) + { + super(out); + } + + public int getErrorStatus() { return errorStatus; } + + public void write(Image image) throws IOException + { + write(image, ORIGINAL_COLOR, null); + } + + public void write(Image image, int colorMode) throws IOException + { + write(image, colorMode, null); + } + + public void write(Image image, Color transparentColor) throws IOException + { + write(image, ORIGINAL_COLOR, transparentColor); + } + + public void write(Image image, int colorMode, Color transparentColor) throws IOException + { + errorStatus = NO_ERROR; + + if (image == null) + return; + + PixelGrabber pg = new PixelGrabber(image, 0, 0, -1, -1, true); + + try { + pg.grabPixels(); + } catch (InterruptedException e) { + errorStatus = IMAGE_LOAD_FAILED; + return; + } + + if ((pg.status() & ImageObserver.ABORT) != 0) { + errorStatus = IMAGE_LOAD_FAILED; + return; + } + + int[] pixels = (int[]) pg.getPixels(); + int width = pg.getWidth(); + int height = pg.getHeight(); + int colorCount = 0; + int[] colorTable = null; + byte[] bytePixels = null; + +////// do color reduction +/* int[][] pixxies = new int[height][width]; + for (int i=0; i 256) { + errorStatus = TOO_MANY_COLORS; + return; + } + colorTable = createColorTable(colorSet, colorCount); + bytePixels = createBytePixels(pixels, colorSet); + break; + + case BLACK_AND_WHITE: + colorCount = 2; + colorTable = createBWTable(); + bytePixels = createBWBytePixels(pixels); + break; + + case GRAYSCALE_16: + colorCount = 16; + colorTable = create16GrayTable(); + bytePixels = create16GrayBytePixels(pixels); + break; + + case GRAYSCALE_256: + colorCount = 256; + colorTable = create256GrayTable(); + bytePixels = create256GrayBytePixels(pixels); + break; + + case STANDARD_16_COLORS: + colorCount = 16; + colorTable = createStd16ColorTable(); + bytePixels = createStd16ColorBytePixels(pixels); + break; + + case STANDARD_256_COLORS: + colorCount = 256; + colorTable = createStd256ColorTable(); + bytePixels = createStd256ColorBytePixels(pixels, width, false); + break; + + case DITHERED_216_COLORS: + colorCount = 216; + colorTable = createStd216ColorTable(); + bytePixels = createStd256ColorBytePixels(pixels, width, true); + break; + + default: + errorStatus = INVALID_COLOR_MODE; + return; + } + + pixels = null; + + int cc1 = colorCount - 1; + int bitsPerPixel = 0; + + while (cc1 != 0) { + ++bitsPerPixel; + cc1 >>= 1; + } + + writeGIFHeader(width, height, bitsPerPixel); + + writeColorTable(colorTable, bitsPerPixel); + + if (transparentColor != null) + writeGraphicControlExtension(transparentColor, colorTable); + + writeImageDescriptor(width, height); + + writeCompressedImageData(bytePixels, bitsPerPixel); + + write(0x00); // Terminate picture data. + + write(0x3B); // GIF file terminator. + } + + protected Hashtable getColorSet(int[] pixels) + { + Hashtable colorSet = new Hashtable(); + boolean[] checked = new boolean[pixels.length]; + int needsChecking = pixels.length; + int color; + int colorIndex = 0; + Integer key; + + for (int j = 0; j < pixels.length && needsChecking > 0; ++j) { + if (!checked[j]) { + color = pixels[j] & 0x00FFFFFF; + checked[j] = true; + --needsChecking; + + key = new Integer(color); + colorSet.put(key, new Integer(colorIndex)); + if (++colorIndex > 256) + break; + + for (int j2 = j + 1; j2 < pixels.length; ++j2) { + if ((pixels[j2] & 0x00FFFFFF) == color) { + checked[j2] = true; + --needsChecking; + } + } + } + } + + if (colorIndex == 1) { + if (colorSet.get(new Integer(0)) == null) + colorSet.put(new Integer(0), new Integer(1)); + else + colorSet.put(new Integer(0xFFFFFF), new Integer(1)); + } + + return colorSet; + } + + protected int[] createColorTable(Hashtable colorSet, int colorCount) + { + int[] colorTable = new int[colorCount]; + Integer key; + + for (Enumeration e = colorSet.keys(); e.hasMoreElements(); ) { + key = (Integer) e.nextElement(); + colorTable[((Integer) colorSet.get(key)).intValue()] = key.intValue(); + } + + return colorTable; + } + + protected byte[] createBytePixels(int[] pixels, Hashtable colorSet) + { + byte[] bytePixels = new byte[pixels.length]; + Integer key; + int colorIndex; + + for (int j = 0; j < pixels.length; ++j) { + key = new Integer(pixels[j] & 0x00FFFFFF); + colorIndex = ((Integer) colorSet.get(key)).intValue(); + bytePixels[j] = (byte) colorIndex; + } + + return bytePixels; + } + + protected int[] createBWTable() + { + int[] colorTable = new int[2]; + + colorTable[BLACK_INDEX] = 0x000000; + colorTable[WHITE_INDEX] = 0xFFFFFF; + + return colorTable; + } + + protected byte[] createBWBytePixels(int[] pixels) + { + byte[] bytePixels = new byte[pixels.length]; + + for (int j = 0; j < pixels.length; ++j) { + if (grayscaleValue(pixels[j]) < 0x80) + bytePixels[j] = (byte) BLACK_INDEX; + else + bytePixels[j] = (byte) WHITE_INDEX; + } + + return bytePixels; + } + + protected int[] create16GrayTable() + { + int[] colorTable = new int[16]; + + for (int j = 0; j < 16; ++j) + colorTable[j] = 0x111111 * j; + + return colorTable; + } + + protected byte[] create16GrayBytePixels(int[] pixels) + { + byte[] bytePixels = new byte[pixels.length]; + + for (int j = 0; j < pixels.length; ++j) { + bytePixels[j] = (byte) (grayscaleValue(pixels[j]) / 16); + } + + return bytePixels; + } + + protected int[] create256GrayTable() + { + int[] colorTable = new int[256]; + + for (int j = 0; j < 256; ++j) + colorTable[j] = 0x010101 * j; + + return colorTable; + } + + protected byte[] create256GrayBytePixels(int[] pixels) + { + byte[] bytePixels = new byte[pixels.length]; + + for (int j = 0; j < pixels.length; ++j) { + bytePixels[j] = (byte) grayscaleValue(pixels[j]); + } + + return bytePixels; + } + + protected int[] createStd16ColorTable() + { + int[] colorTable = new int[16]; + + System.arraycopy(standard16, 0, colorTable, 0, 16); + + return colorTable; + } + + protected byte[] createStd16ColorBytePixels(int[] pixels) + { + byte[] bytePixels = new byte[pixels.length]; + int color; + int minError = 0; + int error; + int minIndex; + + for (int j = 0; j < pixels.length; ++j) { + color = pixels[j] & 0xFFFFFF; + minIndex = -1; + + for (int k = 0; k < 16; ++k) { + error = colorMatchError(color, standard16[k]); + if (error < minError || minIndex < 0) { + minError = error; + minIndex = k; + } + } + + bytePixels[j] = (byte) minIndex; + } + + return bytePixels; + } + + protected int[] createStd256ColorTable() + { + int[] colorTable = new int[256]; + + System.arraycopy(standard256, 0, colorTable, 0, 256); + + return colorTable; + } + + protected int[] createStd216ColorTable() + { + int[] colorTable = new int[216]; + + colorTable[0] = 0x000000; + + System.arraycopy(standard256, 41, colorTable, 1, 215); + + return colorTable; + } + + protected byte[] createStd256ColorBytePixels(int[] pixels, int width, boolean dither) + { + byte[] bytePixels = new byte[pixels.length]; + int color; + int minError = 0; + int error; + int minIndex; + int sampleIndex; + int r, g, b; + int r2, g2, b2; + int x, y; + int threshold; + + for (int j = 0; j < pixels.length; ++j) { + color = pixels[j] & 0xFFFFFF; + minIndex = -1; + + r = (color & 0xFF0000) >> 16; + g = (color & 0x00FF00) >> 8; + b = color & 0x0000FF; + + r2 = r / 0x33; + g2 = g / 0x33; + b2 = b / 0x33; + + if (dither) { + x = j % width; + y = j / width; + threshold = ditherPattern[x % 4][y % 4] / 5; + + if (r2 < 5 && r % 0x33 >= threshold) + ++r2; + + if (g2 < 5 && g % 0x33 >= threshold) + ++g2; + + if (b2 < 5 && b % 0x33 >= threshold) + ++b2; + + bytePixels[j] = (byte) (r2 * 36 + g2 * 6 + b2); + } + else { + // Try to match color to a 0x33-multiple color. + + for (int r0 = r2; r0 <= r2 + 1 && r0 < 6; ++r0) { + for (int g0 = g2; g0 <= g2 + 1 && g0 < 6; ++g0) { + for (int b0 = b2; b0 <= b2 + 1 && b0 < 6; ++b0) { + sampleIndex = 40 + r0 * 36 + g0 * 6 + b0; + if (sampleIndex == 40) + sampleIndex = 0; + + error = colorMatchError(color, standard256[sampleIndex]); + if (error < minError || minIndex < 0) { + minError = error; + minIndex = sampleIndex; + } + } + } + } + + int shadeBase; + int shadeIndex; + + // Try to match color to a 0x11-multiple pure primary shade. + + if (r > g && r > b) { + shadeBase = 30; + shadeIndex = (r + 8) / 0x11; + } + else if (g > r && g > b) { + shadeBase = 20; + shadeIndex = (g + 8) / 0x11; + } + else { + shadeBase = 10; + shadeIndex = (b + 8) / 0x11; + } + + if (shadeIndex > 0) { + shadeIndex -= (shadeIndex / 3); + sampleIndex = shadeBase + shadeIndex; + error = colorMatchError(color, standard256[sampleIndex]); + if (error < minError || minIndex < 0) { + minError = error; + minIndex = sampleIndex; + } + } + + // Try to match color to a 0x11-multiple gray. + + shadeIndex = (grayscaleValue(color) + 8) / 0x11; + if (shadeIndex > 0) { + shadeIndex -= (shadeIndex / 3); + sampleIndex = shadeIndex; + error = colorMatchError(color, standard256[sampleIndex]); + if (error < minError || minIndex < 0) { + minError = error; + minIndex = sampleIndex; + } + } + + bytePixels[j] = (byte) minIndex; + } + } + + return bytePixels; + } + + protected int grayscaleValue(int color) + { + int r = (color & 0xFF0000) >> 16; + int g = (color & 0x00FF00) >> 8; + int b = color & 0x0000FF; + + return (r * 30 + g * 59 + b * 11) / 100; + } + + protected int colorMatchError(int color1, int color2) + { + int r1 = (color1 & 0xFF0000) >> 16; + int g1 = (color1 & 0x00FF00) >> 8; + int b1 = color1 & 0x0000FF; + int r2 = (color2 & 0xFF0000) >> 16; + int g2 = (color2 & 0x00FF00) >> 8; + int b2 = color2 & 0x0000FF; + int dr = (r2 - r1) * 30; + int dg = (g2 - g1) * 59; + int db = (b2 - b1) * 11; + + return (dr * dr + dg * dg + db * db) / 100; + } + + protected void writeGIFHeader(int width, int height, int bitsPerPixel) throws IOException + { + write((int) 'G'); + write((int) 'I'); + write((int) 'F'); + write((int) '8'); + write((int) '9'); + write((int) 'a'); + + writeGIFWord(width); + writeGIFWord(height); + + int packedBits = 0x80; // Yes, there is a global color table, not ordered. + + packedBits |= ((bitsPerPixel - 1) << 4) | (bitsPerPixel - 1); + + write(packedBits); + + write(0); // Background color index -- not used. + + write(0); // Aspect ratio index -- not specified. + } + + protected void writeColorTable(int[] colorTable, int bitsPerPixel) throws IOException + { + int colorCount = 1 << bitsPerPixel; + + for (int j = 0; j < colorCount; ++j) { + if (j < colorTable.length) + writeGIFColor(colorTable[j]); + else + writeGIFColor(0); + } + } + + protected void writeGraphicControlExtension(Color transparentColor, + int[] colorTable) throws IOException + { + for (int j = 0; j < colorTable.length; ++j) { + if (colorTable[j] == (transparentColor.getRGB() & 0xFFFFFF)) { + write(0x21); // Extension identifier. + write(0xF9); // Graphic Control Extension identifier. + write(0x04); // Block size, always 4. + write(0x01); // Sets transparent color bit. Other bits in this + // packed field should be zero. + write(0x00); // Two bytes of delay time -- not used. + write(0x00); + write(j); // Index of transparent color. + write(0x00); // Block terminator. + } + } + } + + protected void writeImageDescriptor(int width, int height) throws IOException + { + write(0x2C); // Image descriptor identifier; + + writeGIFWord(0); // left postion; + writeGIFWord(0); // top postion; + writeGIFWord(width); + writeGIFWord(height); + + write(0); // No local color table, not interlaced. + } + + protected void writeGIFWord(short word) throws IOException + { + writeGIFWord((int) word); + } + + protected void writeGIFWord(int word) throws IOException + { + write(word & 0xFF); + write((word & 0xFF00) >> 8); + } + + protected void writeGIFColor(Color color) throws IOException + { + writeGIFColor(color.getRGB()); + } + + protected void writeGIFColor(int color) throws IOException + { + write((color & 0xFF0000) >> 16); + write((color & 0xFF00) >> 8); + write(color & 0xFF); + } + + + /********************************************************************\ + | | + | The following code is based on C code for GIF compression | + | obtained from http://www.boutell.com | + | | + | Based on GIFENCOD by David Rowley | + | Modified by Marcel Wijkstra | + | One version, Copyright (C) 1989 by Jef Poskanzer. | + | Heavily modified by Mouse, 1998-02-12. | + | | + | And now, modified and rendered in Java by Kerry Shetline, 2000, | + | kerry@shetline.com | + | | + \********************************************************************/ + + protected int rl_pixel; + protected int rl_basecode; + protected int rl_count; + protected int rl_table_pixel; + protected int rl_table_max; + protected boolean just_cleared; + protected int out_bits; + protected int out_bits_init; + protected int out_count; + protected int out_bump; + protected int out_bump_init; + protected int out_clear; + protected int out_clear_init; + protected int max_ocodes; + protected int code_clear; + protected int code_eof; + protected int obuf; + protected int obits; + protected byte[] oblock = new byte[256]; + protected int oblen; + + protected final static int GIFBITS = 12; + + protected void writeCompressedImageData(byte[] bytePixels, int bitsPerPixel) + throws IOException + { + int init_bits = bitsPerPixel; + + if (init_bits < 2) + init_bits = 2; + + write(init_bits); + + int c; + + obuf = 0; + obits = 0; + oblen = 0; + code_clear = 1 << init_bits; + code_eof = code_clear + 1; + rl_basecode = code_eof + 1; + out_bump_init = (1 << init_bits) - 1; + /* for images with a lot of runs, making out_clear_init larger will + give better compression. */ + out_clear_init = (init_bits <= 2) ? 9 : (out_bump_init - 1); + out_bits_init = init_bits + 1; + max_ocodes = (1 << GIFBITS) - ((1 << (out_bits_init - 1)) + 3); + did_clear(); + output(code_clear); + rl_count = 0; + + for (int j = 0; j < bytePixels.length; ++j) { + c = (int) bytePixels[j]; + if (c < 0) + c += 256; + + if ((rl_count > 0) && (c != rl_pixel)) + rl_flush(); + + if (rl_pixel == c) { + rl_count++; + } + else { + rl_pixel = c; + rl_count = 1; + } + } + + if (rl_count > 0) + rl_flush(); + + output(code_eof); + output_flush(); + } + + + protected void write_block() throws IOException + { + write(oblen); + write(oblock, 0, oblen); + oblen = 0; + } + + protected void block_out(int c) throws IOException + { + oblock[oblen++] = (byte) c; + if (oblen >= 255) + write_block(); + } + + protected void block_flush() throws IOException + { + if (oblen > 0) + write_block(); + } + + protected void output(int val) throws IOException + { + obuf |= val << obits; + obits += out_bits; + while (obits >= 8) { + block_out(obuf & 0xFF); + obuf >>= 8; + obits -= 8; + } + } + + protected void output_flush() throws IOException + { + if (obits > 0) + block_out(obuf); + block_flush(); + } + + protected void did_clear() throws IOException + { + out_bits = out_bits_init; + out_bump = out_bump_init; + out_clear = out_clear_init; + out_count = 0; + rl_table_max = 0; + just_cleared = true; + } + + protected void output_plain(int c) throws IOException + { + just_cleared = false; + output(c); + out_count++; + if (out_count >= out_bump) { + out_bits++; + out_bump += 1 << (out_bits - 1); + } + if (out_count >= out_clear) { + output(code_clear); + did_clear(); + } + } + + protected int isqrt(int x) + { + int r; + int v; + + if (x < 2) + return x; + + for (v = x, r = 1; v != 0; v >>= 2, r <<= 1); + + while (true) { + v = ((x / r) + r) / 2; + if ((v == r) || (v == r + 1)) + return r; + r = v; + } + } + + protected int compute_triangle_count(int count, int nrepcodes) + { + int perrep; + int cost; + + cost = 0; + perrep = (nrepcodes * (nrepcodes +1 )) / 2; + while (count >= perrep) { + cost += nrepcodes; + count -= perrep; + } + if (count > 0) { + int n = isqrt(count); + while ((n * (n + 1)) >= 2 * count) + n--; + while ((n * (n + 1)) < 2 * count) + n++; + cost += n; + } + + return cost; + } + + protected void max_out_clear() + { + out_clear = max_ocodes; + } + + protected void reset_out_clear() throws IOException + { + out_clear = out_clear_init; + if (out_count >= out_clear) { + output(code_clear); + did_clear(); + } + } + + protected void rl_flush_fromclear(int count) throws IOException + { + int n; + + max_out_clear(); + rl_table_pixel = rl_pixel; + n = 1; + while (count > 0) { + if (n == 1) { + rl_table_max = 1; + output_plain(rl_pixel); + count--; + } + else if (count >= n) { + rl_table_max = n; + output_plain(rl_basecode + n - 2); + count -= n; + } + else if (count == 1) { + rl_table_max++; + output_plain(rl_pixel); + count = 0; + } + else { + rl_table_max++; + output_plain(rl_basecode + count - 2); + count = 0; + } + + if (out_count == 0) + n = 1; + else + n++; + } + + reset_out_clear(); + } + + protected void rl_flush_clearorrep(int count) throws IOException + { + int withclr; + + withclr = 1 + compute_triangle_count(count, max_ocodes); + if (withclr < count) { + output(code_clear); + did_clear(); + rl_flush_fromclear(count); + } + else { + for (; count > 0; count--) + output_plain(rl_pixel); + } + } + + protected void rl_flush_withtable(int count) throws IOException + { + int repmax; + int repleft; + int leftover; + + repmax = count / rl_table_max; + leftover = count % rl_table_max; + repleft = (leftover != 0 ? 1 : 0); + if (out_count + repmax + repleft > max_ocodes) { + repmax = max_ocodes - out_count; + leftover = count - (repmax * rl_table_max); + repleft = 1 + compute_triangle_count(leftover, max_ocodes); + } + + if (1 + compute_triangle_count(count,max_ocodes) < repmax + repleft) { + output(code_clear); + did_clear(); + rl_flush_fromclear(count); + return; + } + + max_out_clear(); + for (; repmax > 0; repmax--) + output_plain(rl_basecode + rl_table_max - 2); + if (leftover != 0) { + if (just_cleared) { + rl_flush_fromclear(leftover); + } + else if (leftover == 1) { + output_plain(rl_pixel); + } + else { + output_plain(rl_basecode + leftover - 2); + } + } + reset_out_clear(); + } + + protected void rl_flush() throws IOException + { + int table_reps; + int table_extra; + + if (rl_count == 1) { + output_plain(rl_pixel); + rl_count = 0; + return; + } + if (just_cleared) { + rl_flush_fromclear(rl_count); + } + else if ((rl_table_max < 2) || (rl_table_pixel != rl_pixel)) { + rl_flush_clearorrep(rl_count); + } + else { + rl_flush_withtable(rl_count); + } + + rl_count = 0; + } + + /******** END OF IMPORTED GIF COMPRESSION CODE ********/ +} diff --git a/src/tm/gfxlibs/ImageEncoder.java b/src/tm/gfxlibs/ImageEncoder.java new file mode 100644 index 0000000..6133916 --- /dev/null +++ b/src/tm/gfxlibs/ImageEncoder.java @@ -0,0 +1,271 @@ +// ImageEncoder - abstract class for writing out an image +// +// Copyright (C) 1996 by Jef Poskanzer . All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +// SUCH DAMAGE. +// +// Visit the ACME Labs Java page for up-to-date versions of this and other +// fine Java utilities: http://www.acme.com/java/ + +package tm.gfxlibs; + +import java.util.*; +import java.io.*; +import java.awt.Image; +import java.awt.image.*; + +/// Abstract class for writing out an image. +//

+// A framework for classes that encode and write out an image in +// a particular file format. +//

+// This provides a simplified rendition of the ImageConsumer interface. +// It always delivers the pixels as ints in the RGBdefault color model. +// It always provides them in top-down left-right order. +// If you want more flexibility you can always implement ImageConsumer +// directly. +//

+// Fetch the software.
+// Fetch the entire Acme package. +//

+// @see GifEncoder +// @see PpmEncoder +// @see Acme.JPM.Decoders.ImageDecoder + +public abstract class ImageEncoder implements ImageConsumer + { + + protected OutputStream out; + + private ImageProducer producer; + private int width = -1; + private int height = -1; + private int hintflags = 0; + private boolean started = false; + private boolean encoding; + private IOException iox; + private static final ColorModel rgbModel = ColorModel.getRGBdefault(); + private Hashtable props = null; + + /// Constructor. + // @param img The image to encode. + // @param out The stream to write the bytes to. + public ImageEncoder( Image img, OutputStream out ) throws IOException + { + this( img.getSource(), out ); + } + + /// Constructor. + // @param producer The ImageProducer to encode. + // @param out The stream to write the bytes to. + public ImageEncoder( ImageProducer producer, OutputStream out ) throws IOException + { + this.producer = producer; + this.out = out; + } + + + // Methods that subclasses implement. + + /// Subclasses implement this to initialize an encoding. + abstract void encodeStart( int w, int h ) throws IOException; + + /// Subclasses implement this to actually write out some bits. They + // are guaranteed to be delivered in top-down-left-right order. + // One int per pixel, index is row * scansize + off + col, + // RGBdefault (AARRGGBB) color model. + abstract void encodePixels( + int x, int y, int w, int h, int[] rgbPixels, int off, int scansize ) + throws IOException; + + /// Subclasses implement this to finish an encoding. + abstract void encodeDone() throws IOException; + + + // Our own methods. + + /// Call this after initialization to get things going. + public synchronized void encode() throws IOException + { + encoding = true; + iox = null; + producer.startProduction( this ); + while ( encoding ) + try + { + wait(); + } + catch ( InterruptedException e ) {} + if ( iox != null ) + throw iox; + } + + private boolean accumulate = false; + private int[] accumulator; + + private void encodePixelsWrapper( + int x, int y, int w, int h, int[] rgbPixels, int off, int scansize ) + throws IOException + { + if ( ! started ) + { + started = true; + encodeStart( width, height ); + if ( ( hintflags & TOPDOWNLEFTRIGHT ) == 0 ) + { + accumulate = true; + accumulator = new int[width * height]; + } + } + if ( accumulate ) + for ( int row = 0; row < h; ++row ) + System.arraycopy( + rgbPixels, row * scansize + off, + accumulator, ( y + row ) * width + x, + w ); + else + encodePixels( x, y, w, h, rgbPixels, off, scansize ); + } + + private void encodeFinish() throws IOException + { + if ( accumulate ) + { + encodePixels( 0, 0, width, height, accumulator, 0, width ); + accumulator = null; + accumulate = false; + } + } + + private synchronized void stop() + { + encoding = false; + notifyAll(); + } + + + // Methods from ImageConsumer. + + public void setDimensions( int width, int height ) + { + this.width = width; + this.height = height; + } + + public void setProperties( Hashtable props ) + { + this.props = props; + } + + public void setColorModel( ColorModel model ) + { + // Ignore. + } + + public void setHints( int hintflags ) + { + this.hintflags = hintflags; + } + + public void setPixels( + int x, int y, int w, int h, ColorModel model, byte[] pixels, + int off, int scansize ) + { + int[] rgbPixels = new int[w]; + for ( int row = 0; row < h; ++row ) + { + int rowOff = off + row * scansize; + for ( int col = 0; col < w; ++col ) + rgbPixels[col] = model.getRGB( pixels[rowOff + col] & 0xff ); + try + { + encodePixelsWrapper( x, y + row, w, 1, rgbPixels, 0, w ); + } + catch ( IOException e ) + { + iox = e; + stop(); + return; + } + } + } + + public void setPixels( + int x, int y, int w, int h, ColorModel model, int[] pixels, + int off, int scansize ) + { + if ( model == rgbModel ) + { + try + { + encodePixelsWrapper( x, y, w, h, pixels, off, scansize ); + } + catch ( IOException e ) + { + iox = e; + stop(); + return; + } + } + else + { + int[] rgbPixels = new int[w]; + for ( int row = 0; row < h; ++row ) + { + int rowOff = off + row * scansize; + for ( int col = 0; col < w; ++col ) + rgbPixels[col] = model.getRGB( pixels[rowOff + col] ); + try + { + encodePixelsWrapper( x, y + row, w, 1, rgbPixels, 0, w ); + } + catch ( IOException e ) + { + iox = e; + stop(); + return; + } + } + } + } + + public void imageComplete( int status ) + { + producer.removeConsumer( this ); + if ( status == ImageConsumer.IMAGEABORTED ) + iox = new IOException( "image aborted" ); + else + { + try + { + encodeFinish(); + encodeDone(); + } + catch ( IOException e ) + { + iox = e; + } + } + stop(); + } + + } diff --git a/src/tm/gfxlibs/PCXEncoder.java b/src/tm/gfxlibs/PCXEncoder.java new file mode 100644 index 0000000..183c1ce --- /dev/null +++ b/src/tm/gfxlibs/PCXEncoder.java @@ -0,0 +1,147 @@ +/** +* +* @author Kent Hansen +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +**/ + +package tm.gfxlibs; + +import java.awt.Image; +import java.awt.image.PixelGrabber; +import java.awt.image.ImageObserver; +import java.io.ByteArrayOutputStream; + +public class PCXEncoder { + + private static ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + public static byte[] encode(Image image) { + // get width and height of image + int w = image.getWidth(null); + int h = image.getHeight(null); + + // grab the pixels + int[] pixels = new int[w * h]; + PixelGrabber pg = new PixelGrabber(image, 0, 0, w, h, pixels, 0, w); + try { + pg.grabPixels(); + } catch (InterruptedException e) { + System.err.println("interrupted waiting for pixels!"); + return null; + } + if ((pg.getStatus() & ImageObserver.ABORT) != 0) { + System.err.println("image fetch aborted or errored"); + return null; + } + + // prepare the byte stream + baos.reset(); + + // write the header + emitByte(10); // Manufacturer = ZSoft + emitByte(5); // Version = 3.0+ (supports 24-bit PCX) + emitByte(1); // Encoding = RLE + emitByte(8); // BitsPerPixel (per plane) + emitInt(0); // Xmin + emitInt(0); // Ymin + emitInt(w-1); // Xmax + emitInt(h-1); // Ymax + emitInt(0); // HDpi (not used) + emitInt(0); // VDpi (not used) + emitZeroes(48); // Colormap (not used) + emitZeroes(1); // Reserved + emitByte(3); // NPlanes + emitInt(w); // BytesPerLine + emitInt(0); // PaletteInfo (not used) + emitInt(w); // HScreenSize (unsure what this is for) + emitInt(h); // VScreenSize (unsure what this is for) + emitZeroes(54); // Filler + + // encode the pixels + int ofs=0; + int[] plane = new int[w]; + for (int i=0; i> 8) & 0xFF); + } + + private static void emitZeroes(int c) { + for (int i=0; i> 16) & 0xFF; + } + + private static int getGreen(int rgb) { + return (rgb >> 8) & 0xFF; + } + + private static int getBlue(int rgb) { + return rgb & 0xFF; + } + + private static void encodePlane(int[] plane) { + int i=0; + while (i < plane.length) { + int v = plane[i]; + if ((i != plane.length-1) && (v == plane[i+1])) { + // run-length encode + int c = 1; + while ((c < 0x40) && (i+c < plane.length) && (v == plane[i+c])) { + c++; + } + i += c; + emitByte(c | 0xC0); + emitByte(v); + } + else { + // regular encode + if ((v & 0xC0) == 0xC0) { + emitByte(0xC1); + } + emitByte(v); + i++; + } + } + } + +} \ No newline at end of file diff --git a/src/tm/gfxlibs/PCXReader.java b/src/tm/gfxlibs/PCXReader.java new file mode 100644 index 0000000..bdb47be --- /dev/null +++ b/src/tm/gfxlibs/PCXReader.java @@ -0,0 +1,236 @@ +/* PcxReader: This is a class which provides a method for reading + * PCX-Files. + * The PCX-Format is a Image-File-Format which was developed by ZSoft. + * + * PcxReader, Version 1.00 [06/05/2000] + * Copyright (c) 2000 by Matthias Burg + * All rights reserved + * eMail: Matthias@burgsoft.de + * Internet: www.burgsoft.de + * + * The PcxReader is Freeware. You can use and copy it without any fee. + * The author is not responsible for any damages which are caused by + * this software. + * You find further information about the Java-Technology on the Sun- + * Website (Internet: www.sun.com). + * + * At the moment PcxReader supports the following File-Formats: + * - PCX Version 3.0 with 8 Bit (=256) Colors + * - PCX Version 3.0 with 24 Bit (=16.7 Mio) Colors + * + * The PcxReader needs an opened InputStream with the PCX-Data as + * Argument. The return-value is the loaded Image. + * You can use the PcxReader in a Java-Application as well as in a + * Java-Applet + * + * If you have questions or tips for the PcxReader, please write an + * eMail. + */ + +package tm.gfxlibs; + +import java.awt.*; +import java.awt.image.*; +import java.io.*; +import java.util.*; + + +public class PCXReader +{ + /* This is the main-class of the PcxReader. It reads the PCX-Data + * from a stream and converts it into an Image-Class. + */ + + public static final int NORMAL = 1; + public static final int RLE = 2; + + public static Image loadImage(InputStream in) + { + int pcxheight, pcxwidth; + Image picture = null; + + //Header-Data + int manufacturer; + int version; + int encoding; + int bits_per_pixel; + int xmin,ymin; + int xmax,ymax; + int hres; + int vres; + byte[] palette16 = new byte[48]; + int reserved; + int color_planes; + int bytes_per_line; + int palette_type; + byte[] filler = new byte[58]; + + int imagebytes; + try + { + /* In the beginning the Image-Data is read as in the PCX- + * specification. + */ + manufacturer = in.read(); + version = in.read(); + encoding = in.read(); + bits_per_pixel = in.read(); + + xmin = in.read()+in.read()*256; + ymin = in.read()+in.read()*256; + xmax = in.read()+in.read()*256; + ymax = in.read()+in.read()*256; + hres = in.read()+in.read()*256; + vres = in.read()+in.read()*256; + in.read(palette16); + reserved = in.read(); + color_planes = in.read(); + bytes_per_line = in.read()+in.read()*256; + palette_type = (short)(in.read()+in.read()*256); + in.read(filler); + + + pcxwidth = 1+xmax-xmin; + pcxheight = 1+ymax-ymin; + if(pcxwidth % 2 == 1) + { + /* The width of an PCX-Image must be even. That is why the + * width is increased when it was odd before. + */ + pcxwidth++; + } + + + if(bits_per_pixel == 8 && color_planes == 1) + { + /* If the PCX-file has 256 colors there is a color-palete + * at the end of the file. This is 768b bytes long and + * contains the red- green- and blue-values of the colors. + */ + byte[] pal = new byte[768]; + int[] intPal = new int[768]; + + imagebytes = (pcxwidth*pcxheight); + int[] imageData = new int[imagebytes]; + readRLECompressedData(imagebytes, imageData, in); + + if(in.available() > 769) + { + while(in.available() > 769) + { + in.read(); + } + } + + if(in.available() != 769) + { + System.out.println("Error in the palette!"); + } + if(in.read()!=12) + { + System.out.println("Error in the palette!"); + } + + in.read(pal); + in.close(); + for(int y = 0; y <767;y++) + { + intPal[y] = (int)(pal[y]); + if(intPal[y] < 0) + { + intPal[y] += 256; + } + } + + /* Now the PcxReader converts the imagedata into the format + * of a MemoryImageSource. + */ + + int RGBImageData[] = new int[imagebytes]; + for(int i = 0; i < imagebytes; i++) + { + int paletteEntry = imageData[i]; + if(paletteEntry < 0) paletteEntry += 256; + RGBImageData[i] = new Color(intPal[paletteEntry*3], + intPal[paletteEntry*3+1], + intPal[paletteEntry*3+2]).getRGB(); + } + + ImageProducer prod = new MemoryImageSource(pcxwidth, pcxheight, RGBImageData, 0, pcxwidth); + picture = Toolkit.getDefaultToolkit().createImage(prod); + + } + else if(bits_per_pixel == 8 && color_planes == 3) + { + /* If the picture has 24 bit colors, there are 3 times many + * bytes as many pixels. + */ + + imagebytes = (pcxwidth*pcxheight*3); + int[] imageData = new int[imagebytes]; + readRLECompressedData(imagebytes, imageData, in); + + + int RGBImageData[] = new int[imagebytes]; + for(int i = 0; i < pcxheight; i++) + { + for(int j = 0; j < pcxwidth; j++) + { + int red = imageData[i*3*pcxwidth+j]; + int green = imageData[((i*3)+1)*pcxwidth+j]; + int blue = imageData[((i*3)+2)*pcxwidth+j]; + RGBImageData[i*pcxwidth+j] = new Color(red,green,blue).getRGB(); + } + } + + ImageProducer prod = new MemoryImageSource(pcxwidth, pcxheight, RGBImageData, 0, pcxwidth); + picture = Toolkit.getDefaultToolkit().createImage(prod); + + } + } + catch (IOException e) + { + System.out.println("Error reading PCX-File!"); + } + + return picture; + } + + private static void readRLECompressedData(int imagebytes, int[] imageData, InputStream in) + throws IOException + { + /* This method reads the compressed data-stream and decompresses + * it in the memory. + */ + + int i; + int mode=NORMAL,nbytes=0; + int abyte = 0; + + for(i = 0; i 191) + { + nbytes=abyte-192; + abyte =(byte)(in.read()); + if (--nbytes > 0) + { + mode = RLE; + } + } + } + else if(--nbytes == 0) + { + mode = NORMAL; + } + + imageData[i] = abyte; + if(imageData[i] < 0) imageData[i] += 256; + } + } +} + + diff --git a/src/tm/gfxlibs/PngEncoder.java b/src/tm/gfxlibs/PngEncoder.java new file mode 100644 index 0000000..e8b7ea1 --- /dev/null +++ b/src/tm/gfxlibs/PngEncoder.java @@ -0,0 +1,621 @@ +/** + * PngEncoder takes a Java Image object and creates a byte string which can be saved as a PNG file. + * The Image is presumed to use the DirectColorModel. + * + * Thanks to Jay Denny at KeyPoint Software + * http://www.keypoint.com/ + * who let me develop this code on company time. + * + * You may contact me with (probably very-much-needed) improvements, + * comments, and bug fixes at: + * + * david@catcode.com + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * A copy of the GNU LGPL may be found at + * http://www.gnu.org/copyleft/lesser.html, + * + * @author J. David Eisenberg + * @version 1.4, 31 March 2000 + */ + +package tm.gfxlibs; + +import java.awt.*; +import java.awt.image.*; +import java.util.*; +import java.util.zip.*; +import java.io.*; + +public class PngEncoder extends Object +{ + /** Constant specifying that alpha channel should be encoded. */ + public static final boolean ENCODE_ALPHA=true; + /** Constant specifying that alpha channel should not be encoded. */ + public static final boolean NO_ALPHA=false; + /** Constants for filters */ + public static final int FILTER_NONE = 0; + public static final int FILTER_SUB = 1; + public static final int FILTER_UP = 2; + public static final int FILTER_LAST = 2; + + protected byte[] pngBytes; + protected byte[] priorRow; + protected byte[] leftBytes; + protected Image image; + protected int width, height; + protected int bytePos, maxPos; + protected int hdrPos, dataPos, endPos; + protected CRC32 crc = new CRC32(); + protected long crcValue; + protected boolean encodeAlpha; + protected int filter; + protected int bytesPerPixel; + protected int compressionLevel; + + /** + * Class constructor + * + */ + public PngEncoder() + { + this( null, false, FILTER_NONE, 0 ); + } + + /** + * Class constructor specifying Image to encode, with no alpha channel encoding. + * + * @param image A Java Image object which uses the DirectColorModel + * @see java.awt.Image + */ + public PngEncoder( Image image ) + { + this(image, false, FILTER_NONE, 0); + } + + /** + * Class constructor specifying Image to encode, and whether to encode alpha. + * + * @param image A Java Image object which uses the DirectColorModel + * @param encodeAlpha Encode the alpha channel? false=no; true=yes + * @see java.awt.Image + */ + public PngEncoder( Image image, boolean encodeAlpha ) + { + this(image, encodeAlpha, FILTER_NONE, 0); + } + + /** + * Class constructor specifying Image to encode, whether to encode alpha, and filter to use. + * + * @param image A Java Image object which uses the DirectColorModel + * @param encodeAlpha Encode the alpha channel? false=no; true=yes + * @param whichFilter 0=none, 1=sub, 2=up + * @see java.awt.Image + */ + public PngEncoder( Image image, boolean encodeAlpha, int whichFilter ) + { + this( image, encodeAlpha, whichFilter, 0 ); + } + + + /** + * Class constructor specifying Image source to encode, whether to encode alpha, filter to use, and compression level. + * + * @param image A Java Image object + * @param encodeAlpha Encode the alpha channel? false=no; true=yes + * @param whichFilter 0=none, 1=sub, 2=up + * @param compLevel 0..9 + * @see java.awt.Image + */ + public PngEncoder( Image image, boolean encodeAlpha, int whichFilter, + int compLevel) + { + this.image = image; + this.encodeAlpha = encodeAlpha; + setFilter( whichFilter ); + if (compLevel >=0 && compLevel <=9) + { + this.compressionLevel = compLevel; + } + } + + /** + * Set the image to be encoded + * + * @param image A Java Image object which uses the DirectColorModel + * @see java.awt.Image + * @see java.awt.image.DirectColorModel + */ + public void setImage( Image image ) + { + this.image = image; + pngBytes = null; + } + + /** + * Creates an array of bytes that is the PNG equivalent of the current image, specifying whether to encode alpha or not. + * + * @param encodeAlpha boolean false=no alpha, true=encode alpha + * @return an array of bytes, or null if there was a problem + */ + public byte[] pngEncode( boolean encodeAlpha ) + { + byte[] pngIdBytes = { -119, 80, 78, 71, 13, 10, 26, 10 }; + int i; + + if (image == null) + { + return null; + } + width = image.getWidth( null ); + height = image.getHeight( null ); + this.image = image; + + /* + * start with an array that is big enough to hold all the pixels + * (plus filter bytes), and an extra 200 bytes for header info + */ + pngBytes = new byte[((width+1) * height * 3) + 200]; + + /* + * keep track of largest byte written to the array + */ + maxPos = 0; + + bytePos = writeBytes( pngIdBytes, 0 ); + hdrPos = bytePos; + writeHeader(); + dataPos = bytePos; + if (writeImageData()) + { + writeEnd(); + pngBytes = resizeByteArray( pngBytes, maxPos ); + } + else + { + pngBytes = null; + } + return pngBytes; + } + + /** + * Creates an array of bytes that is the PNG equivalent of the current image. + * Alpha encoding is determined by its setting in the constructor. + * + * @return an array of bytes, or null if there was a problem + */ + public byte[] pngEncode() + { + return pngEncode( encodeAlpha ); + } + + /** + * Set the alpha encoding on or off. + * + * @param encodeAlpha false=no, true=yes + */ + public void setEncodeAlpha( boolean encodeAlpha ) + { + this.encodeAlpha = encodeAlpha; + } + + /** + * Retrieve alpha encoding status. + * + * @return boolean false=no, true=yes + */ + public boolean getEncodeAlpha() + { + return encodeAlpha; + } + + /** + * Set the filter to use + * + * @param whichFilter from constant list + */ + public void setFilter( int whichFilter ) + { + this.filter = FILTER_NONE; + if ( whichFilter <= FILTER_LAST ) + { + this.filter = whichFilter; + } + } + + /** + * Retrieve filtering scheme + * + * @return int (see constant list) + */ + public int getFilter() + { + return filter; + } + + /** + * Set the compression level to use + * + * @param level 0 through 9 + */ + public void setCompressionLevel( int level ) + { + if ( level >= 0 && level <= 9) + { + this.compressionLevel = level; + } + } + + /** + * Retrieve compression level + * + * @return int in range 0-9 + */ + public int getCompressionLevel() + { + return compressionLevel; + } + + /** + * Increase or decrease the length of a byte array. + * + * @param array The original array. + * @param newLength The length you wish the new array to have. + * @return Array of newly desired length. If shorter than the + * original, the trailing elements are truncated. + */ + protected byte[] resizeByteArray( byte[] array, int newLength ) + { + byte[] newArray = new byte[newLength]; + int oldLength = array.length; + + System.arraycopy( array, 0, newArray, 0, + Math.min( oldLength, newLength ) ); + return newArray; + } + + /** + * Write an array of bytes into the pngBytes array. + * Note: This routine has the side effect of updating + * maxPos, the largest element written in the array. + * The array is resized by 1000 bytes or the length + * of the data to be written, whichever is larger. + * + * @param data The data to be written into pngBytes. + * @param offset The starting point to write to. + * @return The next place to be written to in the pngBytes array. + */ + protected int writeBytes( byte[] data, int offset ) + { + maxPos = Math.max( maxPos, offset + data.length ); + if (data.length + offset > pngBytes.length) + { + pngBytes = resizeByteArray( pngBytes, pngBytes.length + + Math.max( 1000, data.length ) ); + } + System.arraycopy( data, 0, pngBytes, offset, data.length ); + return offset + data.length; + } + + /** + * Write an array of bytes into the pngBytes array, specifying number of bytes to write. + * Note: This routine has the side effect of updating + * maxPos, the largest element written in the array. + * The array is resized by 1000 bytes or the length + * of the data to be written, whichever is larger. + * + * @param data The data to be written into pngBytes. + * @param nBytes The number of bytes to be written. + * @param offset The starting point to write to. + * @return The next place to be written to in the pngBytes array. + */ + protected int writeBytes( byte[] data, int nBytes, int offset ) + { + maxPos = Math.max( maxPos, offset + nBytes ); + if (nBytes + offset > pngBytes.length) + { + pngBytes = resizeByteArray( pngBytes, pngBytes.length + + Math.max( 1000, nBytes ) ); + } + System.arraycopy( data, 0, pngBytes, offset, nBytes ); + return offset + nBytes; + } + + /** + * Write a two-byte integer into the pngBytes array at a given position. + * + * @param n The integer to be written into pngBytes. + * @param offset The starting point to write to. + * @return The next place to be written to in the pngBytes array. + */ + protected int writeInt2( int n, int offset ) + { + byte[] temp = { (byte)((n >> 8) & 0xff), + (byte) (n & 0xff) }; + return writeBytes( temp, offset ); + } + + /** + * Write a four-byte integer into the pngBytes array at a given position. + * + * @param n The integer to be written into pngBytes. + * @param offset The starting point to write to. + * @return The next place to be written to in the pngBytes array. + */ + protected int writeInt4( int n, int offset ) + { + byte[] temp = { (byte)((n >> 24) & 0xff), + (byte) ((n >> 16) & 0xff ), + (byte) ((n >> 8) & 0xff ), + (byte) ( n & 0xff ) }; + return writeBytes( temp, offset ); + } + + /** + * Write a single byte into the pngBytes array at a given position. + * + * @param n The integer to be written into pngBytes. + * @param offset The starting point to write to. + * @return The next place to be written to in the pngBytes array. + */ + protected int writeByte( int b, int offset ) + { + byte[] temp = { (byte) b }; + return writeBytes( temp, offset ); + } + + /** + * Write a string into the pngBytes array at a given position. + * This uses the getBytes method, so the encoding used will + * be its default. + * + * @param n The integer to be written into pngBytes. + * @param offset The starting point to write to. + * @return The next place to be written to in the pngBytes array. + * @see java.lang.String#getBytes() + */ + protected int writeString( String s, int offset ) + { + return writeBytes( s.getBytes(), offset ); + } + + /** + * Write a PNG "IHDR" chunk into the pngBytes array. + */ + protected void writeHeader() + { + int startPos; + + startPos = bytePos = writeInt4( 13, bytePos ); + bytePos = writeString( "IHDR", bytePos ); + width = image.getWidth( null ); + height = image.getHeight( null ); + bytePos = writeInt4( width, bytePos ); + bytePos = writeInt4( height, bytePos ); + bytePos = writeByte( 8, bytePos ); // bit depth + bytePos = writeByte( (encodeAlpha) ? 6 : 2, bytePos ); // direct model + bytePos = writeByte( 0, bytePos ); // compression method + bytePos = writeByte( 0, bytePos ); // filter method + bytePos = writeByte( 0, bytePos ); // no interlace + crc.reset(); + crc.update( pngBytes, startPos, bytePos-startPos ); + crcValue = crc.getValue(); + bytePos = writeInt4( (int) crcValue, bytePos ); + } + + /** + * Perform "sub" filtering on the given row. + * Uses temporary array leftBytes to store the original values + * of the previous pixels. The array is 16 bytes long, which + * will easily hold two-byte samples plus two-byte alpha. + * + * @param pixels The array holding the scan lines being built + * @param startPos Starting position within pixels of bytes to be filtered. + * @param width Width of a scanline in pixels. + */ + protected void filterSub( byte[] pixels, int startPos, int width ) + { + int i; + int offset = bytesPerPixel; + int actualStart = startPos + offset; + int nBytes = width * bytesPerPixel; + int leftInsert = offset; + int leftExtract = 0; + byte current_byte; + + for (i=actualStart; i < startPos + nBytes; i++) + { + leftBytes[leftInsert] = pixels[i]; + pixels[i] = (byte) ((pixels[i] - leftBytes[leftExtract]) % 256); + leftInsert = (leftInsert+1) % 0x0f; + leftExtract = (leftExtract + 1) % 0x0f; + } + } + + /** + * Perform "up" filtering on the given row. + * Side effect: refills the prior row with current row + * + * @param pixels The array holding the scan lines being built + * @param startPos Starting position within pixels of bytes to be filtered. + * @param width Width of a scanline in pixels. + */ + protected void filterUp( byte[] pixels, int startPos, int width ) + { + int i, nBytes; + byte current_byte; + + nBytes = width * bytesPerPixel; + + for (i=0; i < nBytes; i++) + { + current_byte = pixels[startPos + i]; + pixels[startPos + i] = (byte) ((pixels[startPos + i] - priorRow[i]) % 256); + priorRow[i] = current_byte; + } + } + + /** + * Write the image data into the pngBytes array. + * This will write one or more PNG "IDAT" chunks. In order + * to conserve memory, this method grabs as many rows as will + * fit into 32K bytes, or the whole image; whichever is less. + * + * + * @return true if no errors; false if error grabbing pixels + */ + protected boolean writeImageData() + { + int rowsLeft = height; // number of rows remaining to write + int startRow = 0; // starting row to process this time through + int nRows; // how many rows to grab at a time + + byte[] scanLines; // the scan lines to be compressed + int scanPos; // where we are in the scan lines + int startPos; // where this line's actual pixels start (used for filtering) + + byte[] compressedLines; // the resultant compressed lines + int nCompressed; // how big is the compressed area? + + int depth; // color depth ( handle only 8 or 32 ) + + PixelGrabber pg; + + bytesPerPixel = (encodeAlpha) ? 4 : 3; + + Deflater scrunch = new Deflater( compressionLevel ); + ByteArrayOutputStream outBytes = + new ByteArrayOutputStream(1024); + + DeflaterOutputStream compBytes = + new DeflaterOutputStream( outBytes, scrunch ); + try + { + while (rowsLeft > 0) + { + nRows = Math.min( 32767 / (width*(bytesPerPixel+1)), rowsLeft ); + // nRows = rowsLeft; + + int[] pixels = new int[width * nRows]; + + pg = new PixelGrabber(image, 0, startRow, + width, nRows, pixels, 0, width); + try { + pg.grabPixels(); + } + catch (Exception e) { + System.err.println("interrupted waiting for pixels!"); + return false; + } + if ((pg.getStatus() & ImageObserver.ABORT) != 0) { + System.err.println("image fetch aborted or errored"); + return false; + } + + /* + * Create a data chunk. scanLines adds "nRows" for + * the filter bytes. + */ + scanLines = new byte[width * nRows * bytesPerPixel + nRows]; + + if (filter == FILTER_SUB) + { + leftBytes = new byte[16]; + } + if (filter == FILTER_UP) + { + priorRow = new byte[width*bytesPerPixel]; + } + + scanPos = 0; + startPos = 1; + for (int i=0; i> 16) & 0xff); + scanLines[scanPos++] = (byte) ((pixels[i] >> 8) & 0xff); + scanLines[scanPos++] = (byte) ((pixels[i] ) & 0xff); + if (encodeAlpha) + { + scanLines[scanPos++] = (byte) ((pixels[i] >> 24) & 0xff ); + } + if ((i % width == width-1) && (filter != FILTER_NONE)) + { + if (filter == FILTER_SUB) + { + filterSub( scanLines, startPos, width ); + } + if (filter == FILTER_UP) + { + filterUp( scanLines, startPos, width ); + } + } + } + + /* + * Write these lines to the output area + */ + compBytes.write( scanLines, 0, scanPos ); + + + startRow += nRows; + rowsLeft -= nRows; + } + compBytes.close(); + + /* + * Write the compressed bytes + */ + compressedLines = outBytes.toByteArray(); + nCompressed = compressedLines.length; + + crc.reset(); + bytePos = writeInt4( nCompressed, bytePos ); + bytePos = writeString("IDAT", bytePos ); + crc.update("IDAT".getBytes()); + bytePos = writeBytes( compressedLines, nCompressed, bytePos ); + crc.update( compressedLines, 0, nCompressed ); + + crcValue = crc.getValue(); + bytePos = writeInt4( (int) crcValue, bytePos ); + scrunch.finish(); + return true; + } + catch (IOException e) + { + System.err.println( e.toString()); + return false; + } + } + + /** + * Write a PNG "IEND" chunk into the pngBytes array. + */ + protected void writeEnd() + { + bytePos = writeInt4( 0, bytePos ); + bytePos = writeString( "IEND", bytePos ); + crc.reset(); + crc.update("IEND".getBytes()); + crcValue = crc.getValue(); + bytePos = writeInt4( (int) crcValue, bytePos ); + } +} + diff --git a/src/tm/gfxlibs/Quantize.java b/src/tm/gfxlibs/Quantize.java new file mode 100644 index 0000000..aab2fa1 --- /dev/null +++ b/src/tm/gfxlibs/Quantize.java @@ -0,0 +1,703 @@ +/* + * @(#)Quantize.java 0.90 9/19/00 Adam Doppelt + */ + +/** + * An efficient color quantization algorithm, adapted from the C++ + * implementation quantize.c in ImageMagick. The pixels for + * an image are placed into an oct tree. The oct tree is reduced in + * size, and the pixels from the original image are reassigned to the + * nodes in the reduced tree.

+ * + * Here is the copyright notice from ImageMagick: + * + *

+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%  Permission is hereby granted, free of charge, to any person obtaining a    %
+%  copy of this software and associated documentation files ("ImageMagick"),  %
+%  to deal in ImageMagick without restriction, including without limitation   %
+%  the rights to use, copy, modify, merge, publish, distribute, sublicense,   %
+%  and/or sell copies of ImageMagick, and to permit persons to whom the       %
+%  ImageMagick is furnished to do so, subject to the following conditions:    %
+%                                                                             %
+%  The above copyright notice and this permission notice shall be included in %
+%  all copies or substantial portions of ImageMagick.                         %
+%                                                                             %
+%  The software is provided "as is", without warranty of any kind, express or %
+%  implied, including but not limited to the warranties of merchantability,   %
+%  fitness for a particular purpose and noninfringement.  In no event shall   %
+%  E. I. du Pont de Nemours and Company be liable for any claim, damages or   %
+%  other liability, whether in an action of contract, tort or otherwise,      %
+%  arising from, out of or in connection with ImageMagick or the use or other %
+%  dealings in ImageMagick.                                                   %
+%                                                                             %
+%  Except as contained in this notice, the name of the E. I. du Pont de       %
+%  Nemours and Company shall not be used in advertising or otherwise to       %
+%  promote the sale, use or other dealings in ImageMagick without prior       %
+%  written authorization from the E. I. du Pont de Nemours and Company.       %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ * + * + * @version 0.90 19 Sep 2000 + * @author Adam Doppelt + */ + +package tm.gfxlibs; + +public class Quantize { + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % +% QQQ U U AAA N N TTTTT IIIII ZZZZZ EEEEE % +% Q Q U U A A NN N T I ZZ E % +% Q Q U U AAAAA N N N T I ZZZ EEEEE % +% Q QQ U U A A N NN T I ZZ E % +% QQQQ UUU A A N N T IIIII ZZZZZ EEEEE % +% % +% % +% Reduce the Number of Unique Colors in an Image % +% % +% % +% Software Design % +% John Cristy % +% July 1992 % +% % +% % +% Copyright 1998 E. I. du Pont de Nemours and Company % +% % +% Permission is hereby granted, free of charge, to any person obtaining a % +% copy of this software and associated documentation files ("ImageMagick"), % +% to deal in ImageMagick without restriction, including without limitation % +% the rights to use, copy, modify, merge, publish, distribute, sublicense, % +% and/or sell copies of ImageMagick, and to permit persons to whom the % +% ImageMagick is furnished to do so, subject to the following conditions: % +% % +% The above copyright notice and this permission notice shall be included in % +% all copies or substantial portions of ImageMagick. % +% % +% The software is provided "as is", without warranty of any kind, express or % +% implied, including but not limited to the warranties of merchantability, % +% fitness for a particular purpose and noninfringement. In no event shall % +% E. I. du Pont de Nemours and Company be liable for any claim, damages or % +% other liability, whether in an action of contract, tort or otherwise, % +% arising from, out of or in connection with ImageMagick or the use or other % +% dealings in ImageMagick. % +% % +% Except as contained in this notice, the name of the E. I. du Pont de % +% Nemours and Company shall not be used in advertising or otherwise to % +% promote the sale, use or other dealings in ImageMagick without prior % +% written authorization from the E. I. du Pont de Nemours and Company. % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Realism in computer graphics typically requires using 24 bits/pixel to +% generate an image. Yet many graphic display devices do not contain +% the amount of memory necessary to match the spatial and color +% resolution of the human eye. The QUANTIZE program takes a 24 bit +% image and reduces the number of colors so it can be displayed on +% raster device with less bits per pixel. In most instances, the +% quantized image closely resembles the original reference image. +% +% A reduction of colors in an image is also desirable for image +% transmission and real-time animation. +% +% Function Quantize takes a standard RGB or monochrome images and quantizes +% them down to some fixed number of colors. +% +% For purposes of color allocation, an image is a set of n pixels, where +% each pixel is a point in RGB space. RGB space is a 3-dimensional +% vector space, and each pixel, pi, is defined by an ordered triple of +% red, green, and blue coordinates, (ri, gi, bi). +% +% Each primary color component (red, green, or blue) represents an +% intensity which varies linearly from 0 to a maximum value, cmax, which +% corresponds to full saturation of that color. Color allocation is +% defined over a domain consisting of the cube in RGB space with +% opposite vertices at (0,0,0) and (cmax,cmax,cmax). QUANTIZE requires +% cmax = 255. +% +% The algorithm maps this domain onto a tree in which each node +% represents a cube within that domain. In the following discussion +% these cubes are defined by the coordinate of two opposite vertices: +% The vertex nearest the origin in RGB space and the vertex farthest +% from the origin. +% +% The tree's root node represents the the entire domain, (0,0,0) through +% (cmax,cmax,cmax). Each lower level in the tree is generated by +% subdividing one node's cube into eight smaller cubes of equal size. +% This corresponds to bisecting the parent cube with planes passing +% through the midpoints of each edge. +% +% The basic algorithm operates in three phases: Classification, +% Reduction, and Assignment. Classification builds a color +% description tree for the image. Reduction collapses the tree until +% the number it represents, at most, the number of colors desired in the +% output image. Assignment defines the output image's color map and +% sets each pixel's color by reclassification in the reduced tree. +% Our goal is to minimize the numerical discrepancies between the original +% colors and quantized colors (quantization error). +% +% Classification begins by initializing a color description tree of +% sufficient depth to represent each possible input color in a leaf. +% However, it is impractical to generate a fully-formed color +% description tree in the classification phase for realistic values of +% cmax. If colors components in the input image are quantized to k-bit +% precision, so that cmax= 2k-1, the tree would need k levels below the +% root node to allow representing each possible input color in a leaf. +% This becomes prohibitive because the tree's total number of nodes is +% 1 + sum(i=1,k,8k). +% +% A complete tree would require 19,173,961 nodes for k = 8, cmax = 255. +% Therefore, to avoid building a fully populated tree, QUANTIZE: (1) +% Initializes data structures for nodes only as they are needed; (2) +% Chooses a maximum depth for the tree as a function of the desired +% number of colors in the output image (currently log2(colormap size)). +% +% For each pixel in the input image, classification scans downward from +% the root of the color description tree. At each level of the tree it +% identifies the single node which represents a cube in RGB space +% containing the pixel's color. It updates the following data for each +% such node: +% +% n1: Number of pixels whose color is contained in the RGB cube +% which this node represents; +% +% n2: Number of pixels whose color is not represented in a node at +% lower depth in the tree; initially, n2 = 0 for all nodes except +% leaves of the tree. +% +% Sr, Sg, Sb: Sums of the red, green, and blue component values for +% all pixels not classified at a lower depth. The combination of +% these sums and n2 will ultimately characterize the mean color of a +% set of pixels represented by this node. +% +% E: The distance squared in RGB space between each pixel contained +% within a node and the nodes' center. This represents the quantization +% error for a node. +% +% Reduction repeatedly prunes the tree until the number of nodes with +% n2 > 0 is less than or equal to the maximum number of colors allowed +% in the output image. On any given iteration over the tree, it selects +% those nodes whose E count is minimal for pruning and merges their +% color statistics upward. It uses a pruning threshold, Ep, to govern +% node selection as follows: +% +% Ep = 0 +% while number of nodes with (n2 > 0) > required maximum number of colors +% prune all nodes such that E <= Ep +% Set Ep to minimum E in remaining nodes +% +% This has the effect of minimizing any quantization error when merging +% two nodes together. +% +% When a node to be pruned has offspring, the pruning procedure invokes +% itself recursively in order to prune the tree from the leaves upward. +% n2, Sr, Sg, and Sb in a node being pruned are always added to the +% corresponding data in that node's parent. This retains the pruned +% node's color characteristics for later averaging. +% +% For each node, n2 pixels exist for which that node represents the +% smallest volume in RGB space containing those pixel's colors. When n2 +% > 0 the node will uniquely define a color in the output image. At the +% beginning of reduction, n2 = 0 for all nodes except a the leaves of +% the tree which represent colors present in the input image. +% +% The other pixel count, n1, indicates the total number of colors +% within the cubic volume which the node represents. This includes n1 - +% n2 pixels whose colors should be defined by nodes at a lower level in +% the tree. +% +% Assignment generates the output image from the pruned tree. The +% output image consists of two parts: (1) A color map, which is an +% array of color descriptions (RGB triples) for each color present in +% the output image; (2) A pixel array, which represents each pixel as +% an index into the color map array. +% +% First, the assignment phase makes one pass over the pruned color +% description tree to establish the image's color map. For each node +% with n2 > 0, it divides Sr, Sg, and Sb by n2 . This produces the +% mean color of all pixels that classify no lower than this node. Each +% of these colors becomes an entry in the color map. +% +% Finally, the assignment phase reclassifies each pixel in the pruned +% tree to identify the deepest node containing the pixel's color. The +% pixel's value in the pixel array becomes the index of this node's mean +% color in the color map. +% +% With the permission of USC Information Sciences Institute, 4676 Admiralty +% Way, Marina del Rey, California 90292, this code was adapted from module +% ALCOLS written by Paul Raveling. +% +% The names of ISI and USC are not used in advertising or publicity +% pertaining to distribution of the software without prior specific +% written permission from ISI. +% +*/ + + final static boolean QUICK = true; + + final static int MAX_RGB = 255; + final static int MAX_NODES = 266817; + final static int MAX_TREE_DEPTH = 8; + + // these are precomputed in advance + static int SQUARES[]; + static int SHIFT[]; + + static { + SQUARES = new int[MAX_RGB + MAX_RGB + 1]; + for (int i= -MAX_RGB; i <= MAX_RGB; i++) { + SQUARES[i + MAX_RGB] = i * i; + } + + SHIFT = new int[MAX_TREE_DEPTH + 1]; + for (int i = 0; i < MAX_TREE_DEPTH + 1; ++i) { + SHIFT[i] = 1 << (15 - i); + } + } + + /** + * Reduce the image to the given number of colors. The pixels are + * reduced in place. + * @return The new color palette. + */ + public static int[] quantizeImage(int pixels[][], int max_colors) { + Cube cube = new Cube(pixels, max_colors); + cube.classification(); + cube.reduction(); + cube.assignment(); + return cube.colormap; + } + + static class Cube { + int pixels[][]; + int max_colors; + int colormap[]; + + Node root; + int depth; + + // counter for the number of colors in the cube. this gets + // recalculated often. + int colors; + + // counter for the number of nodes in the tree + int nodes; + + Cube(int pixels[][], int max_colors) { + this.pixels = pixels; + this.max_colors = max_colors; + + int i = max_colors; + // tree_depth = log max_colors + // 4 + for (depth = 1; i != 0; depth++) { + i /= 4; + } + if (depth > 1) { + --depth; + } + if (depth > MAX_TREE_DEPTH) { + depth = MAX_TREE_DEPTH; + } else if (depth < 2) { + depth = 2; + } + + root = new Node(this); + } + + /* + * Procedure Classification begins by initializing a color + * description tree of sufficient depth to represent each + * possible input color in a leaf. However, it is impractical + * to generate a fully-formed color description tree in the + * classification phase for realistic values of cmax. If + * colors components in the input image are quantized to k-bit + * precision, so that cmax= 2k-1, the tree would need k levels + * below the root node to allow representing each possible + * input color in a leaf. This becomes prohibitive because the + * tree's total number of nodes is 1 + sum(i=1,k,8k). + * + * A complete tree would require 19,173,961 nodes for k = 8, + * cmax = 255. Therefore, to avoid building a fully populated + * tree, QUANTIZE: (1) Initializes data structures for nodes + * only as they are needed; (2) Chooses a maximum depth for + * the tree as a function of the desired number of colors in + * the output image (currently log2(colormap size)). + * + * For each pixel in the input image, classification scans + * downward from the root of the color description tree. At + * each level of the tree it identifies the single node which + * represents a cube in RGB space containing It updates the + * following data for each such node: + * + * number_pixels : Number of pixels whose color is contained + * in the RGB cube which this node represents; + * + * unique : Number of pixels whose color is not represented + * in a node at lower depth in the tree; initially, n2 = 0 + * for all nodes except leaves of the tree. + * + * total_red/green/blue : Sums of the red, green, and blue + * component values for all pixels not classified at a lower + * depth. The combination of these sums and n2 will + * ultimately characterize the mean color of a set of pixels + * represented by this node. + */ + void classification() { + int pixels[][] = this.pixels; + + int width = pixels.length; + int height = pixels[0].length; + + // convert to indexed color + for (int x = width; x-- > 0; ) { + for (int y = height; y-- > 0; ) { + int pixel = pixels[x][y]; + int red = (pixel >> 16) & 0xFF; + int green = (pixel >> 8) & 0xFF; + int blue = (pixel >> 0) & 0xFF; + + // a hard limit on the number of nodes in the tree + if (nodes > MAX_NODES) { + System.out.println("pruning"); + root.pruneLevel(); + --depth; + } + + // walk the tree to depth, increasing the + // number_pixels count for each node + Node node = root; + for (int level = 1; level <= depth; ++level) { + int id = (((red > node.mid_red ? 1 : 0) << 0) | + ((green > node.mid_green ? 1 : 0) << 1) | + ((blue > node.mid_blue ? 1 : 0) << 2)); + if (node.child[id] == null) { + new Node(node, id, level); + } + node = node.child[id]; + node.number_pixels += SHIFT[level]; + } + + ++node.unique; + node.total_red += red; + node.total_green += green; + node.total_blue += blue; + } + } + } + + /* + * reduction repeatedly prunes the tree until the number of + * nodes with unique > 0 is less than or equal to the maximum + * number of colors allowed in the output image. + * + * When a node to be pruned has offspring, the pruning + * procedure invokes itself recursively in order to prune the + * tree from the leaves upward. The statistics of the node + * being pruned are always added to the corresponding data in + * that node's parent. This retains the pruned node's color + * characteristics for later averaging. + */ + void reduction() { + int threshold = 1; + while (colors > max_colors) { + colors = 0; + threshold = root.reduce(threshold, Integer.MAX_VALUE); + } + } + + /** + * The result of a closest color search. + */ + static class Search { + int distance; + int color_number; + } + + /* + * Procedure assignment generates the output image from the + * pruned tree. The output image consists of two parts: (1) A + * color map, which is an array of color descriptions (RGB + * triples) for each color present in the output image; (2) A + * pixel array, which represents each pixel as an index into + * the color map array. + * + * First, the assignment phase makes one pass over the pruned + * color description tree to establish the image's color map. + * For each node with n2 > 0, it divides Sr, Sg, and Sb by n2. + * This produces the mean color of all pixels that classify no + * lower than this node. Each of these colors becomes an entry + * in the color map. + * + * Finally, the assignment phase reclassifies each pixel in + * the pruned tree to identify the deepest node containing the + * pixel's color. The pixel's value in the pixel array becomes + * the index of this node's mean color in the color map. + */ + void assignment() { + colormap = new int[colors]; + + colors = 0; + root.colormap(); + + int pixels[][] = this.pixels; + + int width = pixels.length; + int height = pixels[0].length; + + Search search = new Search(); + + // convert to indexed color + for (int x = width; x-- > 0; ) { + for (int y = height; y-- > 0; ) { + int pixel = pixels[x][y]; + int red = (pixel >> 16) & 0xFF; + int green = (pixel >> 8) & 0xFF; + int blue = (pixel >> 0) & 0xFF; + + // walk the tree to find the cube containing that color + Node node = root; + for ( ; ; ) { + int id = (((red > node.mid_red ? 1 : 0) << 0) | + ((green > node.mid_green ? 1 : 0) << 1) | + ((blue > node.mid_blue ? 1 : 0) << 2) ); + if (node.child[id] == null) { + break; + } + node = node.child[id]; + } + + if (QUICK) { + // if QUICK is set, just use that + // node. Strictly speaking, this isn't + // necessarily best match. + pixels[x][y] = node.color_number; + } else { + // Find the closest color. + search.distance = Integer.MAX_VALUE; + node.parent.closestColor(red, green, blue, search); + pixels[x][y] = search.color_number; + } + } + } + } + + /** + * A single Node in the tree. + */ + static class Node { + Cube cube; + + // parent node + Node parent; + + // child nodes + Node child[]; + int nchild; + + // our index within our parent + int id; + // our level within the tree + int level; + // our color midpoint + int mid_red; + int mid_green; + int mid_blue; + + // the pixel count for this node and all children + int number_pixels; + + // the pixel count for this node + int unique; + // the sum of all pixels contained in this node + int total_red; + int total_green; + int total_blue; + + // used to build the colormap + int color_number; + + Node(Cube cube) { + this.cube = cube; + this.parent = this; + this.child = new Node[8]; + this.id = 0; + this.level = 0; + + this.number_pixels = Integer.MAX_VALUE; + + this.mid_red = (MAX_RGB + 1) >> 1; + this.mid_green = (MAX_RGB + 1) >> 1; + this.mid_blue = (MAX_RGB + 1) >> 1; + } + + Node(Node parent, int id, int level) { + this.cube = parent.cube; + this.parent = parent; + this.child = new Node[8]; + this.id = id; + this.level = level; + + // add to the cube + ++cube.nodes; + if (level == cube.depth) { + ++cube.colors; + } + + // add to the parent + ++parent.nchild; + parent.child[id] = this; + + // figure out our midpoint + int bi = (1 << (MAX_TREE_DEPTH - level)) >> 1; + mid_red = parent.mid_red + ((id & 1) > 0 ? bi : -bi); + mid_green = parent.mid_green + ((id & 2) > 0 ? bi : -bi); + mid_blue = parent.mid_blue + ((id & 4) > 0 ? bi : -bi); + } + + /** + * Remove this child node, and make sure our parent + * absorbs our pixel statistics. + */ + void pruneChild() { + --parent.nchild; + parent.unique += unique; + parent.total_red += total_red; + parent.total_green += total_green; + parent.total_blue += total_blue; + parent.child[id] = null; + --cube.nodes; + cube = null; + parent = null; + } + + /** + * Prune the lowest layer of the tree. + */ + void pruneLevel() { + if (nchild != 0) { + for (int id = 0; id < 8; id++) { + if (child[id] != null) { + child[id].pruneLevel(); + } + } + } + if (level == cube.depth) { + pruneChild(); + } + } + + /** + * Remove any nodes that have fewer than threshold + * pixels. Also, as long as we're walking the tree: + * + * - figure out the color with the fewest pixels + * - recalculate the total number of colors in the tree + */ + int reduce(int threshold, int next_threshold) { + if (nchild != 0) { + for (int id = 0; id < 8; id++) { + if (child[id] != null) { + next_threshold = child[id].reduce(threshold, next_threshold); + } + } + } + if (number_pixels <= threshold) { + pruneChild(); + } else { + if (unique != 0) { + cube.colors++; + } + if (number_pixels < next_threshold) { + next_threshold = number_pixels; + } + } + return next_threshold; + } + + /* + * colormap traverses the color cube tree and notes each + * colormap entry. A colormap entry is any node in the + * color cube tree where the number of unique colors is + * not zero. + */ + void colormap() { + if (nchild != 0) { + for (int id = 0; id < 8; id++) { + if (child[id] != null) { + child[id].colormap(); + } + } + } + if (unique != 0) { + int r = ((total_red + (unique >> 1)) / unique); + int g = ((total_green + (unique >> 1)) / unique); + int b = ((total_blue + (unique >> 1)) / unique); + cube.colormap[cube.colors] = ((( 0xFF) << 24) | + ((r & 0xFF) << 16) | + ((g & 0xFF) << 8) | + ((b & 0xFF) << 0)); + color_number = cube.colors++; + } + } + + /* ClosestColor traverses the color cube tree at a + * particular node and determines which colormap entry + * best represents the input color. + */ + void closestColor(int red, int green, int blue, Search search) { + if (nchild != 0) { + for (int id = 0; id < 8; id++) { + if (child[id] != null) { + child[id].closestColor(red, green, blue, search); + } + } + } + + if (unique != 0) { + int color = cube.colormap[color_number]; + int distance = distance(color, red, green, blue); + if (distance < search.distance) { + search.distance = distance; + search.color_number = color_number; + } + } + } + + /** + * Figure out the distance between this node and som color. + */ + final static int distance(int color, int r, int g, int b) { + return (SQUARES[((color >> 16) & 0xFF) - r + MAX_RGB] + + SQUARES[((color >> 8) & 0xFF) - g + MAX_RGB] + + SQUARES[((color >> 0) & 0xFF) - b + MAX_RGB]); + } + + public String toString() { + StringBuffer buf = new StringBuffer(); + if (parent == this) { + buf.append("root"); + } else { + buf.append("node"); + } + buf.append(' '); + buf.append(level); + buf.append(" ["); + buf.append(mid_red); + buf.append(','); + buf.append(mid_green); + buf.append(','); + buf.append(mid_blue); + buf.append(']'); + return new String(buf); + } + } + } +} diff --git a/src/tm/icons/Add24.gif b/src/tm/icons/Add24.gif new file mode 100644 index 0000000000000000000000000000000000000000..fecc7a8373ae392878c5b144ba77bb371f907a70 GIT binary patch literal 470 zcmZ?wbhEHblwgoxxcZ;r|NsBbpZ|aU?Ekap|DQek|K!QPCr|!9dHnbBz&(QZ{PWP`}Wr>SKeL*qRT+^=G?jeXU;s^yLa#A&1W`mInN6F{tX+G2?b>5& z)*M^1WZ#k{d*{sAI%oFQnKL&rFfbfAZ~#cs0x14uVPs%XV$cB@4)T)&+X9D)1s*z5 z{fZ684|=9BiDoFMaLTrxTwyjL(aL7g1ksgqD$blyNvPpvo_9M}ZQ`CbjYoUpc7!o^ zRW(-TI(w#j`}&7uw|I626$aO*ObjfR;VYdIG(A4Cv1K8{K3o8T~fx7mf_ny zYwZTVppebW8GN=)Oj_gOxp%^xod+3?6miNNYdtY>?n2Ka7bDK*%{d(}JiqFI(yE7x zuial3?#Q6{&)+$}pt2}4J)=ay$iTorA*oU!xHM0}H#4~?zqqovBsI5KN5L~MSx><+ pCr2R&q_9{aD784Xs4O)_kC)5K$4$XKNFgk>NWoCgfR~HG8UUH;yg>i} literal 0 HcmV?d00001 diff --git a/src/tm/icons/Back24.gif b/src/tm/icons/Back24.gif new file mode 100644 index 0000000000000000000000000000000000000000..787518c8ce9b57f2abc04a5679f71be7031bc089 GIT binary patch literal 422 zcmZ?wbhEHblwgoxxcZ;r|Ns9_p8k9M`0vAqzaQNHdH3G;+qb{my!q+o&1cuIf4Fkx z-K9&f&!2yJ_T2N+r=OlY`S|#;2S<!ukYS{b?45@+qYlb zy6ybdt>?FFIlFoDnRV-quUT_!#fpQ=mhE4-VAs5PJ7&$=JY&YjDO1)?oVcpDcUf20 z;6Rvz`$_ezyTmhBvAax!pOj2$e;sK5Au@(Tfu=D1s*z5 z{Vozsivla-7#NDUf?L+G-Y8j}lC|9_!Y$P?a^C}!kXdevZaXhsx-znPcZs!)jG?Iq zZ+>+miyUKBb7xnsS5rZSR%!JF|G*ya%4wMsN@q<@trhI+spnPZT0EOok+n^~+n{}3 zS59|=BZJ~Uf9L#y%A(Blj1mPS0|Ntvq)LV0(mVy<%;ci{;>zNZ)ZAhn1<$->Jq5>{ o9EBi|!eWJ>)Z)~lveXnkUM?>mHwE_~g|O5j1w%apUM>b}04xEyoB#j- literal 0 HcmV?d00001 diff --git a/src/tm/icons/Bookmarks24.gif b/src/tm/icons/Bookmarks24.gif new file mode 100644 index 0000000000000000000000000000000000000000..3b180449f448e920cac8b70a70b51e3a38397439 GIT binary patch literal 283 zcmV+$0p$KiNk%w1VHf}y0JHx900030|Nly6Om>lYgPw(rsgIhqoTtL6xz)SI;>hyy z@~Eh&dU|?nY-|k;4Zy&_A^8LW000jFEC2ui02lxm000Da@X1N5z0)boE6`o2fguJ2 z2w7HIl5VB*&8Vw(TA=8z4U33gaCqZ5hC<)!m?Zvi$Y>G6j4ESRqD97?RhvbJ;V?E7 z1YhK7TPB~=S617Mwyx#mJpFs8i1m7J0|WpIPY+#*UH}aYIu<*TI+Kz+E0>rh5db0n zPeX5Td2(rIXmlVlFfcG6VtF7_b#5R{X=8G4b9r-gWo>gTAW3dxE+9c{Y#>r;XJ~YD hAW~&>WpZ|9WG)Q~N=!x|M^YeGWpW@fE-(!W06W!{aPCMz{;QlQUfxB zfyHja3D4DgEnc79{r`bWi>TqGNtO#(4fm|zYG+w6Z(ihfi*zyOrUlOz|FPSluCMz{;QlQUfxB zfyH6N3D4DgEnc79{Xan?>BtVjhM5ajW^G(+eQ=}CbhCr6EEyJ9T-RN(=x@p-=}ik< a-c|U?7J9CYT7P3r+3B}c`)_eDSOWkOFET&? literal 0 HcmV?d00001 diff --git a/src/tm/icons/ColorReplacer24.gif b/src/tm/icons/ColorReplacer24.gif new file mode 100644 index 0000000000000000000000000000000000000000..bb0c604fc20ef4257193c9950ed00dbcf2ac3e9b GIT binary patch literal 166 zcmZ?wbhEHblwgox*v!E2pMl}bng26qp3yU$#lXOD;J^VOi3ceDWMO1rU}ew&sR5b6 zz!JRSgy-tL7O&6l{;%NPlaeVUp}0oJaL&(X7V*1Xpav$(h>R?K-H*z$F~RHn=13b~_wdX+q( zIwCw%F59e}rkCJ+TJ_H^)5Z#&0~3x5s&z}6BqiofT*K-f*Lib7*4*uf?l~1&l{9*! zC#AKAI>aaR334(h{_}UvFQ_caOwTA$FfuSOP)Mp&2rkW2@Xbsv$}g@gE=kQT)=}`x uOV(3x%*jy*0x2w32udwZEhvHOc=A426P_y`Hpc~szNZ)ZAhn1<$->Jq5>{9EBi|!eWJ> g)Z)~lveXnkUM?>mHwE_~g|O5j1w%apUM>b}05SVjh5!Hn literal 0 HcmV?d00001 diff --git a/src/tm/icons/Copy24.gif b/src/tm/icons/Copy24.gif new file mode 100644 index 0000000000000000000000000000000000000000..c665d0713e15fdff54a8ba7fcdfee29bb46590fc GIT binary patch literal 682 zcmZ?wbhEHblwgoxc=n&+|NsBbpZ|aU?Ekap|DQek|MV#k{d@A{@8idRA3gf>@Zs+V z4}RXi|MT9xA9wG5yL0F3ty^Di-uis==BFDsK3>26;mVb_moLA$bm{fQi?1$RczO2h z^Rs84ojLRW%$aAKH=o(O>CC3hXEp)JO{X_*JiTGVsSWE-uHSHS-TD*j)&bG+wQG;9 zS#xyt>LaUG9a*{Z(DLO6mn}Q6blLtTOZP2VvTyN{y^9y`U9@P=f(5(g&)+$3-j2C* zx6huvW!9|CGiL(PCI$wE0|yQO$)O7rf3h$#FgP&ifV=>T69@J!4GvAsEv;>B_6$;n zJe^ij{q{04_U%pfGiEZVGs?|n)D*Gm?C9!WJbCK0*3S8T-F$QA%~;($bNdd4jvX_% zu309!XYcAxzRe8FMGYAzty;Q{!H`dN{yfbkTRZ1n6S0_ZW8cF^kEb&{d%orIdMi== zv#(BccRqjia$4slxy}g_4o*43u;QihRt*Nz>iyf^o(}JwxvphF*UXF`N;eKWeTm9t zzUs@oqng2P?gD}4`|jRfg61iU>j^L@{_}UvFQ_caOwTA$FfuSOP)Mp&2rkW2@Xbsv z$}g@gE=kQT)=}`xOV(3x%*jy*0x2w32udwZEh$>7f8fA@?Cj$e6<0oe`gHT=&FRypcXf5OwY61NR;s9| z@bdD4)PaHGPZmZ71||j_5D#Pq1IxmI6P~O0^0ZhpYR_5Lday&Zb5p2SP)*G5rmN43 zCYc4t?<`u`;3E|BP|bESUzx}WFV4GbXL2tnvCBFhej-a%a(?@_qg{1Z3V$rkc9ZPx zk(p>YLAQs|aXs6c?>?fOHI*#fj2sPh%w=MA-pulqo-ArM6BYVZr%F#Q7vk!w)?;s} z;>Zx1T{VMEf6bivtGFcf*o0Ww$k3de0cBMqX(bw-Fg51?f;k0 zf9%_H^~AAzXHGplee%Jn6ZbD)e175FlZW@eUAyw~!nwyUp8dId`~96;?{43G`|a!h zOBY@}dHnV9qpy!2f4yQB=AQ`s)qn1Ju@PuXO902%p5Wv z8x|aF?iA9BIU&H{^rS8kTY<%J?X6DM^+c@cjvRji> z{}#?G$IegHa%r;Ry!)@4IUpaeSYfD>v4-?RVMp#KQ&)RrrOKx z{qt?gpG=W_%(B{hZRfX`jZLopa~0DT6+}+@nyzG1vf_fFkxJhL{kTb2S~*L21x+%q z{89M4U~E+!ssX&0ve4D&5b-d5ed>c8}_=~Zrm)pulGNN{9R<(4WIYAPoE(K9 lkiuexpw!~jqO#N!Jzg#^A2$W}Ace5hA_YS|170o$YXHbChv5JK literal 0 HcmV?d00001 diff --git a/src/tm/icons/DecHeight24.gif b/src/tm/icons/DecHeight24.gif new file mode 100644 index 0000000000000000000000000000000000000000..d4d811a6f1349c24135fc724339ce0b9be5c5d42 GIT binary patch literal 903 zcmZ?wbhEHblwgox_|Cxa|NsBz&;LJv_W#-Q|IeQNfAZwtlP7 zYmO~hvahS>!JIi;=gi*f% zl|#m3!-9j&9KupO2RAG{+|DarHp64%qNANc`dLd>Y)E$MP>@f%v!YPNvs*4$jOV0L z%gM1tYg16HqXDm(r3l12F2aA7g?-5FnQ%*xBZ z9=ToGPP6Z*kG+js2TwR_LreftF&7_0$I%Wp3L literal 0 HcmV?d00001 diff --git a/src/tm/icons/DecWidth24.gif b/src/tm/icons/DecWidth24.gif new file mode 100644 index 0000000000000000000000000000000000000000..aee6ecc8c112d286376c8d2c48df48af3328abe9 GIT binary patch literal 932 zcmZ?wbhEHblwgox_|Cxa|NsBz&;LJv_W#-Q|IeQNfAZwtlP7 zYmO~hvahS>!JIi;=gi*fL9R@AVf_%;nH75*Q+W7?Z(~d+0E_Usam&}uq+_b=DvRrVHjK{=; z6Vs(4r7T_sJ@sf*3R^ kTJmyAiqG_jsp~>!eASNJsC2qd^yId+x3{w}Gci~L08-12kN^Mx literal 0 HcmV?d00001 diff --git a/src/tm/icons/Delete24.gif b/src/tm/icons/Delete24.gif new file mode 100644 index 0000000000000000000000000000000000000000..96d799a0af0e2276358b794cb9921b80654bd2f6 GIT binary patch literal 249 zcmVgYnPz5YGcz*)006+izyJUMA^8LW000I6 zEC2ui02lxm000APXu90~Fv?Zxj3wxD75QK&Mg*XpfuO2G35jqBkS3b4<@^Fd8Vmt~ zfY8$IdOe_!=%OKi!C_HSdMc&OqwmTzKC0Vjm&yw-r%p50>i{RkXzlx){g&rzvh5~_ ze`6wS4giFOhJ_u8iW3O{A^uN8Z*X~XX=iA3ATls8Fd$-iAX9a2AWdmwa&L2ab97~G zb1Wc9ZeuPWL2PUwQfX&sbaNn5Wpib6c4cHP4GKz3Mj%I0AXa5^ATcg54GI7|RwZ9~ literal 0 HcmV?d00001 diff --git a/src/tm/icons/Down24.gif b/src/tm/icons/Down24.gif new file mode 100644 index 0000000000000000000000000000000000000000..2c47af8c3afb3f2de068be2db7439b8c142393b4 GIT binary patch literal 635 zcmZ?wbhEHblwgoxc=n&+|Ns9_pZ$OG^xxyhe;z*i{oui``wxEJzxU(rz3+GKe!G3= z>#bW~Zr=QS^X9V~H$Gjz{_)zi4_B|gyL|cWXU{%A zbLQEpQ%_Eucy#R8{lkav96WIAz=1RS_Fdn-`^wIpm$z@fxOMBfEnCiR-h5{L`V(u{ z9$&NO=*m@xSFAX+V#UE_%ML7Ex_`-%eTx_GS+r>P!iBpQEZ8}J{*JkGx6huvb>_^? zGiGd@G)HK`JIE{gU;lP0dKyoMo#h)yU3=B>TIv~e`;>3Zy zwZW;WxuvzO)sa_0)lS8+L()uKU(lhw&5_Z8fnoZ*`3syJCr%X9=g?!DJ$K>Sb?cit z`=>A7-0rAoqi7}D?>KoG$La-+{F)q^v*v7QUUTOBg^LTfZJF2EeWiKvq?;Rib}DY$ zZ?=s8@C?~KW|EFi^$wk$|5l&>{mJKR9ofHsJoDoc1M@a676!$C{?7RYl|`B986^rv z1_lNSNtFu0rFjaznaM@@#g)Y+sky~E3Z8k%dJ2v?ISN4_g~bX%sl};9WvMB8yj)&B UZVK)}3Sp^53Wj{0Aq*qg8%>k literal 0 HcmV?d00001 diff --git a/src/tm/icons/Dropper24.gif b/src/tm/icons/Dropper24.gif new file mode 100644 index 0000000000000000000000000000000000000000..b169539fabb96fac1cefdf0dafb99c07f2b5c7f6 GIT binary patch literal 150 zcmZ?wbhEHblwgox*v!E2|Ns9pXa3KedB)f{je&vTz<~om5)V-P$->CMz{;QlQUfxB zfyH^l3D4DgEnc79z5j>-hrBDpqX55^JGQ;!Uhgt-oh$E?td;zxQH%;4zgUzXw<|bk cP4|ph_ai3E_H53!C0D)nKiE(q#K>R`0Px{1V*mgE literal 0 HcmV?d00001 diff --git a/src/tm/icons/DropperCursor24.gif b/src/tm/icons/DropperCursor24.gif new file mode 100644 index 0000000000000000000000000000000000000000..6689523529d954efac0a031773c03e4cf2c861ea GIT binary patch literal 162 zcmZ?wbhEHbRA5kG*v!E2|Ns9pXa3KedB)f{je&vTz<~om5)V-P$->CMz{;QlQUfxB zfyIBr3D4DgEnc5h{Sh0%;KJD<9XTsw*}5Y)!{pDLyUcxhNBaG}PB~v6eofjMQP8B) pIPH)UFSb;j&D(vyz>kH&8UO<$IL`n8 literal 0 HcmV?d00001 diff --git a/src/tm/icons/End24.gif b/src/tm/icons/End24.gif new file mode 100644 index 0000000000000000000000000000000000000000..2eba15292077f38f90f01fc13b864dd206d71b7e GIT binary patch literal 1104 zcmeH`>q}E{0ET}<#X~5Lie)BvDN@8+e$v$NmX{JyD<}|YX=a%#L<^VT)V4KsI?sk~ zbDmAz-LtbzcR54Rxuxd3ZC=vcK3F6agiHy$e8}{l=u_`M@Vw6pZ(c!eatb*Z1cM&{ z93355t=3mmgvn5|JM}y+-q$-WM(i@_yhLmt5Lp%S1-Z;29iAH+oKY$kG^kUpS~8p5 zqxuakwrasWiHYR&bP9!n+_^(7E2EW{x75`MtE$>-YPu;DxS>HvqbV5-EuD^1sR)au zZ)%dT*~aGPVJ>%~txdt@jgh2G1e1LJL|@;yL^6XQ_Wu4Up>R?vogW;Wl}O%-#dZX-4Gc_+L{_D8NugMj z9ru^M8$MPTniYwrP}HSVE-DlYa=Ak$o0m%Gbh-_V#)YEJk&zX(dRcWWX!aP5+oPlJ zb-Hz}b`8T;&1SdBv~4tgFc`MR#x`->V=!!5EFK(pI~;p%_mRtW@bK9BDW{eK*EjH4 z?HJ58^^2y2{gX1eLxZiN8kb7FELS+Rx^-0JRH>KDxW|mU#|)d(w%ygW!-InZ@IU`{ zfrwwe1ONyi_5^$K2>|^8K2T`BPBPsForx*KIYhuDhTZ6__O|*3kYb-KzAL#n*mlkX zwoBy&ysJeoy!Z7!GxTo%I71_i@tGJ~jD8~~uswli5lu;)pZ-Y9GUlg^;+@%GW8jaQ}7wQ|kA}&vWPRCEfZ7?g5fi7+E}; zmSUH6^j^7%1vl0>ZDLZ|ljJWEe)&jbNmt?5R3|w%B_yeS%lk193cBUywIk|wA+fk6o52amq2}a+s-W}nQOS=&_jfY_gReaZ7nEEl_(rv4l|cl9WaezC zEk3}zpOx7XQ;<_x&rhsioq_@;GHm3Emvqvz;=5NaT+Z$as(tIE`I4%4G6@8b`WIPG Bf6V{@ literal 0 HcmV?d00001 diff --git a/src/tm/icons/Export24.gif b/src/tm/icons/Export24.gif new file mode 100644 index 0000000000000000000000000000000000000000..ee523416e5de7726b3c859ad0deda60048b42588 GIT binary patch literal 473 zcmZ?wbhEHblwgoxIP#wX2>$>7f8f9Y1A|0c+q{Vr56zo*e&WQvhYo$3IC1Ow^Z)0~ zJM`((r}O8}A36k-nm2LcL|$HAkT&9g;!hSv1_mYu9guR6oeZo!3l#cNGUsKink2Y+ zmEfg)={X|CwzrPXy}W1k`LA5x`s_ne91@gxI@63ZlUUX;xF$00s4Cs&;u3x;kI~A( zWo=#8&DSAEE-sk8^Q%=UONN7-K%!uMeXJK>1AioYOlPBuT5XFVcT!6iV|!--LtnMh zq`pP1Gfg|DuV|RhG$(uAoTchvo8z`@PT8?jMUlap^9o}e+ktcU%a$g(RIpY>GpMw; zr*?LDs>n!BXs((#vDlSCT25B3US;;|YLEUovdSFn{K`w`M!C&gpv1*1ptL}CQK-yP zMIk|9#WmBLX3bF$5fxL|zSC{VY>@7sOIsb#^*0o9T^n= z`8($qR2F5XXOt)y85kHSBvmQ|m*y$>W+oTq7grXSq~;duD0t>2>nS+qCMz{sEj5&)@XV2+pA zb?2YKDNWWbCLJHk#8|F3B)JOQU|Mw9YRRpivmUP5QKrssHm~1$-qG*DtgT0q)~K-v zure@A;4EcZ%_kEkeYJJN>G12^anm-h_^7Mf%W+PsB5ds<_gj25Y3JYn7UyKJc2o8X zO0r(tY2^L6Jod=p{BtGgHoA4Cjmj0Of`AE36rM?2{I`D^LNfKs4U7%&nQta zGB7YuNUBr_F3nT$%}g%JFRm;uNzEClI$x#RbDJ)h9N-a(;Doah#CMz{;QlQUfxB zfhA(Y3D4DgEnc79J)h-cl literal 0 HcmV?d00001 diff --git a/src/tm/icons/FillCursor24.gif b/src/tm/icons/FillCursor24.gif new file mode 100644 index 0000000000000000000000000000000000000000..128975855dc272869fb631053893029845229a26 GIT binary patch literal 166 zcmZ?wbhEHbRA5kG*v!E2|Ns9pXa3KedB)f{je&vTz<~om5)V-P$->CMz{;QlQUfxB zfhBmu3D4DgEnc79{a?XVK+&BcW#-&9RT~}V?7C!msyqy@&hxT uxqTX;Tc$b$h#A44GVIL-GpWR$_HgEU+4?Al7)^Ap3um%7EJ3EE| literal 0 HcmV?d00001 diff --git a/src/tm/icons/Flip24.gif b/src/tm/icons/Flip24.gif new file mode 100644 index 0000000000000000000000000000000000000000..219a9d5e5fbf07f4f86098230900bbf2802f207a GIT binary patch literal 148 zcmZ?wbhEHblwgox*vtR||Ns9#aNvM}L87f~-o%NA=FK~Q=+LM0=l_5D1SElMpvb(5 z6DRWW@&Xkr{$ycfU|?d<0qF#p!NB4eaKdx-UW?aO-{f4M$0i8&%~{!%v2xZM^E0ny vs^8sRm%-J)Z9xFXldoz!l`pOE`PQ`c=DV-eL8TUHpO-92*!>`mg~1vCx?n?v literal 0 HcmV?d00001 diff --git a/src/tm/icons/Forward24.gif b/src/tm/icons/Forward24.gif new file mode 100644 index 0000000000000000000000000000000000000000..1936fd4bf9d300479fddb665d2650445adbe9f23 GIT binary patch literal 434 zcmV;j0Zsl#Nk%w1VHf}y0M-8h|NsBy=Ktm8{^R5P;o-}&C%_ubw1+uQZq+w|Gl z^4Zzu*VgdV)b7&K>(J2Y(9h}3&F9O@<;lt8$H(Br#NNWf+`z!hzrfkOzSq0E)VaCS zx3|!>wa>J)&a<=3u&~LluE(sb#j2{qsHnlGr@^JAzoVnQqocf`pt_);x}Ki6oSe0q znzNRcuauOnkB_L0ji!i*p@xQ^f`glZftrATnKLtH0002Mz`y_i000000000000000 z00000A^8LW0021vEC2ui02lxm06+$Oz?^VMEEONg#x85cPN)tx*!;(f&;u{Y;%##CGYCrvGe1Toab|Lo;;yp+qd|A z#RV5{s$dg&JFnO4XNF!{`>kVL<7R{IBs6&_h{VG4kyqCKxyQY~PV`Ke4ILC(ParoO$3&PK>waSC z>^=p35lAn7pEeB?qf?9{+d;G-4R~Vdc=W(HEJLpZhqpnz2U$BnYCtMMZrbc!kIcr0 zBZfgKiuWNu0z?jS4Wtz09L9$AmcjO-UHB#t1HE6op8`Zgx>;(xxk3rL^QyW@U4LKl0xz7*8*S5iC(R8*q z>Y5uAS+@E4SbvZWFm-8l&Gjvf%Gyj^ut7c0)?BY`RA?IN>T_^E19@K{Ed-i|T9u-v z>L?OFgRxDm(>Andlp0l?N?D_!e9Yo+`^zAy2{eL&y-K>}y<0!sSF{ ziST^_t|g=NOBCKt-Z3m1LIjf<$| z-ieZnK1nqLwZ5ri&|AA5R&B*Bmz~IPRK@zyXRT8VCu~?_&))TEh?K{ZF04JC@$`b* z_VZktle>%q@5_<|b7xnNt3zUitD@AV%fdr6#s_KPv~F%P?hu=i{DYXW|YoAxW6++(7)o?0w$-HhrC!=VFg z_Wr|2$z8ni$ihtbN}QvGu3BnYwtu}{@;x5@Rr5-Uj*Uc>h;oq5K+I$Yuh?}7sFFO$ zd)5?;{>;Gg1)BZ?AoJk9JbOCDO>K?p;Yxr|UU9g}PcFG`b}N;-!OJN8@O;Hz zx06@U5~jH_KAnleV7I>blQpv=pu?NF_J^2E<~lf+h9zA%*&G#m$ETbrE^qF;6kL{O zWO`iBq6^$_n4-&WI%ca^Zc9dlyU)9uPvtXg??`?lMgHeOx7?$XX3cMJ>?ZEf@N^5%txR>j0L z#Kkoh70pUZ>&njV&&!)sS~{ztVMSZp`qtJpRaNskJ2%$UEa>gsT3^3-^5i|u&C4fG z-rd=`uC;aLq)9t_dN#JVukP*L*wwXe%9NdxCT*WEVM}-Sx|uWgPnoh~^5pH4CT*KI zaqG;P`)178GkyB*1q+VOn|FBj?ESN5?OU?s!lGky=Imdy=HiMKXO=HNy=>X3rAtpPS#o^ChO2AWUR<;0!s^xM zSFJj?66nG0ceZZ5wQ19}4I8ekUw?Vsx=Y))-`=+E*4C{zw`{qwdGqxhJML`Ra((B{ zJ3DsVK6UEd?c4t^Ui_2_^mWdJ+`LI8r87Fa)=iqcZT6h~vu5vGy6n{2b(hwxy|{AK zxn;{wt>18E&DskqSDoFyNLOe(=!KOP9ZW`t*rm6wo&W6o0ZXGB7YQ=zy#R zam7=u6)$412?(js9tcPbhu9BNn9QZV?y#L3`m>9f(Ros8Y4215OIFgty7qw8)OA5hWl@{AxNh>a7{g0~3t7!$aBOCBagF-Zvvcg`=UEXqvJC{ZvnFfdR^s#FLr%~SBrOfJeVt}HG|%`MhZ@XSlr sQ*g}5Q3wJlELI3gElw>eOHI+^CMz{;QlQUfxB kfkkq|3D4DgEnc79{XapYFC}wc#;SEWulE)Fab>Uu0M!*8+yDRo literal 0 HcmV?d00001 diff --git a/src/tm/icons/Import24.gif b/src/tm/icons/Import24.gif new file mode 100644 index 0000000000000000000000000000000000000000..6a34d20bfc40b213e99c6556fa77db9a2d255b3d GIT binary patch literal 473 zcmZ?wbhEHblwgox*!-UX2>$>7f8f9Y1A|0c+q{Vr56zo*{?MUM=gdt`R{Y7r$iTqFpaaqgGJ}DoHQb+MP-)@-BP^94SA@N+Ih+k1$V&atb zQ`hCj9^Jgs-+bC@cBc~=TOFJvb2O*QGb9?AO05W4(yspcTh^Vc=BGHPn=$k!FHHFC z^~RNNS%$%zg_C68Z`OU+P}RU&EXGjU+*zYhU)@#SYTeN{g(pg~x4(L#NJi@Xj9M}8 zCH_m7xabQqSVP^zw%B2EfrpM%|A{9XSrV*f2c!#aco})(LEp6_Fxh$+4 zs{IMxfefrHTuW!UGfJ&hows1!=EYuW%T_RKOWdfs+j+~5m1~c9sWLI2*m&~f>OIRZ z?9Jc3;o|&r+pb>P?{an19aq)+4<25A^8AIHBZJ~Uf9L#y%A(Blj1mPS0|Ntvq)LV0 z(mVy<%;ci{;>zNZ)ZAhn1<$->Jq5>{9EBi|!eWJ>)Z)~lveXnkUM?>mHwE_~g|O5j M1w%apUM>b}0164ckN^Mx literal 0 HcmV?d00001 diff --git a/src/tm/icons/IncHeight24.gif b/src/tm/icons/IncHeight24.gif new file mode 100644 index 0000000000000000000000000000000000000000..6c386c67869d28313bd71677dc15f0fe9d806263 GIT binary patch literal 904 zcmZ?wbhEHblwgox_|Cxa|NsBz&;LJv_W#-Q|IeQNfAZwtlP7 zYmO~hvahS>!JIi;=gi*fY)E$MP>@f%v!YPNvs*4$jOV0L z%gMA& zdl^@+>s$V^LRs5?yZ^o1hAPR1I??>L_L|)Cn$Ds=&54sL`je*y)~W_gOURi!uhh9f j+i^i`kG$D(S;IAJ*RQqMyk+aQ?K^hv+N~ zYmO~hvahS>!JIi;=gi*fL9R@AVf_%;nH75*Q+W7?Z(~d+0E_Usam&}uqELw1+Sur@vq;k^& zuL;_$Z3Y)EEjd10L0M|SOCj}>a~&#gwRnmo1uW2w|7Q~woar^!seMvU=9XnX^Ho!$ j_C}d#A8CtNsaB#TmUDfR#^EB7liSwb-pCMz{;QlQUfxB zfkkt}3D4DgEnc79{r`bW%TX(~10kRTQUKD+z~XLj!gKXri`QpY zN;s6)GHZk_sjPbS%FjvX{FVkzmv!%}Uw?F%%P+>mr@C@d(Mq0Jh6^i7Ue)Zi3k}z* Tz7@r+`i|?D?(Fl=I2fz}RkJPw literal 0 HcmV?d00001 diff --git a/src/tm/icons/Mirror24.gif b/src/tm/icons/Mirror24.gif new file mode 100644 index 0000000000000000000000000000000000000000..064c60441a4382923994931583561ff399c25c62 GIT binary patch literal 156 zcmZ?wbhEHblwgox*vtR||Ns9#aNvM}L87f~-o%NA=FK~Q=+LM0=l_5D1SElMpvb(5 z6DRWW@&Xkr{$ycfU|?d<0qF#p!NB4faKdx-UW?afch5iE-nz)OYk9%4n-kWpiQMzx zj@aha?<>|ka(JMiv4*G9Ddqf%IhwV{=bBV4_H483^5#AzwexyV1dm$(*%w8@9 DBOOKW literal 0 HcmV?d00001 diff --git a/src/tm/icons/Mover24.gif b/src/tm/icons/Mover24.gif new file mode 100644 index 0000000000000000000000000000000000000000..f3b169cb483cfbdf46726cf5c9e6f4d8645246d0 GIT binary patch literal 136 zcmZ?wbhEHblwgox*v!E2|Ns9pXa3KedB)f{je&vTz<~om5)V-P$->CMz{;QlQUfxB zfyH#g3D4DgEnc79{a=PL%Ei(zwQ7;JYTtShapSa28L>-i)~A`z^mZ?jOw_%z>iRF! N$ro0Xh%ho(0|02DCrtnV literal 0 HcmV?d00001 diff --git a/src/tm/icons/New24.gif b/src/tm/icons/New24.gif new file mode 100644 index 0000000000000000000000000000000000000000..1cc488d4524a8f74b5586883fe8d6ab2c91bcb05 GIT binary patch literal 778 zcmV+l1NHnzNk%w1VHf}y0OtPy00030|Np?iz|PC?%*pQ8)cM-i{K?1b$HnQ+%<#?2 z@65{X+u8lv*!Cesc&dl=2#_Pw$>c+(B&CBr2%J0j`?#jsR z)zkRX(e~Nb{Mgp}*VX#AwcNbB;<~xuxwzlN!|TGq=)Jt-#l-8tzvarw@X5&U$j9x( z!|Be=^TovJ(a`qH%kas_?8wLK)ztaY(e}{K^v%rh%E|54)%n`l{n*$0*Vg*l+5Fem z`JSH0sHoDz!}71M*|M_St*zC#xZ$_A;IgvXv9Z{%uhz7*+q1LUzP{$TxZk(8-N3-- zzrW_bzU92UwpP3`I0E~`}kcxr;0dHJBw2G8)WI#npOiCysvYm;YLuhSlP$5?*6B5mdlxJ*e zPfjcmTQ4*Vi~);vQb;CED=AtQJ_|Yt&WDsoR3s`8FlO+;z~IJ*T8BE77!dxq%L6{7ZNyVXfS{QAppVxT*yJ7M}h`81i%#FY-gcP zATr!DAfv`4oxwI0q9pOgjtW{{CN(+Hfdv~?bf%*eX=wlj1zNaxFhx+Nq?LZ!dF1FQ zOrM4nFk#Xu;M69#k_O!^sWh*lz5)UP03rTQLvL_-a%pF1bRaS?Ffbruc_34DZXiu* zV{&hEd2@7SZF4LjNp52`x}SeUO)Ky>VX$m_CL9>=h3;{56%kb3A>i`?^x8gV^Qz+ zMZMb=_H3HlwSIQzx>@aOX11-G-nwXF!-5I*^ZM%M_SVkqs!lUDW?*1AaNq!tL<5RH zSr{1@EE#k_;vhdcu+2Cyr@%u;s^4->(MlGJ`3y1(Iu-|pG5VP)WbM(}!n?LpXZF$y zCA)S_l)GB6qSDX)-n$>S1ErRQ21G|`izendTO>&v3#m6UD)SkNb+oxya7E4Jim&aQ zTDoB2qQy%VR#paw6f#6NC$Dt!*|fQKYE7q+pjw}@V8{At3`s%_GyD1UlS1cvGH7!t zHFD`C%sb<``KI@VrFT6X85IBdJLeZv7GD14S(Y4W0ESJv)zQGv2+dxMTXY3{gIeag2w z+M&ceskJRBRavsTQ#DcABPBIG$%9)$!c@vnD@L!dMs4o=^5BK4iwlF7H7{aVWo5fu zMJp&IigR-s!|KW%y1V@OZ0z(7tX0c8mC@0gs>q=D&)+$}pt2}4J)=ay$iTorA*oU! zxHM0}H#4~?zqqovBsI5KN5L~MSx><+Cr2R&q_9{aD784Xs4O)_kC)5K$4$XKNFgk> NNWoCgfR~HG8UT*vncDyW literal 0 HcmV?d00001 diff --git a/src/tm/icons/Play24.gif b/src/tm/icons/Play24.gif new file mode 100644 index 0000000000000000000000000000000000000000..572467c59508619649b9d374ad3ff2dfee7d229c GIT binary patch literal 247 zcmV5Dk;0yy&%nUIA^8LW000L7 zEC2ui02lxm0009|c)HyFFh&uiJ;97S3#puwd0@B*h4z`tNDM2Bs&L7^f{BE;+5sv%2HmgAuJ=a6xg$R{YU@+JFi(CZgbt(Hx(u( zTV*D%s|H5fPu%nw0RSQXPeX5Td2(rIXmlVlFfcG6VtF7_b#5R{X=8G4b9r-gWo>gT xAW3dxE+9c{Y#>r;XJ~YDAW~&>WpZ|9WG)Q~N=!x|M^YeGWpW@fE-(!W06Y0rU*iA( literal 0 HcmV?d00001 diff --git a/src/tm/icons/Plus24.gif b/src/tm/icons/Plus24.gif new file mode 100644 index 0000000000000000000000000000000000000000..d67ef28cbaa9d9d09e450f2656a1ca565fac36e2 GIT binary patch literal 156 zcmZ?wbhEHblwgox*v!E2|Ns932M*ZU=H=zhn>X(~10kRTQUKD+z!GS1!gKXri`QqD z|AuntqWO!{oD@(@pNY+;sB84jVZ}25SI8RWkwr literal 0 HcmV?d00001 diff --git a/src/tm/icons/Redo24.gif b/src/tm/icons/Redo24.gif new file mode 100644 index 0000000000000000000000000000000000000000..22f40b3826c655a812b1eccaa777f6071e797ff9 GIT binary patch literal 243 zcmZ?wbhEHblwgoxSoELa|NsAI&itP_^Ng`^8Uq8vfddDCBoHY6WMO1rU}ew&aX@Mr zm{TKm-TAkn$K$5L*1iT~WrdBLv21J^S`*ZE?JM{xz?d`H!R7da4MLW&Z`n0|HB6B$ zEac>x?(eOHI+^CMz{sEj5&)@XV2+d6 zb?2YKDbJY=)43S$yqjcD(CgvGWZ2}jYf(!T+sZT3Hr{=<{`h{=(DR?7S=mqA)NAvR zn|&(Qn6tol@mkG*?z2vgi}bzT$l4w9`tmks+1B$n{FmOYT_gUztM2@K6$S=tYd2-T zpd{ulGNN{9R<(4WIYAPoE(K9kiuexpw!~jqO#N!Jzg#^ VA2$W}Ace5hA_YS|170o$YXIpRXrcfB literal 0 HcmV?d00001 diff --git a/src/tm/icons/RotateLeft24.gif b/src/tm/icons/RotateLeft24.gif new file mode 100644 index 0000000000000000000000000000000000000000..08f80d305f0611c3d0588b933642396e8449124a GIT binary patch literal 148 zcmZ?wbhEHblwgox*vtR||Ns9#aNvM}L87f~-o%NA=FK~Q=+LM0=l_5D1SElMpvb(5 z6DRWW@&Xkr{$ycfU|?d<0qF#p!NB4eaKdx-UW?aft>qIm+HMET$%x`v`fAgxm&*#& u)++D)A%X(~er`DdT{RuuS4AuZEZ9Vt^ literal 0 HcmV?d00001 diff --git a/src/tm/icons/RotateRight24.gif b/src/tm/icons/RotateRight24.gif new file mode 100644 index 0000000000000000000000000000000000000000..5fae73d5f9b0b16c8b0bcfcd69eb0a82e22dcfd9 GIT binary patch literal 148 zcmZ?wbhEHblwgox*vtR||Ns9#aNvM}L87f~-o%NA=FK~Q=+LM0=l_5D1SElMpvb(5 z6DRWW@&Xkr{$ycfU|?d<0qF#p!NB4eaKdx-UW?aftK||j+HMET$%x`v`fAgxm&-nw uw`IKb{Io0B_O9NK*#g~7$>~#s3#;_`O}@|OnjVsJY5CLA{Rt^74AuaK4M1W5 literal 0 HcmV?d00001 diff --git a/src/tm/icons/RowDelete24.gif b/src/tm/icons/RowDelete24.gif new file mode 100644 index 0000000000000000000000000000000000000000..8cf24389546b815897cded916532572d4edd716e GIT binary patch literal 248 zcmZ?wbhEHblwgoxSoELa|Ns9pXPz-OPGewTIB?(qkc0rmpDc_F3@i*fATCI)19O(g zt~>9PPI)Rf=$Pz1lIyh1@SYJ*O99h?TYLw(S7aQ%S5aqQ)2}O|@G@CygP-B_OB^dL zRFCv!tkU?o?#7$PC+`M{9t_#?OSNU~;b@-iX$v`*@2K&!UmBTf^UhbS?x$vIda`DW zUrSVH7bk<_KY!=^g36-I^o$Y(BLf2ig``S_;LulGNN{9R<(4WIYAP poE(K9kiuexpw!~jqO#N!Jzg#^A2$W}Ace5hA_YS|170o$YXB>jS`z>O literal 0 HcmV?d00001 diff --git a/src/tm/icons/RowInsertAfter24.gif b/src/tm/icons/RowInsertAfter24.gif new file mode 100644 index 0000000000000000000000000000000000000000..0e32f21a6003ae8a8628fc0124b60a31d1eba161 GIT binary patch literal 239 zcmZ?wbhEHblwgoxSoELa|Ns9pXPz-OPGewTIB?(qkc0rmpDc_F3@i*fATCI)19PIs zt~>v{PI#_PNOn2k_(D#DAt2M}x{$$ZBQ0j}$Sp4OD%LH|d4EqTythm_#bWU}cTKH# z^De9?(el-d3ZHWM>FIxRVN79bT3IsLGt^Qq`1yu%Y5l2Lp?L&#cEP4m(zRzdkK;)Yvok@2+DPR>w95 zM+*nG)w6202Uay?bo=*qhE15*%saI$Wi~e_gW^Ab=lp`oqRjM+5(Ogz0|SMmN`>Ik zJO$s(f^Vuhg8;?$zD)D%5lE-xQ91@|C@u+$<2 LLp=jtE(U7=S*BxA literal 0 HcmV?d00001 diff --git a/src/tm/icons/SaveAll24.gif b/src/tm/icons/SaveAll24.gif new file mode 100644 index 0000000000000000000000000000000000000000..9e4e16840277af7045f71a21be32adcfff297fac GIT binary patch literal 334 zcmZ?wbhEHblwgox*!-UX2>$>7|LN1G^XJbWI&^5>ym=ERPRz^8OH54U<>fta-~dPk z5>Wif!pOkD#h?Qc1DV0VvLfK5=jy#eDrdJpKgi1Bq&R_n(z@pvs)rJIjx12xA}e5U z_3!+%iqB3>@L3_PZSaUw%^>of*GGyIew!w+Oqx<1A?)Mmpdhj5sJg_7lc!FL2r?-C^LNfKs4U7%&nQta zGB7YuNUBr_F3nT$%}g%JFRm;uNzEClI$x#RbDJ)h9N-a(;Doah#KEtq$a^`!1JL1WPbB z462%<1q6tK7)Z*@bz!`gXe=~?D%gOvDz6yMw$$-3I^axYDv2L^9yFf1*@Yp#YiTXMq^#6W=eNR3m0D_2s14nxzUR{uNasq{t2@aPD2b!D* z1&lB~zN0-qiQq@B2_5?!nZuDGVLA-1l+uL-(HkIRr~6L@!a zlNFKGj~Ce40ucZq{!c@1aCvfRXJ~XFGB7YOAYyqSQ*~}2O=)9tZ*zHbbY*RGEFej4 uV=f>;Y-}J>X=iA3b0AV>b7gXNWn?Z53Q9~yAV*RlR%LP^F)lC-3IID(yorVY literal 0 HcmV?d00001 diff --git a/src/tm/icons/Selection24.gif b/src/tm/icons/Selection24.gif new file mode 100644 index 0000000000000000000000000000000000000000..fef12ded16f81c0d6d0dbd3b3fca16d73cc3f4f7 GIT binary patch literal 145 zcmZ?wbhEHblwgox*v!E2|Ns9pXa3KedB)f{je&vTz<~om5)V-P$->CMz{;QlQUfxB zfyHja3D4DgEnc79{Xap&izRT%^3FxG3`F$)95YPI+phbd`di*!Z$0BJ0!>zD{XIi0 WgD+g`GyARUeq&A9>9=)C4AuZdLoQYT literal 0 HcmV?d00001 diff --git a/src/tm/icons/ShiftDown24.gif b/src/tm/icons/ShiftDown24.gif new file mode 100644 index 0000000000000000000000000000000000000000..673b9c3db2414e37c6830e96798d9782bac4e0a8 GIT binary patch literal 159 zcmZ?wbhEHblwgox*vtR||Ns9#aNvM}L87f~-o%NA=FK~Q=+LM0=l_5D1SElMpvb(5 z6DRWW@&Xkr{$ycfU|?d<0qF#p!NB4ZaKdx-UW?afcgrPcwA~JvqgEy6ymQ%`*Q-pT z`zn6#wXr&G8q4N3rM75sP=aLy+bkc|%bc}d^Fv*mhD GU=09@AUTmp)+sVLS F4FCgyMl}Ec literal 0 HcmV?d00001 diff --git a/src/tm/icons/StepBack24.gif b/src/tm/icons/StepBack24.gif new file mode 100644 index 0000000000000000000000000000000000000000..124bac7d962f44adfeadf8e484d4c44f74617a71 GIT binary patch literal 281 zcmZ?wbhEHblwgoxSoELa|Ns9628p(|d5MV=^YZ3RoOo#7yz>VR98mnp!pOkD&Y;5p z1R%8x%mo#@?))=25Dk;0yy&%nUIA^8LW000L7 zEC2ui02lxm000ARc)HyFFv=N&ut5pRL@^(51O%r9pfQME$$20lqQyqhD*Fw#1Q)VV zj5oop4zK}%82JTh%Vp1D)TyFOhjTWR0z}l*G3f?68Z_adQJS~28fg^-3c^OgTAW3dxE+9c{Y#>r;XJ~YDAW~&> dWpZ|9WG)Q~N=!x|M^YeGWpW@fE-(!W06R6HXIuaP literal 0 HcmV?d00001 diff --git a/src/tm/icons/Swap24.gif b/src/tm/icons/Swap24.gif new file mode 100644 index 0000000000000000000000000000000000000000..04b1d0940f2460950ce3ff92b3f529754eb5373e GIT binary patch literal 138 zcmZ?wbhEHblwgox*v!E2|Ns9pXa3KedB)f{je&vTz<~om5)V-P$->CMz{;QlQUfxB zfyI2o2~WE{qlC%b5{DRif7$eEZTG|*>Goy P+WZSEO1yMk7#OSpD`+ZA literal 0 HcmV?d00001 diff --git a/src/tm/icons/TMIcon.gif b/src/tm/icons/TMIcon.gif new file mode 100644 index 0000000000000000000000000000000000000000..aab1babb8cf761acf838628ecd69b7cf493275af GIT binary patch literal 1504 zcmWlZeM}Tb9EM-Hvkq|DQLA06H8+ZQi=eL1$|~xy_yLO=T&>YtZ3f?F9V1INHK2n>V=5kN#x9#jBzK?0S*Nnkv9 z0ZatvR@ui~BZHUSDI)L?1PCGo34#ofgUBHA5JiX*BnF9xBtQ}&Gsrv^ra=)Pi%>+U zJX8UifQ2)>isY4LC^A&nOKynjvP`K0P61QED-aZj3gkXRs0vO6Q^BhcRER1h6>6U( zoCcq2ABcCfY=9wH>hY($>0QoaVD4v-h^O6>;uZ1 zoM19$L9ifNkS$0SWj1)5@HQ1}P7Hw$6CuorVJ3xnIl?P7q9#HYVTjNq=n@PGrUXlZ zCPSBD$S`GCvRjER6HTU?0$qiskhO|W(_m=Obm%$^g&Ha~-DoawhBnGnIa3>D%LutQ zD6kcT6oeI*iKW8QVXLrpgj`l#!&w?vsga0#MnzadWCiLK)ToGPq zmJ6iUB94t-o7@k>v56Cc^QG5`z^U~*4aAAT)Oky1w$6og7BRVy$=92-&h)pKw8f$= zHrG_191C%sW%RFI!<-Ox!qkayonhXo33S&pr!TzIJghz}$Ih!AHR|1_c}|DqI1BH` zRyod2_Qcx{Sc+7*tM5&Kyg&^Zm3y*kZ}RAU|J63mA+M&a@X6tIk(?oHX%?xC&bGfu zekF0+`nGoq_r%LbQWy19<#8$FayBh*nqv=}Hvi1A+9BU=Esc{$`v*%&tFy-}juzE6 z9j!RX)Re4~h1q#~OXd!!E6=$z@ZhY?_cm{#N#&&^;r6oXMl1hP`5N!=k7;Sifj8H+ z1c=0FRfAGYdz~-9;{bC0PC?T4;I9u92#(Qz~^MdTeg3Q7YsqTq1mY!X{ zV0d8VjV*NY`XgBZTKLoO1JyN!gCBp>zv3+}*SC1;ym|cw4)|d0r*-m@>NPE`c^i}7 ze|^G-buZ1G-%wJ?*8hIz#h-fnz0os_1MN4z5B(wU@(tu3t9QQJbNG|zPp=L=dw=Aa zYYWTTBo8@JC=dD?Q+}Q0^o*T9^LkNE-g^@RjU|D@kFGS1t;j6AAU-|ORX*Wf&qnX6 zEmcLiX+QWqzVS0N9=49Zfd{{g&FCpQylAesPMUb(*(zI{`H1?a{By)(C+|Nw=3?5u z)y?poem3UF!^qh)DbMQu`|KhxiI{Kt|<#aoY0-AZZ+O>qQJwaSu`iDA*t!&#KXm>22EjP6UZ_?A+;y! zNlZ(MD{YP&u?xPysG>uur>+!BDLY&9>w+nMe{jpBXfYC}xxZ2NxYd5?rE!}p-wp!P F{|9S61Qh@P literal 0 HcmV?d00001 diff --git a/src/tm/icons/Undo24.gif b/src/tm/icons/Undo24.gif new file mode 100644 index 0000000000000000000000000000000000000000..1d545a77b2adfa6b5496a0523bb3804e818d12db GIT binary patch literal 239 zcmZ?wbhEHblwgoxSoELa|NsAI&itP_^Ng`^8Uq8vfddDCBoHY6WMO1rU}ew&aX@Mr zm=hy*-T7y5%4yZywQXm$m(5n_lQtAQxMC8Eg5YA-)o-=8IM{W6eQmV+_WR8@zIJel zkLfJ({0HiEhLjV8( literal 0 HcmV?d00001 diff --git a/src/tm/icons/Up24.gif b/src/tm/icons/Up24.gif new file mode 100644 index 0000000000000000000000000000000000000000..3db88736f7b15ddd5b131f458cb8373ad5032c41 GIT binary patch literal 429 zcmZ?wbhEHblwgoxxcZ;r|Ns9F9{jv}_uK7T&u`uOeDl_`n>U}`xbf-g)%TY!y}5AV z)wy%ePoI8r^5o-V#~vIxa`*7zyN3>)J9zN+!GpIB9z1*Cz?psfZ|vK5eb1h&yLSW8 zm0i0o@7#HL$Bs+ew_n`8{ld0w7q)Iazjf=mEnCiR-h5{H@`Fp3?3+J-=bSm)X3X3) zZQA;Y6Ib>1E${AL(%HGFvtvc zvM@3*STN{-q(FXhU@Lc+Q{bT^)qmu+f>2Xy-ib$V6PX$M%pJcG+Lv<+PI~S?(3`;jdXwxuF?9~LsKA)k+>Xw!?z$d}1pm$n2E`NeynPkTs>F2o z%Y$YZ)P(hOYb@tj;AAeYBUbClq#CuW+oTq7grXSq~;duD0t>2>nS+q$>7zjVpoqet!<7$n--=5=)~nmBRgym{MJuRgML>E2D7 zPHo(Ha>tGf`}bepx9{4SGf$5my?goc>&us4UAlDd%$e&)k6w8A@Y$6sH$Qy%{P^*+ z88g=>8ZhM9^0wuL9p1kB+@Wn7r`N5TSUIyg>BQ3B^_@kBrq|uyGWXM`PkDKHyu7>z z4jceEf?S~ZlZBCiL7PDbWB|xd3~cKUOfB%xk?KE@62zLYYRYl7XN?;JW?WD_&~!3G zug7_@(}{H<6T6RH5XhHd6$!Z-Yi!nQo)pl)Bv+Ql$05kY!st~ZUfEN@B~a)Uo!HaT z&)ME7(j?8yB)};&(TlaRnRmKyVTTusXmjfVVeXlcEUX(Bva)FUrfKXxsKLk}ui&4? zc=&L-f}GNcG*>MpImL^YoV65{Rc_o&S5Z}$ec+;{t|s%$MONn28<(PwUjiH%6#w}< z=ND8KWu|A8C>R+S7$_uFDg>A2Dfnh47v&dM7MG;v7V9W@<|XSXIOgOi1c4M5D+Hw$ frxul^rs(lKX8IF<1its}i(k literal 0 HcmV?d00001 diff --git a/src/tm/icons/ZoomCursor24.gif b/src/tm/icons/ZoomCursor24.gif new file mode 100644 index 0000000000000000000000000000000000000000..027ce4569da56685c8b8ad6ef78e0c9a740cec60 GIT binary patch literal 950 zcmZ?wbhEHbRA5kG_|5*fYckRrXr$>+8y?pug<;$-wUAlMX%=M#3FFbts?8=p!A3l73{P@|7 znd=h`81ig++w#H=Z(n`x(6)`!>sC#yoLQZ8VrlRC&Z0xp>+Wxv`{~oCyu3VKUfu%- z4uD-TN{oiU0EB?zPZmZ725kl%klmm>!N4(@A)G_TW5a@j%^a*{5jzYPIyZAOdrZ0U zVc}suVdJ1J9RkX(ZF0;d4>$^y9s4!hCWT~dTHroaJH9OEWZ*N$9?kG|8zO_2_|4N} ze)7k2vMSenmrOU8RmIO;CP;>w$liFE;kH_6so&ks;1wrUM2j|+SOsR^Sde=Do6agT g6`!pk%moeAlh@tdUGe$V-P7CG-`}so%*0>~0C|3#LjV8( literal 0 HcmV?d00001 diff --git a/src/tm/icons/ZoomIn24.gif b/src/tm/icons/ZoomIn24.gif new file mode 100644 index 0000000000000000000000000000000000000000..dbd44778a3db23e9b0cd4754a3980c57eed59b91 GIT binary patch literal 484 zcmZ?wbhEHblwgoxxcZ;r|NsB*-+y}Z=JV@)OCLOVcK`m-B-76J->PL z+08Qtu3!In{rZQ?>!x0~@bbd>mnTm?K6&!d$&*(P9lCw!(78hgZyz{t=D_A<`zMy~ z-hE~Ft}DCex9-|~W%JC2b?c6=Zq8c1{NVEC2No>YxnTaznKL&{DT$gidG(}8YbH%v z-QB&UrDbkInr|8q7&90fr!g=v95`?QND>JYf3h$#Fc>oEfYgKhz>ES99jWdO zPK?KL4!QM+Kk%?UWTV5^!?jw3sj^N`N3N>`RXI4f_lx+N?}}+yc{NgA?Vz@l zfrxsJKzfD&M@p-KfC`TyTX89a{`BdU1`^!SwV?)l3e0-*mo4w~lwuX-@R@JGAFplD zBRFM&6l0^7L2It^jxf>W7J~y554r2N_t#C4s zQR92^)PPxX=~I`>A6*?86#w}<=ND8KWu|A8C>R+S7$_uFDg>A2Dfnh47v&dM7MG;v z7V9W@<|XSXIOgOi1c4M5D+Hw$rxul^rs(lKX8IF<1itjdaLs literal 0 HcmV?d00001 diff --git a/src/tm/icons/ZoomOut24.gif b/src/tm/icons/ZoomOut24.gif new file mode 100644 index 0000000000000000000000000000000000000000..259bf9cfe10db2b14ad5af6e82178156caeb5d02 GIT binary patch literal 477 zcmZ?wbhEHblwgoxxcZ;r|NsB*-+y}Z=JV@)OCLOVcK`m-B-76J->PL z+08Qtu3!In{rZQ?>!x0~@bbd>mnTm?K6&!d$&*(P9lCw!(78hgZy!8(`@n%S2R1L; zKe2rG?kl@@UD-Xqb=U4In`btxTX%eQbJp_Z2bV8DuwcQ?1@m{#oVjUANz|mtt0zrb zGilQ5?(QWmEpr>veA9ryn8DaMje&vTz<~omk{F=)lZBCi!H7Wzq!{EU2e#!7GYdR) zq`EgcDIUu?=D{QJz{B>K-CDmMsnsG(jfc`)XC7GPaziDl%E6U=f{3sAzPN^!S0m-s z4(cR}Xygc_XBcv%w5SQF@+h$tmogYkn^tKk$sJuAYRIR^tUqt*vJOvaR#6V0d4~M) zjopHi=SwqgZqCWu7AD%%lQ&_XyTR_>eDnExG4%_LZw6gW^Ab=lp`oqRjM+5(Ogz0|SMmN`>IkJO$s(f^Vuhg8;?$zD)D%5lE-xQ91@|C@u+$<2Lp=jtE(U7=18K@4 literal 0 HcmV?d00001 diff --git a/src/tm/modaldialog/TMAddToTreeDialog.java b/src/tm/modaldialog/TMAddToTreeDialog.java new file mode 100644 index 0000000..344c321 --- /dev/null +++ b/src/tm/modaldialog/TMAddToTreeDialog.java @@ -0,0 +1,195 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.modaldialog; + +import tm.treenodes.*; +import javax.swing.*; +import javax.swing.event.*; +import javax.swing.tree.*; +import java.awt.*; +import java.awt.event.*; + +/** +* +* +**/ + +public class TMAddToTreeDialog extends TMModalDialog { + + private TMTreeNodeTree tree; + private JLabel descLabel; + private JLabel createInLabel; + private JTextField descField; + private JButton newFolderButton; + private TMNewFolderDialog newFolderDialog; + private JScrollPane scrollPane; + +/** +* +* Creates the dialog. +* +**/ + + public TMAddToTreeDialog(Frame owner, String title, tm.utils.Xlator xl) { + super(owner, title, xl); + newFolderDialog = new TMNewFolderDialog(owner, xl); + } + +/** +* +* +* +**/ + + protected JPanel getDialogPane() { + descLabel = new JLabel(xlate("Description_Prompt")); + descField = new JTextField(); + descField.getDocument().addDocumentListener(new TMDocumentListener()); + createInLabel = new JLabel(xlate("Create_In")); + + newFolderButton = new JButton(xlate("New_Folder")); + newFolderButton.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + doNewFolderCommand(); + } + } + ); + + tree = new TMTreeNodeTree(); + tree.setCellRenderer(new FolderCellRenderer()); + scrollPane = new JScrollPane(tree); + + JPanel p = new JPanel(); + GridBagLayout gbl = new GridBagLayout(); + p.setLayout(gbl); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.anchor = GridBagConstraints.WEST; + gbc.fill = GridBagConstraints.NONE; + buildConstraints(gbc, 0, 0, 1, 1, 25, 10); + gbl.setConstraints(descLabel, gbc); + p.add(descLabel); + gbc.fill = GridBagConstraints.HORIZONTAL; + buildConstraints(gbc, 1, 0, 1, 1, 75, 10); + gbl.setConstraints(descField, gbc); + p.add(descField); + gbc.fill = GridBagConstraints.NONE; + buildConstraints(gbc, 0, 1, 1, 1, 25, 10); + gbl.setConstraints(createInLabel, gbc); + p.add(createInLabel); + gbc.anchor = GridBagConstraints.EAST; + buildConstraints(gbc, 1, 1, 1, 1, 75, 10); + gbl.setConstraints(newFolderButton, gbc); + p.add(newFolderButton); + gbc.anchor = GridBagConstraints.CENTER; + gbc.fill = GridBagConstraints.BOTH; + buildConstraints(gbc, 0, 2, 2, 1, 80, 80); + gbl.setConstraints(scrollPane, gbc); + p.add(scrollPane); + + p.setPreferredSize(new Dimension(300, 200)); + return p; + } + +/** +* +* Prompts the user for a folder name, then inserts a folder node with that name +* as a subfolder of the currently selected node in the tree. +* +**/ + + public void doNewFolderCommand() { + newFolderDialog.setName(""); // clear previous input, if any + int retVal = newFolderDialog.showDialog(); // prompt user for folder name + if (retVal == JOptionPane.OK_OPTION) { + // create & insert the folder + String name = newFolderDialog.getName(); + FolderNode folder = (FolderNode)tree.getSelectedNode(); + FolderNode newFolder = new FolderNode(name); + folder.add(newFolder); + ((DefaultTreeModel)tree.getModel()).reload(folder); + tree.expandNode(newFolder); + tree.setSelectionPath(new TreePath(newFolder.getPath())); + scrollPane.revalidate(); + } + } + +/** +* +* Gets the folder where the new item is to be inserted. +* +**/ + + public FolderNode getFolder() { + return (FolderNode)tree.getSelectedNode(); + } + +/** +* +* Gets the description that the user entered for the item. +* +**/ + + public String getDescription() { + return descField.getText(); + } + +/** +* +* +* +**/ + + private class FolderCellRenderer extends DefaultTreeCellRenderer { + + public FolderCellRenderer() { + super(); + setLeafIcon(openIcon); + } + } + +/** +* +* +* +**/ + + public int showDialog(TMTreeNode root) { + tree.loadTreeNodes(root, false); + descField.setText(""); + maybeEnableOKButton(); + SwingUtilities.invokeLater( new Runnable() { + public void run() { + descField.requestFocus(); + } + }); + return super.showDialog(); + } + +/** +* +* +* +**/ + + public boolean inputOK() { + return !(descField.getText().trim().equals("")); + } + +} \ No newline at end of file diff --git a/src/tm/modaldialog/TMBlockSizeDialog.java b/src/tm/modaldialog/TMBlockSizeDialog.java new file mode 100644 index 0000000..df1455c --- /dev/null +++ b/src/tm/modaldialog/TMBlockSizeDialog.java @@ -0,0 +1,135 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.modaldialog; + +import tm.utils.DecimalNumberVerifier; + +import javax.swing.*; +import java.awt.*; + +/** +* +* The dialog where user can enter new dimensions for the block. +* +**/ + +public class TMBlockSizeDialog extends TMModalDialog { + + private JLabel colsLabel; + private JLabel rowsLabel; + private JTextField colsField; + private JTextField rowsField; + +/** +* +* Creates the block size dialog. +* +**/ + + public TMBlockSizeDialog(Frame owner, tm.utils.Xlator xl) { + super(owner, "Block_Size_Dialog_Title", xl); + } + +/** +* +* +* +**/ + + public int getCols() { + return Integer.parseInt(colsField.getText()); + } + +/** +* +* +* +**/ + + public int getRows() { + return Integer.parseInt(rowsField.getText()); + } + +/** +* +* +* +**/ + + protected JPanel getDialogPane() { + colsLabel = new JLabel(xlate("Columns_Prompt")); + rowsLabel = new JLabel(xlate("Rows_Prompt")); + colsField = new JTextField(); + rowsField = new JTextField(); + + JPanel colsPane = new JPanel(); + colsPane.setLayout(new BoxLayout(colsPane, BoxLayout.X_AXIS)); + colsPane.add(colsLabel); + colsPane.add(colsField); + + JPanel rowsPane = new JPanel(); + rowsPane.setLayout(new BoxLayout(rowsPane, BoxLayout.X_AXIS)); + rowsPane.add(rowsLabel); + rowsPane.add(rowsField); + + JPanel p = new JPanel(); + GridBagLayout gbl = new GridBagLayout(); + p.setLayout(gbl); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.anchor = GridBagConstraints.WEST; + + buildConstraints(gbc, 0, 0, 1, 1, 100, 50); + gbl.setConstraints(colsPane, gbc); + p.add(colsPane); + + buildConstraints(gbc, 0, 1, 1, 1, 100, 50); + gbl.setConstraints(rowsPane, gbc); + p.add(rowsPane); + + p.setPreferredSize(new Dimension(200, 60)); + + colsField.setColumns(2); + rowsField.setColumns(2); + + colsField.addKeyListener(new DecimalNumberVerifier()); + colsField.getDocument().addDocumentListener(new TMDocumentListener()); + rowsField.addKeyListener(new DecimalNumberVerifier()); + rowsField.getDocument().addDocumentListener(new TMDocumentListener()); + + return p; + } + + public int showDialog(int initialCols, int initialRows) { + colsField.setText(Integer.toString(initialCols)); + rowsField.setText(Integer.toString(initialRows)); + maybeEnableOKButton(); + SwingUtilities.invokeLater( new Runnable() { + public void run() { + colsField.requestFocus(); + } + }); + return super.showDialog(); + } + + public boolean inputOK() { + return (!colsField.getText().equals("") && !rowsField.getText().equals("") + && (getCols() > 0) && (getRows() > 0)); + } + +} \ No newline at end of file diff --git a/src/tm/modaldialog/TMCanvasSizeDialog.java b/src/tm/modaldialog/TMCanvasSizeDialog.java new file mode 100644 index 0000000..c98e4e8 --- /dev/null +++ b/src/tm/modaldialog/TMCanvasSizeDialog.java @@ -0,0 +1,135 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.modaldialog; + +import tm.utils.DecimalNumberVerifier; + +import javax.swing.*; +import java.awt.*; + +/** +* +* The dialog where user can enter new dimensions for the current view. +* +**/ + +public class TMCanvasSizeDialog extends TMModalDialog { + + private JLabel colsLabel; + private JLabel rowsLabel; + private JTextField colsField; + private JTextField rowsField; + +/** +* +* Creates the canvas size dialog. +* +**/ + + public TMCanvasSizeDialog(Frame owner, tm.utils.Xlator xl) { + super(owner, "Canvas_Size_Dialog_Title", xl); + } + +/** +* +* +* +**/ + + public int getCols() { + return Integer.parseInt(colsField.getText()); + } + +/** +* +* +* +**/ + + public int getRows() { + return Integer.parseInt(rowsField.getText()); + } + +/** +* +* +* +**/ + + protected JPanel getDialogPane() { + colsLabel = new JLabel(xlate("Columns_Prompt")); + rowsLabel = new JLabel(xlate("Rows_Prompt")); + colsField = new JTextField(); + rowsField = new JTextField(); + + JPanel colsPane = new JPanel(); + colsPane.setLayout(new BoxLayout(colsPane, BoxLayout.X_AXIS)); + colsPane.add(colsLabel); + colsPane.add(colsField); + + JPanel rowsPane = new JPanel(); + rowsPane.setLayout(new BoxLayout(rowsPane, BoxLayout.X_AXIS)); + rowsPane.add(rowsLabel); + rowsPane.add(rowsField); + + JPanel p = new JPanel(); + GridBagLayout gbl = new GridBagLayout(); + p.setLayout(gbl); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.anchor = GridBagConstraints.WEST; + + buildConstraints(gbc, 0, 0, 1, 1, 100, 50); + gbl.setConstraints(colsPane, gbc); + p.add(colsPane); + + buildConstraints(gbc, 0, 1, 1, 1, 100, 50); + gbl.setConstraints(rowsPane, gbc); + p.add(rowsPane); + + p.setPreferredSize(new Dimension(200, 60)); + + colsField.setColumns(3); + rowsField.setColumns(3); + + colsField.addKeyListener(new DecimalNumberVerifier()); + colsField.getDocument().addDocumentListener(new TMDocumentListener()); + rowsField.addKeyListener(new DecimalNumberVerifier()); + rowsField.getDocument().addDocumentListener(new TMDocumentListener()); + + return p; + } + + public int showDialog(int initialCols, int initialRows) { + colsField.setText(Integer.toString(initialCols)); + rowsField.setText(Integer.toString(initialRows)); + maybeEnableOKButton(); + SwingUtilities.invokeLater( new Runnable() { + public void run() { + colsField.requestFocus(); + } + }); + return super.showDialog(); + } + + public boolean inputOK() { + return (!colsField.getText().equals("") && !rowsField.getText().equals("") + && (getCols() > 0) && (getRows() > 0)); + } + +} \ No newline at end of file diff --git a/src/tm/modaldialog/TMCustomCodecDialog.java b/src/tm/modaldialog/TMCustomCodecDialog.java new file mode 100644 index 0000000..fe7cda8 --- /dev/null +++ b/src/tm/modaldialog/TMCustomCodecDialog.java @@ -0,0 +1,196 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.modaldialog; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; + +/** +* +* The dialog that's shown when user wants to define a new codec. +* +**/ + +public class TMCustomCodecDialog extends JDialog { + + int result; + + // labels + private JLabel bppLabel = new JLabel("Bits per pixel:"); + private JLabel rmaskLabel = new JLabel("Red bitmask:"); + private JLabel gmaskLabel = new JLabel("Green bitmask:"); + private JLabel bmaskLabel = new JLabel("Blue bitmask:"); + private JLabel amaskLabel = new JLabel("Alpha bitmask:"); + private JLabel endiannessLabel = new JLabel("Endianness:"); + + // input fields + private JFormattedTextField bppField = new JFormattedTextField(); + private JFormattedTextField rmaskField = new JFormattedTextField(); + private JFormattedTextField gmaskField = new JFormattedTextField(); + private JFormattedTextField bmaskField = new JFormattedTextField(); + private JFormattedTextField amaskField = new JFormattedTextField(); + + private JButton okButton = new JButton("OK"); + private JButton cancelButton = new JButton("Cancel"); + +/** +* +* Creates the custom codec dialog. +* +**/ + + public TMCustomCodecDialog(Frame owner, String title, boolean modal) { + super(owner, title, modal); + JPanel pane = new JPanel(); + setContentPane(pane); + pane.setLayout(new GridLayout(6, 2)); + pane.add(bppLabel); + pane.add(bppField); + pane.add(rmaskLabel); + pane.add(rmaskField); + pane.add(gmaskLabel); + pane.add(gmaskField); + pane.add(bmaskLabel); + pane.add(bmaskField); + pane.add(amaskLabel); + pane.add(amaskField); + pane.add(okButton); + pane.add(cancelButton); + + okButton.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + okClicked(); + } + } + ); + cancelButton.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + cancelClicked(); + } + } + ); + } + +/** +* +* +* +**/ + + public int getBitsPerPixel() { + return 0; + } + +/** +* +* +* +**/ + + public int getRedMask() { + return 0; + } + +/** +* +* +* +**/ + + public int getGreenMask() { + return 0; + } + +/** +* +* +* +**/ + + public int getBlueMask() { + return 0; + } + +/** +* +* +* +**/ + + public int getAlphaMask() { + return 0; + } + +/** +* +* +* +**/ + + public int getEndianness() { + return 0; + } + +/** +* +* +* +**/ + + public String getDescription() { + return ""; + } + +/** +* +* +* +**/ + + public void okClicked() { + result = JOptionPane.OK_OPTION; + setVisible(false); + } + +/** +* +* +* +**/ + + public void cancelClicked() { + setVisible(false); + } + +/** +* +* +* +**/ + + public int showDialog() { + result = JOptionPane.CANCEL_OPTION; + setVisible(true); + return result; + } + +} \ No newline at end of file diff --git a/src/tm/modaldialog/TMGoToDialog.java b/src/tm/modaldialog/TMGoToDialog.java new file mode 100644 index 0000000..d6116cf --- /dev/null +++ b/src/tm/modaldialog/TMGoToDialog.java @@ -0,0 +1,197 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.modaldialog; + +import javax.swing.*; +import javax.swing.event.*; +import javax.swing.border.EtchedBorder; +import javax.swing.border.TitledBorder; +import java.awt.*; +import java.awt.event.*; + +/** +* +* The dialog where user can enter desired file offset. +* +**/ + +public class TMGoToDialog extends TMModalDialog { + + // available modes + public static int ABSOLUTE_MODE = 1; + public static int RELATIVE_MODE = 2; + + private JTextField ofsField; + private JRadioButton hexButton; + private JRadioButton decButton; + private JRadioButton absButton; + private JRadioButton relButton; + +/** +* +* Creates the goto dialog. +* +**/ + + public TMGoToDialog(Frame owner, tm.utils.Xlator xl) { + super(owner, "Go_To_Dialog_Title", xl); + } + +/** +* +* Gets the selected mode. +* +**/ + + public int getMode() { + return (absButton.isSelected()) ? ABSOLUTE_MODE : RELATIVE_MODE; + } + +/** +* +* Gets the offset that was entered. +* +**/ + + public int getOffset() { + if (inputOK()) + return Integer.parseInt(ofsField.getText(), getRadix()); + return 0; + } + +/** +* +* +* +**/ + + protected JPanel getDialogPane() { + JPanel p = new JPanel(); + GridBagLayout gbl = new GridBagLayout(); + p.setLayout(gbl); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.anchor = GridBagConstraints.WEST; + + JPanel ofsPane = new JPanel(); + ofsPane.setBorder(new TitledBorder(new EtchedBorder(), xlate("Offset"))); + ofsField = new JTextField(); + ofsPane.add(ofsField); + + JPanel radixPane = new JPanel(); + radixPane.setBorder(new TitledBorder(new EtchedBorder(), xlate("Radix"))); + radixPane.setLayout(new BoxLayout(radixPane, BoxLayout.Y_AXIS)); + hexButton = new JRadioButton(xlate("Hex")); + decButton = new JRadioButton(xlate("Dec")); + radixPane.add(hexButton); + radixPane.add(decButton); + + JPanel modePane = new JPanel(); + modePane.setBorder(new TitledBorder(new EtchedBorder(), xlate("Mode"))); + modePane.setLayout(new BoxLayout(modePane, BoxLayout.Y_AXIS)); + absButton = new JRadioButton(xlate("Absolute")); + relButton = new JRadioButton(xlate("Relative")); + modePane.add(absButton); + modePane.add(relButton); + + buildConstraints(gbc, 0, 0, 1, 1, 50, 100); + gbl.setConstraints(ofsPane, gbc); + p.add(ofsPane); + + buildConstraints(gbc, 1, 0, 1, 1, 25, 100); + gbl.setConstraints(radixPane, gbc); + p.add(radixPane); + + buildConstraints(gbc, 2, 0, 1, 1, 25, 100); + gbl.setConstraints(modePane, gbc); + p.add(modePane); + + ButtonGroup modeButtonGroup = new ButtonGroup(); + modeButtonGroup.add(absButton); + modeButtonGroup.add(relButton); + absButton.setSelected(true); + + ButtonGroup radixButtonGroup = new ButtonGroup(); + radixButtonGroup.add(hexButton); + radixButtonGroup.add(decButton); + hexButton.setSelected(true); + + p.setPreferredSize(new Dimension(300, 100)); + + ofsField.setText(""); + ofsField.setColumns(10); + ofsField.addKeyListener(new KeyAdapter() { + public void keyTyped(KeyEvent e) { + char c = e.getKeyChar(); + if (!((Character.digit(c, getRadix()) != -1) || + (c == KeyEvent.VK_BACK_SPACE) || + (c == KeyEvent.VK_DELETE))) { + getToolkit().beep(); + e.consume(); + } + } + }); + + ofsField.getDocument().addDocumentListener(new TMDocumentListener()); + + hexButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (inputOK()) { + int ofs = Integer.parseInt(ofsField.getText(), 10); + ofsField.setText(Integer.toString(ofs, 16)); + } + } + }); + decButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (inputOK()) { + int ofs = Integer.parseInt(ofsField.getText(), 16); + ofsField.setText(Integer.toString(ofs, 10)); + } + } + }); + + return p; + } + +/** +* +* +* +**/ + + public int showDialog() { + ofsField.setText(""); + maybeEnableOKButton(); + SwingUtilities.invokeLater( new Runnable() { + public void run() { + ofsField.requestFocus(); + } + }); + return super.showDialog(); + } + + private int getRadix() { + return (hexButton.isSelected()) ? 16 : 10; + } + + public boolean inputOK() { + return !(ofsField.getText().equals("")); + } + +} \ No newline at end of file diff --git a/src/tm/modaldialog/TMImportInternalPaletteDialog.java b/src/tm/modaldialog/TMImportInternalPaletteDialog.java new file mode 100644 index 0000000..41cbe38 --- /dev/null +++ b/src/tm/modaldialog/TMImportInternalPaletteDialog.java @@ -0,0 +1,186 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.modaldialog; + +import tm.colorcodecs.ColorCodec; +import tm.utils.DecimalNumberVerifier; +import tm.utils.HexadecimalNumberVerifier; + +import javax.swing.*; +import javax.swing.border.*; +import java.awt.*; +import java.util.Vector; + +/** +* +* +* +**/ + +public class TMImportInternalPaletteDialog extends TMModalDialog { + + private JLabel offsetLabel; + private JTextField offsetField; + private JLabel sizeLabel; + private JTextField sizeField; + private JLabel formatLabel; + private JComboBox codecCombo; + private JRadioButton littleRadio; + private JRadioButton bigRadio; + private JCheckBox copyCheck; + +/** +* +* Creates the dialog. +* +**/ + + public TMImportInternalPaletteDialog(Frame owner, tm.utils.Xlator xl) { + super(owner, "Import_Internal_Palette_Dialog_Title", xl); + } + +/** +* +* +* +**/ + + protected JPanel getDialogPane() { + offsetLabel = new JLabel(xlate("Offset_Prompt")); + offsetField = new JTextField(); + sizeLabel = new JLabel(xlate("Size_Prompt")); + sizeField = new JTextField(); + formatLabel = new JLabel(xlate("Format")); + codecCombo = new JComboBox(); + copyCheck = new JCheckBox(xlate("Copy")); + + offsetField.setColumns(8); + sizeField.setColumns(4); + offsetField.getDocument().addDocumentListener(new TMDocumentListener()); + offsetField.addKeyListener(new HexadecimalNumberVerifier()); + sizeField.getDocument().addDocumentListener(new TMDocumentListener()); + sizeField.addKeyListener(new DecimalNumberVerifier()); + + JPanel endiannessPane = new JPanel(); + endiannessPane.setBorder(new TitledBorder(new EtchedBorder(), xlate("Endianness"))); + endiannessPane.setLayout(new BoxLayout(endiannessPane, BoxLayout.Y_AXIS)); + littleRadio = new JRadioButton(xlate("Little_Endian")+" "); + bigRadio = new JRadioButton(xlate("Big_Endian")+" "); + endiannessPane.add(littleRadio); + endiannessPane.add(bigRadio); + + ButtonGroup endiannessButtonGroup = new ButtonGroup(); + endiannessButtonGroup.add(littleRadio); + endiannessButtonGroup.add(bigRadio); + littleRadio.setSelected(true); + + JPanel p = new JPanel(); + GridBagLayout gbl = new GridBagLayout(); + p.setLayout(gbl); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.anchor = GridBagConstraints.WEST; + gbc.fill = GridBagConstraints.NONE; + buildConstraints(gbc, 0, 0, 1, 1, 20, 10); + gbl.setConstraints(offsetLabel, gbc); + p.add(offsetLabel); + buildConstraints(gbc, 1, 0, 1, 1, 30, 10); + gbl.setConstraints(offsetField, gbc); + p.add(offsetField); + buildConstraints(gbc, 2, 0, 1, 1, 20, 10); + gbl.setConstraints(sizeLabel, gbc); + p.add(sizeLabel); + buildConstraints(gbc, 3, 0, 1, 1, 30, 10); + gbl.setConstraints(sizeField, gbc); + p.add(sizeField); + buildConstraints(gbc, 0, 1, 1, 1, 20, 10); + gbl.setConstraints(formatLabel, gbc); + p.add(formatLabel); + buildConstraints(gbc, 1, 1, 2, 1, 55, 10); + gbl.setConstraints(codecCombo, gbc); + p.add(codecCombo); + buildConstraints(gbc, 3, 1, 1, 1, 25, 10); + gbl.setConstraints(endiannessPane, gbc); + p.add(endiannessPane); + buildConstraints(gbc, 0, 2, 1, 1, 25, 10); + gbl.setConstraints(copyCheck, gbc); + p.add(copyCheck); + + p.setPreferredSize(new Dimension(450, 150)); + + return p; + } + + public int getOffset() { + return Integer.parseInt(offsetField.getText(), 16); + } + + public int getPaletteSize() { + return Integer.parseInt(sizeField.getText()); + } + + public int getEndianness() { + return littleRadio.isSelected() ? ColorCodec.LITTLE_ENDIAN : ColorCodec.BIG_ENDIAN; + } + + public ColorCodec getCodec() { + return (ColorCodec)codecCombo.getSelectedItem(); + } + + public boolean getCopy() { + return copyCheck.isSelected(); + } + +/** +* +* +* +**/ + + public void setCodecs(Vector codecs) { + codecCombo.removeAllItems(); + for (int i=0; i 0)); + } + +} \ No newline at end of file diff --git a/src/tm/modaldialog/TMModalDialog.java b/src/tm/modaldialog/TMModalDialog.java new file mode 100644 index 0000000..287da44 --- /dev/null +++ b/src/tm/modaldialog/TMModalDialog.java @@ -0,0 +1,203 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.modaldialog; + +import tm.utils.Xlator; +import javax.swing.*; +import javax.swing.event.*; +import java.awt.*; +import java.awt.event.*; + +/** +* +* A class providing a general framework for modal dialogs. +* It has an OK and Cancel button. Must be subclassed to +* provide the getDialogPane() method, which creates and +* returns a panel with the actual dialog components where +* input can be given by the user. +* +**/ + +public abstract class TMModalDialog extends JDialog { + + private int result; + private JButton okButton; + private JButton cancelButton; + private Xlator xl; + private JPanel dialogPane; + +/** +* +* +* +**/ + + public TMModalDialog(Frame owner, String title, Xlator xl) { + super(owner, xl != null ? xl.xlate(title) : title, true); + this.xl = xl; + setResizable(false); + okButton = new JButton(xlate("OK")); + cancelButton = new JButton(xlate("Cancel")); + okButton.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + approveInput(); + } + } + ); + cancelButton.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + cancelInput(); + } + } + ); + JPanel buttonPane = new JPanel(); + GridBagLayout gbl = new GridBagLayout(); + buttonPane.setLayout(gbl); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.anchor = GridBagConstraints.EAST; + buildConstraints(gbc, 0, 0, 1, 1, 45, 100); + gbl.setConstraints(okButton, gbc); + buttonPane.add(okButton); + JLabel filler = new JLabel(); + gbc.anchor = GridBagConstraints.CENTER; + buildConstraints(gbc, 1, 0, 1, 1, 10, 100); + gbl.setConstraints(filler, gbc); + buttonPane.add(filler); + buildConstraints(gbc, 2, 0, 1, 1, 45, 100); + gbc.anchor = GridBagConstraints.WEST; + gbl.setConstraints(cancelButton, gbc); + buttonPane.add(cancelButton); + + JPanel contentPane = new JPanel() { + public Insets getInsets() { + return new Insets(10,10,10,10); + } + }; + setContentPane(contentPane); + contentPane.setLayout(new BorderLayout()); + contentPane.add(buttonPane, BorderLayout.SOUTH); + this.dialogPane = getDialogPane(); + contentPane.add(this.dialogPane, BorderLayout.CENTER); + pack(); + + } + +/** +* +* Shows the dialog. +* +**/ + + public int showDialog() { + // center the dialog + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + int insetx = (screenSize.width - getWidth()) / 2; + int insety = (screenSize.height - getHeight()) / 2; + setBounds(insetx, insety, + getWidth(), getHeight()); + + result = JOptionPane.CANCEL_OPTION; + setVisible(true); + return result; + } + +/** +* +* +* +**/ + + protected void approveInput() { + result = JOptionPane.OK_OPTION; + setVisible(false); + } + +/** +* +* +* +**/ + + protected void cancelInput() { + result = JOptionPane.CANCEL_OPTION; + setVisible(false); + } + +/** +* +* Method that provides the real content pane of the dialog. +* +**/ + + protected abstract JPanel getDialogPane(); + +/** +* +* +* +**/ + + protected static void buildConstraints(GridBagConstraints gbc, int gx, int gy, int gw, int gh, int wx, int wy) { + gbc.gridx = gx; + gbc.gridy = gy; + gbc.gridwidth = gw; + gbc.gridheight = gh; + gbc.weightx = wx; + gbc.weighty = wy; + } + +/** +* +* Sets enabled state of OK button. +* Subclasses can use this to keep the user from OK'ing the input when it +* isn't valid/completed. +* +**/ + + public void maybeEnableOKButton() { + okButton.setEnabled(inputOK()); + } + + public abstract boolean inputOK(); + + protected class TMDocumentListener implements DocumentListener { + public void changedUpdate(DocumentEvent e) { + maybeEnableOKButton(); + } + public void insertUpdate(DocumentEvent e) { + maybeEnableOKButton(); + } + public void removeUpdate(DocumentEvent e) { + maybeEnableOKButton(); + } + } + + public String xlate(String key) { + try { + String value = xl.xlate(key); + return value; + } + catch (Exception e) { + return key; + } + } + +} \ No newline at end of file diff --git a/src/tm/modaldialog/TMNewFileDialog.java b/src/tm/modaldialog/TMNewFileDialog.java new file mode 100644 index 0000000..127e207 --- /dev/null +++ b/src/tm/modaldialog/TMNewFileDialog.java @@ -0,0 +1,101 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.modaldialog; + +import tm.utils.DecimalNumberVerifier; + +import javax.swing.*; +import java.awt.*; + +/** +* +* The dialog that's shown when user wants to create a new ("blank") file. +* +**/ + +public class TMNewFileDialog extends TMModalDialog { + + private JLabel sizeLabel; + private JTextField sizeField; + +/** +* +* Creates the New File dialog. +* +**/ + + public TMNewFileDialog(Frame owner, tm.utils.Xlator xl) { + super(owner, "New_File_Dialog_Title", xl); + } + +/** +* +* Gets the filesize given by the user. +* +**/ + + public int getFileSize() { + return Integer.parseInt(sizeField.getText()); + } + +/** +* +* +* +**/ + + protected JPanel getDialogPane() { + JPanel p = new JPanel(); + GridBagLayout gbl = new GridBagLayout(); + p.setLayout(gbl); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.anchor = GridBagConstraints.WEST; + sizeLabel = new JLabel(xlate("Size_Prompt")); + buildConstraints(gbc, 0, 0, 1, 1, 50, 100); + gbl.setConstraints(sizeLabel, gbc); + p.add(sizeLabel); + sizeField = new JTextField(); + buildConstraints(gbc, 1, 0, 1, 1, 50, 100); + gbl.setConstraints(sizeField, gbc); + p.add(sizeField); + p.setPreferredSize(new Dimension(200, 50)); + + sizeField.setColumns(7); + sizeField.addKeyListener(new DecimalNumberVerifier()); + sizeField.getDocument().addDocumentListener(new TMDocumentListener()); + + return p; + } + + public int showDialog() { + sizeField.setText(""); + maybeEnableOKButton(); + SwingUtilities.invokeLater( new Runnable() { + public void run() { + sizeField.requestFocus(); + } + }); + return super.showDialog(); + } + + public boolean inputOK() { + return !(sizeField.getText().equals("") || (getFileSize() == 0)); + } + +} \ No newline at end of file diff --git a/src/tm/modaldialog/TMNewFolderDialog.java b/src/tm/modaldialog/TMNewFolderDialog.java new file mode 100644 index 0000000..ff81b18 --- /dev/null +++ b/src/tm/modaldialog/TMNewFolderDialog.java @@ -0,0 +1,106 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.modaldialog; + +import javax.swing.*; +import javax.swing.event.*; +import java.awt.*; + +/** +* +* The dialog that's shown when user wants to create a new folder. +* +**/ + +public class TMNewFolderDialog extends TMModalDialog { + + private JLabel nameLabel; + private JTextField nameField; + +/** +* +* Creates the New Folder dialog. +* +**/ + + public TMNewFolderDialog(Frame owner, tm.utils.Xlator xl) { + super(owner, "New_Folder_Dialog_Title", xl); + } + +/** +* +* Gets the folder name given by the user. +* +**/ + + public String getName() { + return nameField.getText(); + } + +/** +* +* +* +**/ + + public void setName(String name) { + nameField.setText(name); + } + +/** +* +* +* +**/ + + protected JPanel getDialogPane() { + JPanel p = new JPanel(); + nameLabel = new JLabel(xlate("Folder_Name_Prompt")); + p.add(nameLabel); + nameField = new JTextField(); + nameField.getDocument().addDocumentListener(new TMDocumentListener()); + nameField.setColumns(15); + p.add(nameField); + p.setPreferredSize(new Dimension(300, 50)); + + return p; + } + +/** +* +* +* +**/ + + public int showDialog() { + nameField.setText(""); + maybeEnableOKButton(); + SwingUtilities.invokeLater( new Runnable() { + public void run() { + nameField.requestFocus(); + } + }); + return super.showDialog(); + } + + public boolean inputOK() { + return !(nameField.getText().trim().equals("")); + } + +} \ No newline at end of file diff --git a/src/tm/modaldialog/TMNewPaletteDialog.java b/src/tm/modaldialog/TMNewPaletteDialog.java new file mode 100644 index 0000000..ef5587d --- /dev/null +++ b/src/tm/modaldialog/TMNewPaletteDialog.java @@ -0,0 +1,156 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.modaldialog; + +import tm.colorcodecs.ColorCodec; +import tm.utils.DecimalNumberVerifier; + +import javax.swing.*; +import javax.swing.border.*; +import java.awt.*; +import java.util.Vector; + +/** +* +* +**/ + +public class TMNewPaletteDialog extends TMModalDialog { + + private JLabel sizeLabel; + private JFormattedTextField sizeField; + private JLabel formatLabel; + private JComboBox codecCombo; + private JRadioButton littleRadio; + private JRadioButton bigRadio; + +/** +* +* Creates the dialog. +* +**/ + + public TMNewPaletteDialog(Frame owner, tm.utils.Xlator xl) { + super(owner, "New_Palette_Dialog_Title", xl); + } + +/** +* +* +* +**/ + + protected JPanel getDialogPane() { + sizeLabel = new JLabel(xlate("Size_Prompt")); + sizeField = new JFormattedTextField(); + formatLabel = new JLabel(xlate("Format")); + codecCombo = new JComboBox(); + + sizeField.setColumns(5); + sizeField.getDocument().addDocumentListener(new TMDocumentListener()); + sizeField.addKeyListener(new DecimalNumberVerifier()); + + JPanel endiannessPane = new JPanel(); + endiannessPane.setBorder(new TitledBorder(new EtchedBorder(), xlate("Endianness"))); + endiannessPane.setLayout(new BoxLayout(endiannessPane, BoxLayout.Y_AXIS)); + littleRadio = new JRadioButton(xlate("Little_Endian")+" "); + bigRadio = new JRadioButton(xlate("Big_Endian")+" "); + endiannessPane.add(littleRadio); + endiannessPane.add(bigRadio); + + ButtonGroup endiannessButtonGroup = new ButtonGroup(); + endiannessButtonGroup.add(littleRadio); + endiannessButtonGroup.add(bigRadio); + littleRadio.setSelected(true); + + JPanel p = new JPanel(); + GridBagLayout gbl = new GridBagLayout(); + p.setLayout(gbl); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.anchor = GridBagConstraints.WEST; + gbc.fill = GridBagConstraints.NONE; + buildConstraints(gbc, 0, 0, 1, 1, 25, 10); + gbl.setConstraints(sizeLabel, gbc); + p.add(sizeLabel); + buildConstraints(gbc, 1, 0, 1, 1, 25, 10); + gbl.setConstraints(sizeField, gbc); + p.add(sizeField); + buildConstraints(gbc, 0, 1, 1, 1, 25, 10); + gbl.setConstraints(formatLabel, gbc); + p.add(formatLabel); + buildConstraints(gbc, 1, 1, 2, 1, 50, 10); + gbl.setConstraints(codecCombo, gbc); + p.add(codecCombo); + buildConstraints(gbc, 3, 1, 1, 1, 25, 10); + gbl.setConstraints(endiannessPane, gbc); + p.add(endiannessPane); + + p.setPreferredSize(new Dimension(400, 100)); + + return p; + } + + public int getPaletteSize() { + return Integer.parseInt(sizeField.getText()); + } + + public int getEndianness() { + return littleRadio.isSelected() ? ColorCodec.LITTLE_ENDIAN : ColorCodec.BIG_ENDIAN; + } + + public ColorCodec getCodec() { + return (ColorCodec)codecCombo.getSelectedItem(); + } + +/** +* +* +* +**/ + + public void setCodecs(Vector codecs) { + codecCombo.removeAllItems(); + for (int i=0; i 0)); + } + +} \ No newline at end of file diff --git a/src/tm/modaldialog/TMOrganizeTreeDialog.java b/src/tm/modaldialog/TMOrganizeTreeDialog.java new file mode 100644 index 0000000..90fe577 --- /dev/null +++ b/src/tm/modaldialog/TMOrganizeTreeDialog.java @@ -0,0 +1,362 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.modaldialog; + +import tm.treenodes.*; +import tm.modaldialog.TMNewFolderDialog; +import tm.utils.Xlator; +import javax.swing.*; +import javax.swing.tree.*; +import javax.swing.event.*; +import java.awt.*; +import java.awt.event.*; +import java.awt.dnd.*; +import java.awt.datatransfer.*; + +/** +* +* Dialog where the user can organize treenodes. +* Items and folders can be moved, renamed and deleted. +* New folders can be created. +* Items can be sorted (?) +* +**/ + +public class TMOrganizeTreeDialog extends JDialog implements TreeModelListener { + + private TMTreeNodeTree tree = new TMTreeNodeTree(); + private JScrollPane scrollPane = new JScrollPane(tree); + private TMNewFolderDialog newFolderDialog; + + private JButton newFolderButton; + private JButton renameButton; + private JButton moveButton; + private JButton deleteButton; + private JButton closeButton; + private Xlator xl; + +/** +* +* +* +**/ + + public TMOrganizeTreeDialog(Frame owner, String title, Xlator xl) { + super(owner, xl != null ? xl.xlate(title) : title, true); + this.xl = xl; + + newFolderButton = new JButton(xlate("New_Folder")); + renameButton = new JButton(xlate("Rename")); + moveButton = new JButton(xlate("Move")); + deleteButton = new JButton(xlate("Delete")); + closeButton = new JButton(xlate("Close")); + + newFolderDialog = new TMNewFolderDialog(owner, xl); + setSize(500, 400); + + tree.setRootVisible(false); + tree.setEditable(true); + + DragSource dragSource = DragSource.getDefaultDragSource() ; + dragSource.createDefaultDragGestureRecognizer( + tree, //DragSource + DnDConstants.ACTION_MOVE, //specifies valid actions + new MyDragGestureListener() //DragGestureListener + ); + new DropTarget(tree, DnDConstants.ACTION_MOVE, new MyDropTargetListener(), true); + + JPanel contentPane = new JPanel() { + public Insets getInsets() { + return new Insets(10,10,10,10); + } + }; + setContentPane(contentPane); + contentPane.setLayout(new BorderLayout()); + + // create panel with command buttons + JPanel topPane = new JPanel(); + topPane.setLayout(new GridLayout(1, 4)); + topPane.add(renameButton); + topPane.add(moveButton); + topPane.add(newFolderButton); + topPane.add(deleteButton); + + // create panel with Close button + JPanel bottomPane = new JPanel(); + bottomPane.setLayout(new FlowLayout(FlowLayout.RIGHT)); + bottomPane.add(closeButton); + + contentPane.add(topPane, BorderLayout.NORTH); + contentPane.add(scrollPane, BorderLayout.CENTER); + contentPane.add(bottomPane, BorderLayout.SOUTH); + + // make button action handlers + newFolderButton.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + doNewFolderCommand(); + } + } + ); + renameButton.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + doRenameCommand(); + } + } + ); + moveButton.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + doMoveCommand(); + } + } + ); + deleteButton.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + doDeleteCommand(); + } + } + ); + closeButton.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + doCloseCommand(); + } + } + ); + + tree.addKeyListener( + new KeyAdapter() { + public void keyTyped(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_DELETE) { + doDeleteCommand(); + } + } + } + ); + } + +/** +* +* +* +**/ + + public void doNewFolderCommand() { + newFolderDialog.setName(""); // clear previous input, if any + int retVal = newFolderDialog.showDialog(); // prompt user for folder name + if (retVal == JOptionPane.OK_OPTION) { + // create & insert the folder + String name = newFolderDialog.getName(); + TMTreeNode node = tree.getSelectedNode(); + FolderNode folder; + if (node instanceof FolderNode) { + folder = (FolderNode)node; + } + else { + folder = (FolderNode)node.getParent(); + } + FolderNode newFolder = new FolderNode(name); + folder.add(newFolder); + ((DefaultTreeModel)tree.getModel()).reload(folder); + tree.expandNode(newFolder); + tree.setSelectionPath(new TreePath(newFolder.getPath())); + scrollPane.revalidate(); + } + } + +/** +* +* +* +**/ + + public void doRenameCommand() { + DefaultMutableTreeNode node = tree.getSelectedNode(); + if (node.isRoot()) return; + tree.startEditingAtPath(tree.getSelectionPath()); + } + +/** +* +* +* +**/ + + public void doMoveCommand() { + JOptionPane.showMessageDialog( + this, + "Todo.\nUse drag and drop to move items.", + "Tile Molester", + JOptionPane.INFORMATION_MESSAGE + ); + } + +/** +* +* +* +**/ + + public void doDeleteCommand() { + TMTreeNode node = tree.getSelectedNode(); + if (node.isRoot()) return; + int retVal = JOptionPane.showConfirmDialog(this, + "You sure about this?", // i18n + "Tile Molester", + JOptionPane.YES_NO_OPTION, + JOptionPane.WARNING_MESSAGE); + if (retVal == JOptionPane.OK_OPTION) { + TMTreeNode parent = node.getTMParent(); + parent.remove(node); + + ((DefaultTreeModel)tree.getModel()).reload(parent); + tree.expandNode(parent); + tree.setSelectionPath(new TreePath(parent.getPath())); + scrollPane.revalidate(); + } + } + +/** +* +* +* +**/ + + public void doCloseCommand() { + setVisible(false); + } + +/** +* +* Shows the dialog. +* +**/ + + public void showDialog(FolderNode root) { + tree.loadTreeNodes(root, true); + tree.getModel().addTreeModelListener(this); + // center the dialog + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + int insetx = (screenSize.width - getWidth()) / 2; + int insety = (screenSize.height - getHeight()) / 2; + setBounds(insetx, insety, + getWidth(), getHeight()); + + setVisible(true); + } + + public void treeNodesChanged(TreeModelEvent e) { + TMTreeNode node; + node = (TMTreeNode)e.getTreePath().getLastPathComponent(); + try { + int index = e.getChildIndices()[0]; + node = (TMTreeNode)node.getChildAt(index); + } catch (NullPointerException exc) {} + node.setText((String)node.getUserObject()); + } + + public void treeNodesInserted(TreeModelEvent e) { + } + + public void treeNodesRemoved(TreeModelEvent e) { + } + + public void treeStructureChanged(TreeModelEvent e) { + } + +/** +* +* +* +**/ + + public String xlate(String key) { + try { + String value = xl.xlate(key); + return value; + } + catch (Exception e) { + return key; + } + } + +/** +* +* +* +**/ + + private class MyDragGestureListener implements DragGestureListener { + + public void dragGestureRecognized(DragGestureEvent dge) { + TMTreeNode dragNode = tree.getSelectedNode(); + if ((dragNode != null) && !dragNode.isRoot()) { + dge.startDrag(DragSource.DefaultMoveDrop, new TMTreeNodeTransferable(dragNode)); + } + } + + } + +/** +* +* +* +**/ + + private class MyDropTargetListener extends DropTargetAdapter { + + public void drop(DropTargetDropEvent dtde) { + Transferable transferable = dtde.getTransferable(); + //flavor not supported, reject drop + if (!transferable.isDataFlavorSupported(TMTreeNodeTransferable.localTMTreeNodeFlavor)) { + dtde.rejectDrop(); + return; + } + TMTreeNode node = null; + try { + node = (TMTreeNode)transferable.getTransferData(TMTreeNodeTransferable.localTMTreeNodeFlavor); + } catch (Exception e) { } + TMTreeNode oldParent = node.getTMParent(); + Point loc = dtde.getLocation(); + TMTreeNode newParent; + try { + TreePath destinationPath = tree.getPathForLocation(loc.x, loc.y); + newParent = (TMTreeNode)destinationPath.getLastPathComponent(); + } + catch (Exception e) { + newParent = (TMTreeNode)((DefaultTreeModel)tree.getModel()).getRoot(); + } + if (!(newParent instanceof FolderNode)) { + newParent = newParent.getTMParent(); + } + oldParent.remove(node); + newParent.add(node); + ((DefaultTreeModel)tree.getModel()).reload(); + tree.expandNode(oldParent); + tree.expandNode(newParent); + tree.setSelectionPath(new TreePath(newParent.getPath())); + scrollPane.revalidate(); + } + + } + +} \ No newline at end of file diff --git a/src/tm/modaldialog/TMPaletteSizeDialog.java b/src/tm/modaldialog/TMPaletteSizeDialog.java new file mode 100644 index 0000000..71795cf --- /dev/null +++ b/src/tm/modaldialog/TMPaletteSizeDialog.java @@ -0,0 +1,101 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.modaldialog; + +import tm.utils.DecimalNumberVerifier; + +import javax.swing.*; +import java.awt.*; + +/** +* +* The dialog that's shown when user wants to change the size of current palette. +* +**/ + +public class TMPaletteSizeDialog extends TMModalDialog { + + private JLabel sizeLabel; + private JTextField sizeField; + +/** +* +* Creates the Palette Size dialog. +* +**/ + + public TMPaletteSizeDialog(Frame owner, tm.utils.Xlator xl) { + super(owner, "Palette_Size_Dialog_Title", xl); + } + +/** +* +* Gets the palette size given by the user. +* +**/ + + public int getPaletteSize() { + return Integer.parseInt(sizeField.getText()); + } + +/** +* +* +* +**/ + + protected JPanel getDialogPane() { + JPanel p = new JPanel(); + GridBagLayout gbl = new GridBagLayout(); + p.setLayout(gbl); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.anchor = GridBagConstraints.WEST; + sizeLabel = new JLabel(xlate("Size_Prompt")); + buildConstraints(gbc, 0, 0, 1, 1, 50, 100); + gbl.setConstraints(sizeLabel, gbc); + p.add(sizeLabel); + sizeField = new JTextField(); + buildConstraints(gbc, 1, 0, 1, 1, 50, 100); + gbl.setConstraints(sizeField, gbc); + p.add(sizeField); + p.setPreferredSize(new Dimension(200, 50)); + + sizeField.setColumns(4); + sizeField.addKeyListener(new DecimalNumberVerifier()); + sizeField.getDocument().addDocumentListener(new TMDocumentListener()); + + return p; + } + + public int showDialog(int initialSize) { + sizeField.setText(Integer.toString(initialSize)); + maybeEnableOKButton(); + SwingUtilities.invokeLater( new Runnable() { + public void run() { + sizeField.requestFocus(); + } + }); + return super.showDialog(); + } + + public boolean inputOK() { + return !(sizeField.getText().equals("") || (getPaletteSize() == 0)); + } + +} \ No newline at end of file diff --git a/src/tm/modaldialog/TMStretchDialog.java b/src/tm/modaldialog/TMStretchDialog.java new file mode 100644 index 0000000..7b877dc --- /dev/null +++ b/src/tm/modaldialog/TMStretchDialog.java @@ -0,0 +1,135 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.modaldialog; + +import tm.utils.DecimalNumberVerifier; + +import javax.swing.*; +import java.awt.*; + +/** +* +* The dialog where user can enter new dimensions for the current selection. +* +**/ + +public class TMStretchDialog extends TMModalDialog { + + private JLabel colsLabel; + private JLabel rowsLabel; + private JTextField colsField; + private JTextField rowsField; + +/** +* +* Creates the stretch dialog. +* +**/ + + public TMStretchDialog(Frame owner, tm.utils.Xlator xl) { + super(owner, "Stretch_Image_Dialog_Title", xl); + } + +/** +* +* +* +**/ + + public int getCols() { + return Integer.parseInt(colsField.getText()); + } + +/** +* +* +* +**/ + + public int getRows() { + return Integer.parseInt(rowsField.getText()); + } + +/** +* +* +* +**/ + + protected JPanel getDialogPane() { + colsLabel = new JLabel(xlate("Columns_Prompt")); + rowsLabel = new JLabel(xlate("Rows_Prompt")); + colsField = new JTextField(); + rowsField = new JTextField(); + + JPanel colsPane = new JPanel(); + colsPane.setLayout(new BoxLayout(colsPane, BoxLayout.X_AXIS)); + colsPane.add(colsLabel); + colsPane.add(colsField); + + JPanel rowsPane = new JPanel(); + rowsPane.setLayout(new BoxLayout(rowsPane, BoxLayout.X_AXIS)); + rowsPane.add(rowsLabel); + rowsPane.add(rowsField); + + JPanel p = new JPanel(); + GridBagLayout gbl = new GridBagLayout(); + p.setLayout(gbl); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.anchor = GridBagConstraints.WEST; + + buildConstraints(gbc, 0, 0, 1, 1, 100, 50); + gbl.setConstraints(colsPane, gbc); + p.add(colsPane); + + buildConstraints(gbc, 0, 1, 1, 1, 100, 50); + gbl.setConstraints(rowsPane, gbc); + p.add(rowsPane); + + p.setPreferredSize(new Dimension(200, 60)); + + colsField.setColumns(3); + rowsField.setColumns(3); + + colsField.addKeyListener(new DecimalNumberVerifier()); + colsField.getDocument().addDocumentListener(new TMDocumentListener()); + rowsField.addKeyListener(new DecimalNumberVerifier()); + rowsField.getDocument().addDocumentListener(new TMDocumentListener()); + + return p; + } + + public int showDialog(int initialCols, int initialRows) { + colsField.setText(Integer.toString(initialCols)); + rowsField.setText(Integer.toString(initialRows)); + maybeEnableOKButton(); + SwingUtilities.invokeLater( new Runnable() { + public void run() { + colsField.requestFocus(); + } + }); + return super.showDialog(); + } + + public boolean inputOK() { + return (!colsField.getText().equals("") && !rowsField.getText().equals("") + && (getCols() > 0) && (getRows() > 0)); + } + +} \ No newline at end of file diff --git a/src/tm/osbaldeston/image/BMP.java b/src/tm/osbaldeston/image/BMP.java new file mode 100644 index 0000000..6e7d925 --- /dev/null +++ b/src/tm/osbaldeston/image/BMP.java @@ -0,0 +1,500 @@ +package tm.osbaldeston.image; + +/** + * BMP - Wrapper Class for the loading & saving of uncompressed BMP files. + * + * Known problems/issues: + * Only 24 bit BMP files are output, images get converted to 24-bit + * which corresponds to Java's default colour model, output from + * PixelGrabber in Java 1.1.x. + * + * @see PCBinaryInputStream, PCBinaryOutputStream + * + * @author Richard J.Osbaldeston + * @version 1.1 02/08/98 + * @copyright Richard J.Osbaldeston (http://www.osbald.co.uk) + */ + +import java.awt.Image; +import java.awt.image.*; +import java.awt.Toolkit; +import java.io.*; +import java.net.URL; +import tm.osbaldeston.io.*; + +public class BMP { + + private java.awt.Image image; + private BmpFileheader bmp_fileheader = new BmpFileheader(); + private BmpInfoHeader bmp_infoheader = new BmpInfoHeader(); + private BmpPalette bmp_palette; + private int width; + private int height; + + /** + * Creates an BMP by reading from the given File. + * + * @param f File to read BMP from + */ + public BMP(File f) { + try { + PCBinaryInputStream file = new PCBinaryInputStream(f); + read(file); + } catch (IOException e) { + System.err.println(e); + } + } + + /** + * Creates an BMP by reading from the given File. + * + * @param url URL to read BMP from + */ + public BMP(URL url) { + try { + PCBinaryInputStream file = new PCBinaryInputStream(url); + read(file); + } catch (IOException e) { + System.err.println(e); + } + } + + /** + * Creates an BMP from the given Image, (for writing). + */ + public BMP(Image image) { + this.image=image; + width=image.getWidth(null); + height=image.getHeight(null); + bmp_infoheader.biWidth = (short)width; + bmp_infoheader.biHeight = (short)height; + bmp_infoheader.biBitCount = 24; + bmp_infoheader.biClrUsed = 0; + } + + /** + * Returns the image loaded, last saved image or null if unused. + * + * @return the current image + */ + public Image getImage() { + return image; + } + + /** + * Saves the BMP in a given file. + * + * @param f File to write BMP + */ + public void write(File f) { + try { + PCBinaryOutputStream file = new PCBinaryOutputStream(f); + write(file); + } catch (IOException e) { + System.err.println(e); + } + } + + /** + * Saves the BMP in a given file. + * + * @param url URL to write BMP + */ + public void write(URL url) { + try { + PCBinaryOutputStream file = new PCBinaryOutputStream(url); + write(file); + } catch (IOException e) { + System.err.println(e); + } + } + + /** + * Saves the BMP in a given file. + */ + void write(PCBinaryOutputStream file) { + try { + int rawData[] = new int[width*height]; + PixelGrabber grabber = new PixelGrabber(image, 0, 0, width, height, rawData, 0, width); + bmp_palette = new BmpPalette(grabber.getColorModel()); + + try { + grabber.grabPixels(); + } catch (InterruptedException e) { System.err.println(e); } + + ColorModel model = grabber.getColorModel(); + + bmp_fileheader.bfOffBits = bmp_fileheader.getSize() + + bmp_infoheader.getSize() + + bmp_palette.getSize(); + int x=0,y=0,i=0,j=0,k=0; + byte bitmap[]; + int w=width*3; + int h=height-1; + + // dword align width + if (w%4 != 0) + w += (4-(w%4)); + + if (model instanceof IndexColorModel) { + // not tested - (can't get IndexColorModel from PixelGrabber??!) + bitmap = new byte[width*bmp_infoheader.biHeight]; + for (y=h;y>=0;y--) { + i=(h-y)*width; + j=y*width; + for (x=0;x 0) { + file.skip(skip); + } + + scanlineSize = ((bmp_infoheader.biWidth*bmp_infoheader.biBitCount+31)/32)*4; + + if (bmp_infoheader.biSizeImage != 0) + bitplaneSize = bmp_infoheader.biSizeImage; + else + bitplaneSize = scanlineSize * bmp_infoheader.biHeight; + + rawData = new byte[bitplaneSize]; + file.readByteArray(rawData); + file.close(); + + } catch (IOException e) { + System.err.println(e); + } + + if (rawData != null) { + if (bmp_infoheader.biBitCount > 8) { + image = unpack24(rawData, scanlineSize); + } + else { + image = unpack08(rawData, scanlineSize); + } + } + rawData = null; + } + + Image unpack24(byte [] rawData, int scanlineSize) { + int b=0, k=0, x=0, y=0; + int [] data = new int[bmp_infoheader.biWidth * bmp_infoheader.biHeight]; + try { + for (y=0; y < bmp_infoheader.biHeight; y++) { + b=(bmp_infoheader.biHeight-1-y)*bmp_infoheader.biWidth; + k=y*scanlineSize; + for (x=0; x < bmp_infoheader.biWidth; x++) { + data[x+b] = 0xFF000000 | + (((int)(rawData[k++])) & 0xFF) | + (((int)(rawData[k++])) & 0xFF) << 8 | + (((int)(rawData[k++])) & 0xFF) << 16; + } + } + }catch (Exception e) {}; + return Toolkit.getDefaultToolkit().createImage(new MemoryImageSource(bmp_infoheader.biWidth, bmp_infoheader.biHeight, ColorModel.getRGBdefault(), data, 0, bmp_infoheader.biWidth)); + } + + Image unpack08(byte [] rawData, int scanlineSize) { + int b=0, k=0, i=0, x=0, y=0; + byte [] data = new byte[bmp_infoheader.biWidth * bmp_infoheader.biHeight]; + try { + if (bmp_infoheader.biBitCount == 1) { + for (y=0; y < bmp_infoheader.biHeight; y++) { + b=(bmp_infoheader.biHeight-1-y)*bmp_infoheader.biWidth; + k=y*scanlineSize; + for (x=0; x < (bmp_infoheader.biWidth-8); x+=8) { + data[b+x+7] = (byte)((rawData[k]) & 1); + data[b+x+6] = (byte)((rawData[k] >>> 1) & 1); + data[b+x+5] = (byte)((rawData[k] >>> 2) & 1); + data[b+x+4] = (byte)((rawData[k] >>> 3) & 1); + data[b+x+3] = (byte)((rawData[k] >>> 4) & 1); + data[b+x+2] = (byte)((rawData[k] >>> 5) & 1); + data[b+x+1] = (byte)((rawData[k] >>> 6) & 1); + data[b+x] = (byte)((rawData[k] >>> 7) & 1); + k++; + } + for (i=7; i>=0 ; i--) { + if ((i+x)< bmp_infoheader.biWidth) { + data[b+x+i] = (byte)((rawData[k] >>> (7-i)) & 1); + } + } + } + } else if (bmp_infoheader.biBitCount == 4) { + for (y=0; y < bmp_infoheader.biHeight; y++) { + b=(bmp_infoheader.biHeight-1-y)*bmp_infoheader.biWidth; + k=y*scanlineSize; + for (x=0; x < (bmp_infoheader.biWidth-2); x+=2) { + data[b+x] = (byte)((rawData[k]>>4) & 0x0F); + data[b+x+1] = (byte)((rawData[k] & 0x0F)); + k+=1; + } + for (i=1; i>=0 ; i--) { + if ((i+x)< bmp_infoheader.biWidth) { + data[b+x+i] = (byte)((rawData[k] >>> ((1-i)<<2)) & 0x0F); + } + } + } + } else { + for (y=0; y < bmp_infoheader.biHeight; y++) { + b=(bmp_infoheader.biHeight-1-y)*bmp_infoheader.biWidth; + k=y*scanlineSize; + for (x=0; x < bmp_infoheader.biWidth; x++) { + data[x+b] = (byte)(rawData[k++] & 0xFF); + } + } + } + }catch (Exception e) {}; + + ColorModel colourModel = new IndexColorModel(bmp_infoheader.biBitCount, bmp_palette.length, bmp_palette.r, bmp_palette.g, bmp_palette.b); + return Toolkit.getDefaultToolkit().createImage(new MemoryImageSource(bmp_infoheader.biWidth, bmp_infoheader.biHeight, colourModel, data, 0, bmp_infoheader.biWidth)); + } + + /** + * .BMP InfoHeader + */ + + class BmpInfoHeader { + int biSize = 40; /* InfoHeader Offset*/ + int biWidth; /* Width */ + int biHeight; /* Height */ + short biPlanes = 1; /* BitPlanes on Target Device */ + short biBitCount; /* Bits per Pixel */ + int biCompression; /* Bitmap Compression */ + int biSizeImage; /* Bitmap Image Size */ + int biXPelsPerMeter; /* Horiz Pixels Per Meter */ + int biYPelsPerMeter; /* Vert Pixels Per Meter */ + int biClrUsed; /* Number of ColorMap Entries */ + int biClrImportant; /* Number of important colours */ + + int getSize() { + return biSize; + } + + void read(PCBinaryInputStream file) { + try { + biSize = file.readInt(); + if (biSize == 12) { + biWidth = file.readShort(); + biHeight = file.readShort(); + biPlanes = file.readShort(); + biBitCount = file.readShort(); + } + else + { + biWidth = file.readInt(); + biHeight = file.readInt(); + biPlanes = file.readShort(); + biBitCount = file.readShort(); + biCompression = file.readInt(); + biSizeImage = file.readInt(); + biXPelsPerMeter = file.readInt(); + biYPelsPerMeter = file.readInt(); + biClrUsed = file.readInt(); + biClrImportant = file.readInt(); + } + } catch (IOException e) { System.err.println(e); } + + if (biSizeImage == 0) + biSizeImage = (((biWidth*biBitCount+31)>>5)<<2)*biHeight; + + if (biClrUsed == 0 && biBitCount < 16) + biClrUsed = 1 << biBitCount; + } + + void write(PCBinaryOutputStream file) { + try { + file.writeInt(biSize); + if (biSize == 12) { + file.writeShort((short)biWidth); + file.writeShort((short)biHeight); + file.writeShort(biPlanes); + file.writeShort(biBitCount); + } + else { + file.writeInt(biWidth); + file.writeInt(biHeight); + file.writeShort(biPlanes); + file.writeShort(biBitCount); + file.writeInt(biCompression); + file.writeInt(biSizeImage); + file.writeInt(biXPelsPerMeter); + file.writeInt(biYPelsPerMeter); + file.writeInt(biClrUsed); + file.writeInt(biClrImportant); + } + } catch (IOException e) { + System.err.println(e); + } + } + } + + /** + * .BMP FileHeader + */ + + class BmpFileheader { + byte bfType[] = {'B','M'}; /* Type */ + int bfSize; /* File Size */ + short bfReserved1=0; /* Reserved 1 */ + short bfReserved2=0; /* Reserved 2 */ + int bfOffBits; /* Offset to Data */ + + int getSize() { + return 14; + } + + void read(PCBinaryInputStream file) { + try { + bfType[0] = file.readByte(); + bfType[1] = file.readByte(); + if (bfType[0] != 'B' && bfType[1] != 'M') + throw new IOException("Invalid BMP 3.0 File."); + bfSize = file.readInt(); + bfReserved1 = file.readShort(); + bfReserved2 = file.readShort(); + bfOffBits = file.readInt(); + } catch (IOException e) { + System.err.println(e); + } + } + + void write(PCBinaryOutputStream file) { + try { + file.writeByte(bfType[0]); + file.writeByte(bfType[1]); + file.writeInt(bfSize); + file.writeShort(bfReserved1); + file.writeShort(bfReserved2); + file.writeInt(bfOffBits); + } catch (IOException e) { + System.err.println(e); + } + } + } + + /** + * .BMP Palette + */ + + class BmpPalette { + int length; + byte r[]; + byte g[]; + byte b[]; + + public BmpPalette(int length) + { + this.length = length; + r = new byte[length]; + g = new byte[length]; + b = new byte[length]; + } + + int getSize() { + return length*4; + } + + public BmpPalette(ColorModel colourModel) { + if (colourModel instanceof IndexColorModel) { + IndexColorModel indexColourModel = (IndexColorModel)colourModel; + this.length = indexColourModel.getMapSize(); + r = new byte[length]; + indexColourModel.getReds(r); + g = new byte[length]; + indexColourModel.getGreens(g); + b = new byte[length]; + indexColourModel.getBlues(b); + bmp_infoheader.biBitCount = (short)indexColourModel.getPixelSize(); + bmp_infoheader.biClrUsed = length; + } + } + + void read(PCBinaryInputStream file) { + if (length > 0) { + try { + byte reserved; + for (int i=0; i < length; i++) { + b[i] = file.readByte(); // blue + g[i] = file.readByte(); // green + r[i] = file.readByte(); // red + reserved = file.readByte(); // reserved + } + } catch (IOException e) { + System.err.println(e); + } + } + } + + void write(PCBinaryOutputStream file) { + if (length > 0) { + try { + byte reserved = 0; + for (int i=0; i < length; i++) { + file.writeByte(b[i]); + file.writeByte(g[i]); + file.writeByte(r[i]); + file.writeByte(reserved); + } + } catch (IOException e) { + System.err.println(e); + } + } + } + } + +} \ No newline at end of file diff --git a/src/tm/osbaldeston/io/PCBinaryInputStream.java b/src/tm/osbaldeston/io/PCBinaryInputStream.java new file mode 100644 index 0000000..ca1193f --- /dev/null +++ b/src/tm/osbaldeston/io/PCBinaryInputStream.java @@ -0,0 +1,69 @@ +package tm.osbaldeston.io; + +/** + * PCBinaryInputStream + * + * @author Richard J.Osbaldeston + * @version 1.1 02/08/98 + * @copyright Richard J.Osbaldeston (http://www.osbald.co.uk) + */ + +import java.io.*; +import java.net.URL; + +public class PCBinaryInputStream { + + DataInputStream file; + + public PCBinaryInputStream(File f) throws IOException + { + file = new DataInputStream(new BufferedInputStream(new FileInputStream(f))); + } + + public PCBinaryInputStream(URL url) throws IOException + { + file = new DataInputStream(new BufferedInputStream((url.openConnection()).getInputStream())); + } + + public int readInt() throws IOException + { + int i=file.readInt(); + return ((i<<24)|((i&0x0000FF00)<<8)|((i&0x00FF0000)>>>8)|(i>>>24)); + } + + public short readShort() throws IOException + { + int i=file.readUnsignedShort(); + return (short)((i<<8)|(i>>>8)); + } + + public byte readByte() throws IOException + { + return (byte)file.readUnsignedByte(); + } + + public void readByteArray(byte b[]) throws IOException + { + file.readFully(b); + } + + public void skip(long nbytes) throws IOException + { + file.skip(nbytes); + } + + public void close() throws IOException + { + file.close(); + file=null; + } + + public void finalize() { + if (file != null) { + try { + close(); + } catch (IOException e) {} + } + } +} + diff --git a/src/tm/osbaldeston/io/PCBinaryOutputStream.java b/src/tm/osbaldeston/io/PCBinaryOutputStream.java new file mode 100644 index 0000000..a2d0b81 --- /dev/null +++ b/src/tm/osbaldeston/io/PCBinaryOutputStream.java @@ -0,0 +1,75 @@ +package tm.osbaldeston.io; + +/** + * PCBinaryOutputStream + * + * @author Richard J.Osbaldeston + * @version 1.1 02/08/98 + * @copyright Richard J.Osbaldeston (http://www.osbald.co.uk) + */ + +import java.io.*; +import java.net.URL; + +public class PCBinaryOutputStream { + + DataOutputStream file; + + public PCBinaryOutputStream(File f) throws IOException + { + file = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(f))); + } + + public PCBinaryOutputStream(URL url) throws IOException + { + file = new DataOutputStream(new BufferedOutputStream((url.openConnection()).getOutputStream())); + } + + public void writeInt(int i) throws IOException + { + int j=(i<<24)|((i&0x0000FF00)<<8)|((i&0x00FF0000)>>>8)|(i>>>24); + file.writeInt(j); + } + + public void writeShort(short i) throws IOException + { + int j=(i<<8)|(i>>>8); + file.writeShort((short)j); + } + + public void writeByte(byte i) throws IOException + { + file.writeByte(i); + } + + public void writeByteArray(byte b[]) throws IOException + { + file.write(b); + } + + public long getFilePointer() throws IOException + { + return file.size(); + } + + public long size() throws IOException + { + return file.size(); + } + + public void close() throws IOException + { + file.flush(); + file.close(); + file=null; + } + + public void finalize() { + if (file != null) { + try { + close(); + } catch (IOException e) {} + } + } +} + diff --git a/src/tm/reversibleaction/ReversibleAction.java b/src/tm/reversibleaction/ReversibleAction.java new file mode 100644 index 0000000..7871ee2 --- /dev/null +++ b/src/tm/reversibleaction/ReversibleAction.java @@ -0,0 +1,80 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.reversibleaction; + +import java.util.Date; + +/** +* +* Abstract class for handling reversible actions (undoable/redoable). +* Every type of action needs to subclass this class and implement the +* below methods. +* +**/ + +public abstract class ReversibleAction { + + private String presentationName; + private Date timeStamp; + +/** +* +* Creates a reversible action with the given presentation name. +* +**/ + + public ReversibleAction(String presentationName) { + this.presentationName = presentationName; + timeStamp = new Date(); + } + +/** +* +* Subclasses must implement these. +* +**/ + + public abstract void undo(); + public abstract void redo(); + public abstract boolean canUndo(); + public abstract boolean canRedo(); + +/** +* +* Gets the presentation name. +* The presentation name is the text that is displayed after "Undo"/"Redo" +* when this action can be undone/redone. +* +**/ + + public String getPresentationName() { + return presentationName; + } + +/** +* +* Gets the timestamp for this action, i.e. when it was first executed. +* +**/ + + public Date getTimeStamp() { + return timeStamp; + } + +} \ No newline at end of file diff --git a/src/tm/reversibleaction/ReversibleActionsSelectionAction.java b/src/tm/reversibleaction/ReversibleActionsSelectionAction.java new file mode 100644 index 0000000..8454668 --- /dev/null +++ b/src/tm/reversibleaction/ReversibleActionsSelectionAction.java @@ -0,0 +1,137 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.reversibleaction; + +import tm.treenodes.BookmarkItemNode; +import tm.canvases.TMTileCanvas; +import tm.canvases.TMEditorCanvas; + + +/** +* +* Allows undo/redo of an action that modifies the entire image/selection, +* such as flip and rotate. +* +**/ + +public class ReversibleActionsSelectionAction extends ReversibleAction { + + public static final int FLIP_ACTION = 1; + public static final int MIRROR_ACTION = 2; + public static final int ROTATELEFT_ACTION = 3; + public static final int ROTATERIGHT_ACTION = 4; + public static final int SHIFTLEFT_ACTION = 5; + public static final int SHIFTRIGHT_ACTION = 6; + public static final int SHIFTUP_ACTION = 7; + public static final int SHIFTDOWN_ACTION = 8; + + private TMTileCanvas canvas; + private int action; + private BookmarkItemNode bookmark; + + public ReversibleActionsSelectionAction(String presentationName, TMTileCanvas canvas, int action) { + super(presentationName); + this.canvas = canvas; + this.action = action; + if (canvas instanceof TMEditorCanvas) { + bookmark = ((TMEditorCanvas)canvas).getView().createBookmark(""); + } + } + + // undo by performing the "inverse" action. + public void undo() { + if (canvas instanceof TMEditorCanvas) { + ((TMEditorCanvas)canvas).getView().gotoBookmark(bookmark); + } + if (action == FLIP_ACTION) { + canvas.flip(); + } + else if (action == MIRROR_ACTION) { + canvas.mirror(); + } + else if (action == ROTATELEFT_ACTION) { + canvas.rotateRight(); + if (canvas instanceof TMEditorCanvas) { + bookmark = ((TMEditorCanvas)canvas).getView().createBookmark(""); + } + } + else if (action == ROTATERIGHT_ACTION) { + canvas.rotateLeft(); + if (canvas instanceof TMEditorCanvas) { + bookmark = ((TMEditorCanvas)canvas).getView().createBookmark(""); + } + } + else if (action == SHIFTLEFT_ACTION) { + canvas.shiftRight(); + } + else if (action == SHIFTRIGHT_ACTION) { + canvas.shiftLeft(); + } + else if (action == SHIFTUP_ACTION) { + canvas.shiftDown(); + } + else if (action == SHIFTDOWN_ACTION) { + canvas.shiftUp(); + } + canvas.redraw(); + } + + // redo by simply performing the original action again. + public void redo() { + if (canvas instanceof TMEditorCanvas) { + ((TMEditorCanvas)canvas).getView().gotoBookmark(bookmark); + } + if (action == FLIP_ACTION) { + canvas.flip(); + } + else if (action == MIRROR_ACTION) { + canvas.mirror(); + } + else if (action == ROTATELEFT_ACTION) { + canvas.rotateLeft(); + if (canvas instanceof TMEditorCanvas) { + bookmark = ((TMEditorCanvas)canvas).getView().createBookmark(""); + } + } + else if (action == ROTATERIGHT_ACTION) { + canvas.rotateRight(); + if (canvas instanceof TMEditorCanvas) { + bookmark = ((TMEditorCanvas)canvas).getView().createBookmark(""); + } + } + else if (action == SHIFTLEFT_ACTION) { + canvas.shiftLeft(); + } + else if (action == SHIFTRIGHT_ACTION) { + canvas.shiftRight(); + } + else if (action == SHIFTUP_ACTION) { + canvas.shiftUp(); + } + else if (action == SHIFTDOWN_ACTION) { + canvas.shiftDown(); + } + canvas.redraw(); + } + + public boolean canUndo() { return true; } + + public boolean canRedo() { return true; } + +} \ No newline at end of file diff --git a/src/tm/reversibleaction/ReversibleAddBookmarkAction.java b/src/tm/reversibleaction/ReversibleAddBookmarkAction.java new file mode 100644 index 0000000..379f54f --- /dev/null +++ b/src/tm/reversibleaction/ReversibleAddBookmarkAction.java @@ -0,0 +1,53 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.reversibleaction; + +import tm.treenodes.*; + +/** +* +* Allows undo/redo of a bookmark addition. +* +**/ + +public class ReversibleAddBookmarkAction extends ReversibleAction { + + private BookmarkItemNode bookmark; + private FolderNode folder; + + public ReversibleAddBookmarkAction(BookmarkItemNode bookmark) { + super("Add Bookmark"); // i18n + this.bookmark = bookmark; + this.folder = (FolderNode)bookmark.getParent(); + } + + public void undo() { + folder.remove(bookmark); + // ui.buildBookmarksMenu(); + } + + public void redo() { + folder.add(bookmark); + // ui.buildBookmarksMenu(); + } + + public boolean canUndo() { return true; } + public boolean canRedo() { return true; } + +} \ No newline at end of file diff --git a/src/tm/reversibleaction/ReversibleApplySelectionAction.java b/src/tm/reversibleaction/ReversibleApplySelectionAction.java new file mode 100644 index 0000000..ee28024 --- /dev/null +++ b/src/tm/reversibleaction/ReversibleApplySelectionAction.java @@ -0,0 +1,47 @@ +package tm.reversibleaction; + +import tm.canvases.TMEditorCanvas; +import tm.canvases.TMSelectionCanvas; + +/** + * + * Allows the deletion of a selection + * + **/ + +public class ReversibleApplySelectionAction extends ReversibleAction { + private TMSelectionCanvas selection; + private TMEditorCanvas owner; + private ReversibleTileModifyAction modifiedTiles; + + public ReversibleApplySelectionAction(TMSelectionCanvas selection, TMEditorCanvas owner) + { + super("Apply_Selection"); + this.selection = selection; + this.owner = owner; + this.modifiedTiles = owner.encodeSelection(false); + } + + public void undo() + { + int x = selection.getX() / selection.getScaledTileDim(); + int y = selection.getY() / selection.getScaledTileDim(); + modifiedTiles.undo(); + owner.showSelection(selection, x, y); + } + + public void redo() + { + owner.encodeSelection(false); + } + + public boolean canUndo() + { + return true; + } + + public boolean canRedo() + { + return true; + } +} diff --git a/src/tm/reversibleaction/ReversibleClearAction.java b/src/tm/reversibleaction/ReversibleClearAction.java new file mode 100644 index 0000000..6bc8d9f --- /dev/null +++ b/src/tm/reversibleaction/ReversibleClearAction.java @@ -0,0 +1,56 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.reversibleaction; + +import tm.canvases.TMSelectionCanvas; +import tm.canvases.TMEditorCanvas; + +/** +* +* Allows undo/redo of the Clear operation. +* +**/ + +public class ReversibleClearAction extends ReversibleAction { + + private TMSelectionCanvas selection; + private TMEditorCanvas owner; + private int x, y; + + public ReversibleClearAction(TMSelectionCanvas selection, TMEditorCanvas owner) { + super("Clear Selection"); // i18n + this.selection = selection; + this.owner = owner; + x = selection.getX() / selection.getScaledTileDim(); + y = selection.getY() / selection.getScaledTileDim(); + } + + public void undo() { + owner.showSelection(selection, x, y); + } + + public void redo() { + owner.remove(selection); + owner.repaint(); + } + + public boolean canUndo() { return true; } + public boolean canRedo() { return true; } + +} \ No newline at end of file diff --git a/src/tm/reversibleaction/ReversibleCutAction.java b/src/tm/reversibleaction/ReversibleCutAction.java new file mode 100644 index 0000000..060b080 --- /dev/null +++ b/src/tm/reversibleaction/ReversibleCutAction.java @@ -0,0 +1,56 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.reversibleaction; + +import tm.canvases.TMSelectionCanvas; +import tm.canvases.TMEditorCanvas; + +/** +* +* Allows undo/redo for the Cut operation. +* +**/ + +public class ReversibleCutAction extends ReversibleAction { + + private TMSelectionCanvas selection; + private TMEditorCanvas owner; + private int x, y; + + public ReversibleCutAction(TMSelectionCanvas selection, TMEditorCanvas owner) { + super("Cut"); // i18n + this.selection = selection; + this.owner = owner; + x = selection.getX() / selection.getScaledTileDim(); + y = selection.getY() / selection.getScaledTileDim(); + } + + public void undo() { + owner.showSelection(selection, x, y); + } + + public void redo() { + owner.remove(selection); + owner.repaint(); + } + + public boolean canUndo() { return true; } + public boolean canRedo() { return true; } + +} \ No newline at end of file diff --git a/src/tm/reversibleaction/ReversibleMoveSelectionAction.java b/src/tm/reversibleaction/ReversibleMoveSelectionAction.java new file mode 100644 index 0000000..f6c9c77 --- /dev/null +++ b/src/tm/reversibleaction/ReversibleMoveSelectionAction.java @@ -0,0 +1,58 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.reversibleaction; + +import tm.canvases.TMSelectionCanvas; + +/** +* +* Allows undo/redo of moving a selection. +* +**/ + +public class ReversibleMoveSelectionAction extends ReversibleAction { + + private TMSelectionCanvas selection; + private int oldX, oldY; + private int newX, newY; + + public ReversibleMoveSelectionAction(TMSelectionCanvas selection, int oldX, int oldY, int newX, int newY) { + super("Move Selection"); // i18n + this.selection = selection; + this.oldX = oldX; + this.oldY = oldY; + this.newX = newX; + this.newY = newY; + } + + public void undo() { + int dim = selection.getScaledTileDim(); + selection.setLocation(oldX * dim, oldY * dim); + } + + public void redo() { + int dim = selection.getScaledTileDim(); + selection.setLocation(newX * dim, newY * dim); + + } + + public boolean canUndo() { return true; } + public boolean canRedo() { return true; } + +} \ No newline at end of file diff --git a/src/tm/reversibleaction/ReversibleNewSelectionAction.java b/src/tm/reversibleaction/ReversibleNewSelectionAction.java new file mode 100644 index 0000000..c89d117 --- /dev/null +++ b/src/tm/reversibleaction/ReversibleNewSelectionAction.java @@ -0,0 +1,56 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.reversibleaction; + +import tm.canvases.TMEditorCanvas; +import tm.canvases.TMSelectionCanvas; + +/** +* +* Allows undo/redo of making a new selection. +* +**/ + +public class ReversibleNewSelectionAction extends ReversibleAction { + private TMSelectionCanvas newSelection; + private TMEditorCanvas owner; + private int newX, newY; + + public ReversibleNewSelectionAction(TMSelectionCanvas newSelection, TMEditorCanvas owner) { + super("New_Selection"); // i18n + this.newSelection = newSelection; + this.owner = owner; + newX = newSelection.getX() / newSelection.getScaledTileDim(); + newY = newSelection.getY() / newSelection.getScaledTileDim(); + } + + public void undo() { + owner.encodeSelection(false); // newSelection + owner.repaint(); + } + + public void redo() { + owner.makeSelection(newSelection); + owner.repaint(); + } + + public boolean canUndo() { return true; } + public boolean canRedo() { return true; } + +} \ No newline at end of file diff --git a/src/tm/reversibleaction/ReversiblePaletteEditAction.java b/src/tm/reversibleaction/ReversiblePaletteEditAction.java new file mode 100644 index 0000000..c712bc4 --- /dev/null +++ b/src/tm/reversibleaction/ReversiblePaletteEditAction.java @@ -0,0 +1,59 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.reversibleaction; + +import tm.TMPalette; +import tm.ui.TMView; + +/** +* +* Allows undo/redo of a palette entry modification. +* +**/ + +public class ReversiblePaletteEditAction extends ReversibleAction { + + private int colorIndex; + private int oldColor; + private int newColor; + private TMPalette palette; + + public ReversiblePaletteEditAction(TMView view, TMPalette palette, int colorIndex, int oldColor, int newColor) { + super("Edit Palette"); // i18n + this.palette = palette; + this.colorIndex = colorIndex; + this.oldColor = oldColor; + this.newColor = newColor; + } + + public void undo() { + palette.setEntryRGB(colorIndex, oldColor); + // paletteChanged() + } + + public void redo() { + palette.setEntryRGB(colorIndex, newColor); + // paletteChanged() + } + + public boolean canUndo() { return true; } + + public boolean canRedo() { return true; } + +} \ No newline at end of file diff --git a/src/tm/reversibleaction/ReversiblePasteSelectionAction.java b/src/tm/reversibleaction/ReversiblePasteSelectionAction.java new file mode 100644 index 0000000..31d6341 --- /dev/null +++ b/src/tm/reversibleaction/ReversiblePasteSelectionAction.java @@ -0,0 +1,42 @@ +package tm.reversibleaction; + +import tm.canvases.TMEditorCanvas; +import tm.canvases.TMSelectionCanvas; + +/** + * Manages the Paste undo/redo action + */ +public class ReversiblePasteSelectionAction extends ReversibleAction{ + private TMSelectionCanvas pastedSel; + private TMEditorCanvas owner; + + public ReversiblePasteSelectionAction(TMSelectionCanvas pastedSel, TMEditorCanvas owner) + { + super("Paste"); + this.pastedSel = pastedSel; + this.owner = owner; + + owner.showSelection(pastedSel, 0, 0); + } + + public boolean canUndo() + { + return true; + } + + public boolean canRedo() + { + return true; + } + + public void undo() + { + owner.remove(pastedSel); + owner.redraw(); + } + + public void redo() + { + owner.showSelection(pastedSel,0,0); + } +} diff --git a/src/tm/reversibleaction/ReversibleStretchAction.java b/src/tm/reversibleaction/ReversibleStretchAction.java new file mode 100644 index 0000000..6e93aa0 --- /dev/null +++ b/src/tm/reversibleaction/ReversibleStretchAction.java @@ -0,0 +1,63 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.reversibleaction; + +import tm.canvases.TMSelectionCanvas; + +/** +* +* Allows undo/redo of selection stretching. +* +**/ + +public class ReversibleStretchAction extends ReversibleAction { + + private TMSelectionCanvas canvas; + private int oldCols; + private int oldRows; + private int newCols; + private int newRows; + private byte[] oldBits; + + public ReversibleStretchAction(TMSelectionCanvas canvas, int newCols, int newRows) { + super("Stretch Selection"); // i18n + this.canvas = canvas; + oldCols = canvas.getCols(); + oldRows = canvas.getRows(); + oldBits = canvas.getBits(); + this.newCols = newCols; + this.newRows = newRows; + } + + public void undo() { + canvas.setGridSize(oldCols, oldRows); + canvas.setBits(oldBits); + canvas.unpackPixels(); + canvas.redraw(); + } + + public void redo() { + canvas.stretchTo(newCols, newRows); + canvas.redraw(); + } + + public boolean canUndo() { return true; } + public boolean canRedo() { return true; } + +} \ No newline at end of file diff --git a/src/tm/reversibleaction/ReversibleTileModifyAction.java b/src/tm/reversibleaction/ReversibleTileModifyAction.java new file mode 100644 index 0000000..153d4fe --- /dev/null +++ b/src/tm/reversibleaction/ReversibleTileModifyAction.java @@ -0,0 +1,86 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.reversibleaction; + +import java.awt.Point; +import tm.treenodes.BookmarkItemNode; +import tm.canvases.TMEditorCanvas; + +/** +* +* Allows undo/redo of drawing operations. +* Records the view settings when the edit was done, +* the grid coordinates of the tiles that were modified, +* the old pixels, and the new pixels. +* +**/ + +public class ReversibleTileModifyAction extends ReversibleAction { + + TMEditorCanvas canvas; + BookmarkItemNode bookmark; + Point[] gridCoords; + int[] oldPixels; + int[] newPixels; + + public ReversibleTileModifyAction( + String presentationName, + TMEditorCanvas canvas, + BookmarkItemNode bookmark, + Point[] gridCoords, + int[] oldPixels, + int[] newPixels) { + + super(presentationName); + this.canvas = canvas; + this.bookmark = bookmark; + this.gridCoords = gridCoords; + this.oldPixels = oldPixels; + this.newPixels = newPixels; + } + + public void undo() { + canvas.getView().gotoBookmark(bookmark); + for (int i=0; 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
  • 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 literal 0 HcmV?d00001 diff --git a/src/tm/threads/FileLoaderThread.java b/src/tm/threads/FileLoaderThread.java new file mode 100644 index 0000000..d173fe8 --- /dev/null +++ b/src/tm/threads/FileLoaderThread.java @@ -0,0 +1,90 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.threads; + +import java.io.*; + +/** +* +* Thread for reading a file into a buffer. +* +**/ + +public class FileLoaderThread extends ProgressThread { + + private static final int CHUNK_SIZE = 16384; + BufferedInputStream bis=null; + private int bytesLeft; + private byte[] contents; + + public FileLoaderThread(File file) throws OutOfMemoryError, FileNotFoundException { + super(); + try { + contents = new byte[(int)file.length()]; + } + catch (OutOfMemoryError e) { + throw e; + } + try { + bis = new BufferedInputStream(new FileInputStream(file)); + } catch (FileNotFoundException e) { + throw e; + } + bytesLeft = contents.length; + this.setPriority(NORM_PRIORITY); + } + + public int getPercentageCompleted() { + int result = (int)((long)(((long)contents.length - (long)bytesLeft) * 100) / (long)contents.length); + return result; + } + + public void run() { + while (bytesLeft > 0) { + if (bytesLeft > CHUNK_SIZE) { + try { + bis.read(contents, contents.length - bytesLeft, CHUNK_SIZE); + } + catch (Exception e) { } + bytesLeft -= CHUNK_SIZE; + } + else { + try { + bis.read(contents, contents.length - bytesLeft, bytesLeft); + } + catch (Exception e) { } + bytesLeft = 0; + } + yield(); + } + try { + bis.close(); + } catch (Exception e) { } + // done loading data + } + + public byte[] getContents() { + return contents; + } + + public void killContentsRef() { + contents = null; + } + +} \ No newline at end of file diff --git a/src/tm/threads/FileSaverThread.java b/src/tm/threads/FileSaverThread.java new file mode 100644 index 0000000..1e8f3ef --- /dev/null +++ b/src/tm/threads/FileSaverThread.java @@ -0,0 +1,83 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.threads; + +import java.io.*; + +/** +* +* Thread for writing a buffer to a file. +* +**/ + +public class FileSaverThread extends ProgressThread { + + private static final int CHUNK_SIZE = 16384; + private RandomAccessFile raf=null; + private int bytesLeft; + private byte[] contents; + + public FileSaverThread(byte[] contents, File file) + throws FileNotFoundException, IOException { + super(); + this.contents = contents; + try { + raf = new RandomAccessFile(file, "rw"); + raf.seek(0); + } + catch (FileNotFoundException e) { + throw e; + } + catch (IOException e) { + throw e; + } + bytesLeft = contents.length; + this.setPriority(NORM_PRIORITY); + } + + public int getPercentageCompleted() { + int result = (int)(((long)contents.length - (long)bytesLeft) * 100 / (long)contents.length); + return result; + } + + public void run() { + while (bytesLeft > 0) { + if (bytesLeft > CHUNK_SIZE) { + try { + raf.write(contents, contents.length - bytesLeft, CHUNK_SIZE); + } + catch (Exception e) { } + bytesLeft -= CHUNK_SIZE; + } + else { + try { + raf.write(contents, contents.length - bytesLeft, bytesLeft); + } + catch (Exception e) { } + bytesLeft = 0; + } + yield(); + } + try { + raf.close(); + } catch (Exception e) { } + // done saving data + } + +} \ No newline at end of file diff --git a/src/tm/threads/ProgressThread.java b/src/tm/threads/ProgressThread.java new file mode 100644 index 0000000..f61af4e --- /dev/null +++ b/src/tm/threads/ProgressThread.java @@ -0,0 +1,23 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.threads; + +public abstract class ProgressThread extends Thread { + public abstract int getPercentageCompleted(); +} diff --git a/src/tm/tilecodecs/CompositeTileCodec.java b/src/tm/tilecodecs/CompositeTileCodec.java new file mode 100644 index 0000000..88d297f --- /dev/null +++ b/src/tm/tilecodecs/CompositeTileCodec.java @@ -0,0 +1,102 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.tilecodecs; + +/** +* +* Composite tile codec. +* A composite tile is a tile that is built up of several +* standard tiles. As an example, consider a 3bpp tile that consists +* of a single 2bpp non-interleaved tile followed by a single 1bpp tile. +* Such a format cannot be accommodated by the standard planar tile codec +* (PlanarTileCodec). However, it can be accommodated by instantiating several +* PlanarTileCodecs, decoding planar tiles separately and then "overlaying" them +* on top of each other. This class provides just this kind of functionality. +* It allows more flexibility in the tile formats, but is probably a bit +* slower. +* +**/ + +public class CompositeTileCodec extends TileCodec { + + private TileCodec[] codecs; + +/** +* +* Creates a composite tile codec. +* codecs is an array of codecs that will be used to build +* a tile, going from low to high bitplanes. +* +**/ + + public CompositeTileCodec(String id, int bpp, TileCodec[] codecs, String description) { + super(id, bpp, description); + this.codecs = codecs; + } + +/** +* +* Decodes a tile. +* +* @param bits An array of ints holding encoded tile data in each LSB +* @param ofs Where to start decoding from in the array +* +**/ + + public int[] decode(byte[] bits, int ofs, int stride) { + // decode the first sub-tile + int[] tilePixels = codecs[0].decode(bits, ofs, stride); + System.arraycopy(tilePixels, 0, pixels, 0, tilePixels.length); + // decode remaining sub-tiles + int p = codecs[0].getBitsPerPixel(); + for (int i=1; i>= p; + } + codecs[i].encode(pixels, bits, ofs, stride); + p += codecs[i].getBitsPerPixel(); + } + } + +} \ No newline at end of file diff --git a/src/tm/tilecodecs/DirectColorTileCodec.java b/src/tm/tilecodecs/DirectColorTileCodec.java new file mode 100644 index 0000000..5b3cde4 --- /dev/null +++ b/src/tm/tilecodecs/DirectColorTileCodec.java @@ -0,0 +1,257 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.tilecodecs; + +/** +* +* 16, 24, and 32-bit direct-color (ARGB) tile codec. +* # of bits per color component must not exceed 8. +* The color component masks must be directly adjacent. +* +**/ + +public class DirectColorTileCodec extends TileCodec { + + public static final int LITTLE_ENDIAN=1; + public static final int BIG_ENDIAN=2; + + private static int endianness; // LITTLE_ENDIAN | BIG_ENDIAN + + private int rmask; // bitmask for Red component + private int gmask; // bitmask for Green component + private int bmask; // bitmask for Blue component + private int amask; // bitmask for Alpha component + + // how much each component must be shifted to be transformed to a 32-bit ARGB int-packed Java pixel. + // these are pre-calculated in the constructor and used for decoding/encoding individual pixels. + private int rshift; + private int gshift; + private int bshift; + private int ashift; + + // number of bytes that hold one compressed pixel. + private int bytesPerPixel; + + private int startShift; + private int shiftStep; + +/** +* +* Creates a direct-color tile codec. +* +**/ + + public DirectColorTileCodec(String id, int bpp, int rmask, int gmask, int bmask, int amask, String description) { + super(id, getByteIntegralBitCount(bpp), description); + bytesPerPixel = bitsPerPixel / 8; // 2, 3 or 4 + this.rmask = rmask; + this.gmask = gmask; + this.bmask = bmask; + this.amask = amask; + // calculate the shifts + rshift = 23 - msb(rmask); + gshift = 15 - msb(gmask); + bshift = 7 - msb(bmask); + ashift = 31 - msb(amask); + + setEndianness(LITTLE_ENDIAN); // default + } + +/** +* Sets the endianness. +**/ + + public void setEndianness(int endianness) { + this.endianness = endianness; + if (endianness == LITTLE_ENDIAN) { + startShift = 0; + shiftStep = 8; + } + else { + // BIG_ENDIAN + startShift = (bytesPerPixel-1) * 8; + shiftStep = -8; + } + } + +/** +* Gets the position of the most significant set bit in the given int. +**/ + + private static int msb(int mask) { + for (int i=31; i>=0; i--) { + if ((mask & 0x80000000) != 0) { + return i; + } + mask <<= 1; + } + return -1; // no bits set + } + +/** +* +* Decodes a tile. +* +**/ + + public int[] decode(byte[] bits, int ofs, int stride) { + int v, r, g, b, a, s; + int pos=0; + stride *= bytesPerRow; + for (int i=0; i<8; i++) { + // do one row of pixels + for (int j=0; j<8; j++) { + + // get encoded pixel + s = startShift; + v = 0; + for (int k=0; k>= -rshift; + } + else { + r <<= rshift; + } + + // decode G component + g = v & gmask; + if (gshift < 0) { + g >>= -gshift; + } + else { + g <<= gshift; + } + + // decode B component + b = v & bmask; + if (bshift < 0) { + b >>= -bshift; + } + else { + b <<= bshift; + } + + // decode A component + a = v & amask; + if (ashift < 0) { + a >>= -ashift; + } + else { + a <<= ashift; + } + + // final pixel + pixels[pos++] = a | r | g | b; + } + ofs += stride; + } + return pixels; + } + +/** +* +* Encodes a tile. +* +**/ + + public void encode(int[] pixels, byte[] bits, int ofs, int stride) { + int v, r, g, b, a, s, argb; + int pos=0; + stride *= bytesPerRow; + for (int i=0; i<8; i++) { + // do one row of pixels + for (int j=0; j<8; j++) { + + // get decoded pixel + argb = pixels[pos++]; + + // encode R component + r = argb; + if (rshift < 0) { + r <<= -rshift; + } + else { + r >>= rshift; + } + r &= rmask; + + // encode G component + g = argb; + if (gshift < 0) { + g <<= -gshift; + } + else { + g >>= gshift; + } + g &= gmask; + + // encode B component + b = argb; + if (bshift < 0) { + b <<= -bshift; + } + else { + b >>= bshift; + } + b &= bmask; + + // encode A component + a = argb; + if (ashift < 0) { + a <<= -ashift; + } + else { + a >>= ashift; + } + a &= amask; + + // final value + s = startShift; + v = a | r | g | b; + for (int k=0; k> s); + s += shiftStep; + } + + } + ofs += stride; + } + } + +/** +* +* Gets the least number of whole bytes that are required to store +* bits bits of information. +* +**/ + + private static int getByteIntegralBitCount(int bits) { + int bytes = bits / 8; + int extrabits = bits % 8; + if (extrabits != 0) bytes++; + return bytes * 8; + } + +} \ No newline at end of file diff --git a/src/tm/tilecodecs/LinearTileCodec.java b/src/tm/tilecodecs/LinearTileCodec.java new file mode 100644 index 0000000..e14241a --- /dev/null +++ b/src/tm/tilecodecs/LinearTileCodec.java @@ -0,0 +1,166 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.tilecodecs; + +/** +* +* Linear palette-indexed 8x8 tile codec. Max. 8 bits per pixel. +* bitsPerPixel mod 2 = 0 (so only 1, 2, 4, 8bpp possible). +* +* Some notes on "pixel ordering": +* +* I define pixel order for a row like so: 0 1 2 3 4 5 6 7. +* In other words, pixels are numbered from leftmost to rightmost, +* as they appear on screen. +* I define bit order in a byte like so: 7 6 5 4 3 2 1 0. +* In other words, bits are numbered from rightmost (high) to leftmost (low). +* +* For formats with less than 8 bits per pixel, it is then an +* issue how bits are extracted from the bytes of encoded tile data +* to form the order of pixels stated above. +* +* Note that this applies at the PIXEL-level, not bit-, byte- or row-level; +* this is why ordering is not an issue for 8bpp tiles, since each byte +* contains only one pixel. It is assumed that the bytes themselves are +* always stored in-order (0, 1, 2, 3, ...). Similary, it is assumed that +* the individual bits of a pixel are always stored from high -> low. +* +* The familiar terms "little endian" and "big endian" are not appropriate to +* use here, as I consider them to apply at the byte-level. To avoid any +* confusion or ambiguity, I therefore use the expressions "in-order" and +* "reverse-order" to refer to the ordering of pixels within a byte. +* This is still a bit tricky since the order of pixels and bits above are +* reverses of eachother to begin with, but shouldn't be too confusing: +* +* I define "in-order" to mean that the order of pixel data as stored in a byte +* complies with the order of pixels to be rendered, from left to right. For +* 1bpp, this is simple: in-order means that bit 7 corresponds to pixel 0, +* bit 6 to pixel 1 and so on. Reverse-order means that bit 7 corresponds to +* pixel 7, bit 6 corresponds to pixel 6 and so on (in other words, the bits +* have to be reversed from left to right in order for the pixel order to be +* correct). Diagrammatically: +* +* Pixels: 01234567 +* |||||||| (In-order) +* Bits: 76543210 +* +* Pixels: 01234567 +* |||||||| (Reverse-order) +* Bits: 01234567 +* +* This extends quite intuitively to the cases of 2 and 4 bits per pixel. +* I will give one example of each. +* +* 2bpp, in-order: +* +* Pixels: 0 1 2 3 +* | | | | +* Bits: 76 54 32 10 +* +* 4bpp, reverse-order: +* +* Pixels: 0 1 +* | | +* Bits: 3210 7654 +* +**/ + +public class LinearTileCodec extends TileCodec { + + public static final int IN_ORDER=1; + public static final int REVERSE_ORDER=2; + + protected int ordering; + protected int pixelsPerByte; + protected int pixelMask; + protected int startPixel; + protected int boundary; + protected int step; + +/** +* Constructor. +**/ + + public LinearTileCodec(String id, int bitsPerPixel, int ordering, String description) { + super(id, bitsPerPixel, description); // <= 8 + this.ordering = ordering; // IN_ORDER or REVERSE_ORDER + pixelsPerByte = 8 / bitsPerPixel; + pixelMask = (int)(colorCount - 1); + + if (IN_ORDER == ordering) { + startPixel = pixelsPerByte-1; + boundary = -1; + step = -1; + } + else { // REVERSE_ORDER + startPixel = 0; + boundary = pixelsPerByte; + step = 1; + } + } + +/** +* +* Decodes a tile. +* +**/ + + public int[] decode(byte[] bits, int ofs, int stride) { + int pos=0; + stride *= bytesPerRow; + for (int i=0; i<8; i++) { + // do one row + for (int k=0; k> bitsPerPixel*m) & pixelMask; + } + } + ofs += stride; + } + return pixels; + } + +/** +* +* Encodes a tile. +* +**/ + + public void encode(int[] pixels, byte[] bits, int ofs, int stride) { + int pos = 0; + stride *= bytesPerRow; + for (int i=0; i<8; i++) { + // do one row + for (int k=0; k=0; k--) { + // do one pixel + bitsToPixelsLookup[i][j][7-k] = ((j >> k) & 1) << i; + } + } + } + } + } + +/** +* +* Decodes a tile. +* +* @param bits An array of ints holding encoded tile data in each LSB +* @param ofs Where to start decoding from in the array +* +**/ + + public int[] decode(byte[] bits, int ofs, int stride) { + int pos=0; + stride++; + stride *= bytesPerRow; + for (int i=0; i<8; i++) { + // do one row of pixels + for (int j=0; j> k) & 0x01) << (7-j); + } + pos++; + } + ofs += stride; + } + } + +} \ No newline at end of file diff --git a/src/tm/tilecodecs/TileCodec.java b/src/tm/tilecodecs/TileCodec.java new file mode 100644 index 0000000..0df3931 --- /dev/null +++ b/src/tm/tilecodecs/TileCodec.java @@ -0,0 +1,150 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.tilecodecs; + +/** +* +* Abstract class for 8x8 ("atomic") tile codecs. +* To add a new tile format, simply extend this class and implement decode() and encode(). +* +**/ + +public abstract class TileCodec { + + public static final int MODE_1D=1; + public static final int MODE_2D=2; + + private String id; + private String description; + protected int[] pixels; // destination for DEcoded tile data + protected int bitsPerPixel; + protected int bytesPerRow; // row = 8 pixels + protected long colorCount; + protected int tileSize; // size of one encoded tile + +/** +* +* Constructor. Every subclass must call this with argument bitsPerPixel. +* +* @param bitsPerPixel Duh! +* +**/ + + public TileCodec(String id, int bitsPerPixel, String description) { + this.id = id; + this.bitsPerPixel = bitsPerPixel; + this.description = description; + bytesPerRow = bitsPerPixel; // because (bitsPerPixel*8)/8 = bitsPerPixel + tileSize = bytesPerRow*8; + colorCount = 1 << bitsPerPixel; + pixels = new int[8*8]; + } + +/** +* +* Decodes a tile. +* +* @param bits An array of encoded tile data +* @param ofs Start offset of tile in bits array +* +**/ + + public abstract int[] decode(byte[] bits, int ofs, int stride); + +/** +* +* Encodes a tile. +* +* @param pixels An array of decoded tile data +* +**/ + + public abstract void encode(int[] pixels, byte[] bits, int ofs, int stride); + +/** +* +* Gets the # of bits per pixel for the tile format. +* +**/ + + public int getBitsPerPixel() { + return bitsPerPixel; + } + +/** +* +* Gets the # of bytes per row (8 pixels) for the tile format. +* +**/ + + public int getBytesPerRow() { + return bytesPerRow; + } + +/** +* +* +* +**/ +/* + public long getColorCount() { + return colorCount; + } +*/ +// TEMP!!!!!!!!!! + public int getColorCount() { + if (bitsPerPixel < 8) return (1 << bitsPerPixel); + return 256; + } + +/** +* +* Gets the size in bytes of one tile encoded in this format. +* +**/ + + public int getTileSize() { + return tileSize; + } + +/** +* +* Gets the description of the codec. +* +**/ + + public String getDescription() { + return description; + } + +/** +* +* Gets the codec id. +* +**/ + + public String getID() { + return id; + } + + public String toString() { + return description; + } + +} \ No newline at end of file diff --git a/src/tm/tilecodecs/_3BPPLinearTileCodec.java b/src/tm/tilecodecs/_3BPPLinearTileCodec.java new file mode 100644 index 0000000..3df5c76 --- /dev/null +++ b/src/tm/tilecodecs/_3BPPLinearTileCodec.java @@ -0,0 +1,70 @@ +package tm.tilecodecs; + +public class _3BPPLinearTileCodec extends TileCodec { + +/** +* Constructor. +**/ + + public _3BPPLinearTileCodec() { + super("LN99", 3, "3bpp linear"); + } + +/** +* +* Decodes a tile. +* +**/ + + public int[] decode(byte[] bits, int ofs, int stride) { + int pos=0; + int b1, b2, b3; + stride *= bytesPerRow; + for (int i=0; i<8; i++) { + // do one row + b1 = bits[ofs++] & 0xFF; // byte 1: 0001 1122 + b2 = bits[ofs++] & 0xFF; // byte 2: 2333 4445 + b3 = bits[ofs++] & 0xFF; // byte 3: 5566 6777 + pixels[pos++] = (b1 >> 5) & 7; + pixels[pos++] = (b1 >> 2) & 7; + pixels[pos++] = ((b1 & 3) << 1) | ((b2 >> 7) & 1); + pixels[pos++] = (b2 >> 4) & 7; + pixels[pos++] = (b2 >> 1) & 7; + pixels[pos++] = ((b2 & 1) << 2) | ((b3 >> 6) & 3); + pixels[pos++] = (b3 >> 3) & 7; + pixels[pos++] = b3 & 7; + ofs += stride; + } + return pixels; + } + +/** +* +* Encodes a tile. +* +**/ + + public void encode(int[] pixels, byte[] bits, int ofs, int stride) { + int pos = 0; + int b1, b2, b3; + stride *= bytesPerRow; + for (int i=0; i<8; i++) { + // do one row + b1 = (pixels[pos++] & 7) << 5; + b1 |= (pixels[pos++] & 7) << 2; + b1 |= (pixels[pos] & 6) >> 1; + b2 = (pixels[pos++] & 1) << 7; + b2 |= (pixels[pos++] & 7) << 4; + b2 |= (pixels[pos++] & 7) << 1; + b2 |= (pixels[pos] & 4) >> 2; + b3 = (pixels[pos++] & 3) << 6; + b3 |= (pixels[pos++] & 7) << 3; + b3 |= (pixels[pos++] & 7); + bits[ofs++] = (byte)b1; // byte 1: 0001 1122 + bits[ofs++] = (byte)b2; // byte 2: 2333 4445 + bits[ofs++] = (byte)b3; // byte 3: 5566 6777 + ofs += stride; + } + } + +} \ No newline at end of file diff --git a/src/tm/treenodes/BookmarkItemNode.java b/src/tm/treenodes/BookmarkItemNode.java new file mode 100644 index 0000000..07ac57f --- /dev/null +++ b/src/tm/treenodes/BookmarkItemNode.java @@ -0,0 +1,256 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.treenodes; + +import tm.tilecodecs.TileCodec; + +/** +* +* A file bookmark. +* Records all info required to restore the view presented to the user at the +* time the bookmark was added. +* +**/ + +public class BookmarkItemNode extends TMTreeNode { + + private int offset; // file offset + private int cols; + private int rows; + private int blockWidth; + private int blockHeight; + private boolean rowInterleaved; + private boolean sizeBlockToCanvas; + private int mode; // MODE_1D or MODE_2D + private TileCodec codec; + private String description; // entered by the user to describe/name the bookmark + private String paletteID; + private int palIndex; + + public BookmarkItemNode(int offset, + int cols, + int rows, + int blockWidth, + int blockHeight, + boolean rowInterleaved, + boolean sizeBlockToCanvas, + int mode, + int palIndex, + TileCodec codec, + String description + ) { + super(); + this.offset = offset; + this.cols = cols; + this.rows = rows; + this.blockWidth = blockWidth; + this.blockHeight = blockHeight; + this.rowInterleaved = rowInterleaved; + this.sizeBlockToCanvas = sizeBlockToCanvas; + this.mode = mode; + this.palIndex = palIndex; + this.codec = codec; + this.description = description; + } + +/** +* +* Gets the file offset that marks the beginning of the bookmark. +* +**/ + + public int getOffset() { + return offset; + } + +/** +* +* Gets the # of columns. +* +**/ + + public int getCols() { + return cols; + } + +/** +* +* Gets the # of rows. +* +**/ + + public int getRows() { + return rows; + } + +/** +* +* Gets the block width. +* +**/ + + public int getBlockWidth() { + return blockWidth; + } + +/** +* +* Gets the block height. +* +**/ + + public int getBlockHeight() { + return blockHeight; + } + +/** +* +* +* +**/ + + public boolean getRowInterleaved() { + return rowInterleaved; + } + +/** +* +* +* +**/ + + public boolean getSizeBlockToCanvas() { + return sizeBlockToCanvas; + } + +/** +* +* Gets the mode. +* +**/ + + public int getMode() { + return mode; + } + +/** +* +* Gets the palette index. +* +**/ + + public int getPalIndex() { + return palIndex; + } + +/** +* +* Gets the codec. +* +**/ + + public TileCodec getCodec() { + return codec; + } + +/** +* +* Gets the bookmark description. +* +**/ + + public String getDescription() { + return description; + } + +/** +* +* Sets the bookmark description. +* +**/ + + public void setDescription(String description) { + this.description = description; + setModified(true); + } + +/** +* +* Returns the XML-equivalent of this bookmark. +* +**/ + + public String toXML() { + StringBuffer s = new StringBuffer(); + s.append(getIndent()); + s.append("\n"); + s.append(getIndent()).append(" "); + s.append("").append(description).append("\n"); + s.append(getIndent()); + s.append("\n"); + return s.toString(); + } + +/** +* +* +* +**/ + + public String toString() { + return description; + } + +/** +* +* +* +**/ + + public void setText(String text) { + this.description = text; + } + +/** +* +* +* +**/ + + public String getToolTipText() { + return "Offset: "+offset+" ... Columns: "+cols+" ... Rows: "+rows+" ... Codec: "+codec.getDescription(); + } + +} \ No newline at end of file diff --git a/src/tm/treenodes/FolderNode.java b/src/tm/treenodes/FolderNode.java new file mode 100644 index 0000000..8b0a196 --- /dev/null +++ b/src/tm/treenodes/FolderNode.java @@ -0,0 +1,86 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.treenodes; + +/** +* +* A folder. +* Has a name and zero or more children, each of which may be either +* an item or a folder. +* +**/ + +public class FolderNode extends TMTreeNode { + + private String name; + +/** +* +* Creates a folder with the given name. +* +**/ + + public FolderNode(String name) { + super(); + this.name = name; + } + +/** +* +* +* +**/ + + public String toString() { + return name; + } + +/** +* +* Returns the XML-equivalent of this folder. +* +**/ + + public String toXML() { + // TODO: Use getDepth() to indent properly + StringBuffer s = new StringBuffer(); + s.append(getIndent()); + s.append("\n"); + s.append(getIndent()).append(" "); + s.append("").append(name).append("\n"); + TMTreeNode[] children = getChildren(); + for (int i=0; i\n"); + return s.toString(); + } + +/** +* +* +* +**/ + + public void setText(String text) { + this.name = text; + } + +} \ No newline at end of file diff --git a/src/tm/treenodes/PaletteItemNode.java b/src/tm/treenodes/PaletteItemNode.java new file mode 100644 index 0000000..2a855c8 --- /dev/null +++ b/src/tm/treenodes/PaletteItemNode.java @@ -0,0 +1,135 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.treenodes; + +import tm.TMPalette; +import tm.colorcodecs.ColorCodec; +import tm.utils.HexStringConverter; + +/** +* +* A palette node. +* +**/ + +public class PaletteItemNode extends TMTreeNode { + + private TMPalette palette; + private String description; + + public PaletteItemNode(TMPalette palette, String description) { + super(); + this.palette = palette; + this.description = description; + } + +/** +* +* Gets the palette represented by this node. +* +**/ + + public TMPalette getPalette() { + return palette; + } + +/** +* +* Gets the palette description. +* +**/ + + public String getDescription() { + return description; + } + +/** +* +* Sets the palette description. +* +**/ + + public void setDescription(String description) { + this.description = description; + setModified(true); + } + +/** +* +* Returns the XML-equivalent of this palette node. +* +**/ + + public String toXML() { + StringBuffer s = new StringBuffer(); + s.append(getIndent()); + s.append("\n"); + s.append(getIndent()).append(" "); + s.append("").append(description).append("\n"); + if (palette.isDirect()) { + s.append(getIndent()).append(" "); + s.append(""); + s.append(HexStringConverter.bytesToHexString(palette.entriesToBytes())); + s.append("\n"); + } + s.append(getIndent()); + s.append("\n"); + return s.toString(); + } + +/** +* +* Returns the string representation of this node. +* +**/ + + public String toString() { + return description; + } + +/** +* +* Sets the text of this node. +* +**/ + + public void setText(String text) { + setDescription(text); + } + +/** +* +* Gets the tooltiptext of this node. +* +**/ + + public String getToolTipText() { + return "Size: "+palette.getSize()+" ... Format: "+palette.getCodec().getDescription(); + } + +} \ No newline at end of file diff --git a/src/tm/treenodes/TMTreeNode.java b/src/tm/treenodes/TMTreeNode.java new file mode 100644 index 0000000..866dcea --- /dev/null +++ b/src/tm/treenodes/TMTreeNode.java @@ -0,0 +1,95 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.treenodes; + +import java.util.Enumeration; +import javax.swing.tree.DefaultMutableTreeNode; + +/** +* +* Generic treenode class. +* +**/ + +public abstract class TMTreeNode extends DefaultMutableTreeNode { + + private boolean modified; + private TMTreeNode parent; + +/** +* +* Creates a treenode. +* +**/ + + public TMTreeNode() { + super(); + modified = false; + } + +/** +* +* +* +**/ + + public TMTreeNode[] getChildren() { + TMTreeNode[] ch = new TMTreeNode[getChildCount()]; + for (int i=0; irootNode. +* @param loadLeaves If true, all nodes are loaded; if false, only internal nodes. +* +**/ + + public void loadTreeNodes(TMTreeNode rootNode, boolean loadLeaves) { + if (loadLeaves) { + setModel(new DefaultTreeModel(rootNode)); + } + else { + setModel(new FolderTreeModel(rootNode)); + } +// model.addTreeModelListener(this); + } + +/** +* +* Gets the selected node. +* If there is no selected node, the root is returned as default. +* +**/ + + public TMTreeNode getSelectedNode() { + TMTreeNode n = (TMTreeNode)getLastSelectedPathComponent(); + if (n != null) return n; + return (TMTreeNode)getModel().getRoot(); + } + +/** +* +* Expands the specified node. +* +**/ + + public void expandNode(DefaultMutableTreeNode node) { + setExpandedState(new TreePath(node.getPath()), true); + } + +/** +* +* +* +**/ + + private class FolderTreeModel extends DefaultTreeModel { + + private DefaultMutableTreeNode mRoot; + + FolderTreeModel(DefaultMutableTreeNode root) { + super(root); + mRoot= root; + } + + public Object getChild(Object parent, int index) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode)parent; + int pos = 0; + for (int i=0, cnt=0; i 8) + bitDepth = 8; + this.bitDepth = bitDepth; + colorCount = 1 << bitDepth; + } + +/** +* +* Paints the palette. +* +**/ + + public void paintComponent(Graphics g) { + super.paintComponent(g); + if (palette != null) { + int colorIndex = palIndex * colorCount; + int w = getBoxWidth(); + int h = getBoxHeight(); + // draw color boxes + int x=0, y=0; + for (int i=0; i ("+x2+","+y2+") = ("+w+","+h+")"); + } + +/** +* +* Sets the text that indicates the graphics codec in use. +* +**/ + + public void setCodec(String s) { + codecLabel.setText(" "+s+" "); // i18n + } + + + +/** +* +* Sets the text that indicates the graphics codec in use. +* +**/ + + public void setPalOffset(int offset) { + String hexOffset = Integer.toHexString(offset).toUpperCase(); + while (hexOffset.length() < 8) { + hexOffset = "0" + hexOffset; + } + palOffsetLabel.setText(" Palette: "+hexOffset+" "); // i18n + } + + +/** +* +* Sets the text that indicates the current mode. +* +**/ + + public void setMode(int mode) { + if (mode == TileCodec.MODE_1D) + modeLabel.setText(" 1-Dimensional "); // i18n + else + modeLabel.setText(" 2-Dimensional "); // i18n + } + +/** +* +* Sets the text that indicates how many tiles are shown. +* +**/ + + public void setTiles(int w, int h) { + tilesLabel.setText(" "+w+"x"+h+" tiles "); // i18n + } + +/** +* +* Called when a view has been selected. +* +**/ + + public void viewSelected(TMView view) { + TMEditorCanvas ec = view.getEditorCanvas(); + setMessage(""); + setOffset(view.getOffset()); + if (ec.isSelecting()) { + setSelectionCoords(ec.getSelX1(), ec.getSelY1(), ec.getCurrentCol(), ec.getCurrentRow()); + } + else if (ec.isDrawingLine()) { + setSelectionCoords(ec.getLineX1(), ec.getLineY1(), ec.getLineX2(), ec.getLineY2()); + } + else { + setCoords(ec.getCurrentCol(), ec.getCurrentRow()); + } + if (view.getTileCodec() != null) { + setCodec(view.getTileCodec().getDescription()); + } + else { + setCodec(""); + } + setPalOffset(view.getPalette().getOffset()); + setMode(view.getMode()); + setTiles(view.getCols(), view.getRows()); + } + +/** + * + * Convenience method for setting various fields of gridbagconstraints. + * + */ + + protected static void buildConstraints(GridBagConstraints gbc, int gx, int gy, int gw, int gh, int wx, int wy) { + gbc.gridx = gx; + gbc.gridy = gy; + gbc.gridwidth = gw; + gbc.gridheight = gh; + gbc.weightx = wx; + gbc.weighty = wy; + } + +} \ No newline at end of file diff --git a/src/tm/ui/TMUI.java b/src/tm/ui/TMUI.java new file mode 100644 index 0000000..98718a4 --- /dev/null +++ b/src/tm/ui/TMUI.java @@ -0,0 +1,4833 @@ +/* +* +* Copyright (C) 2003 Kent Hansen. +* +* This file is part of Tile Molester. +* +* Tile Molester is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Tile Molester is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +package tm.ui; + +import tm.*; +import tm.colorcodecs.*; +import tm.tilecodecs.*; +import tm.fileselection.*; +import tm.modaldialog.*; +import tm.treenodes.*; +import tm.utils.*; +import tm.threads.*; +import tm.filelistener.*; +import tm.canvases.*; +import javax.swing.*; +import javax.swing.event.*; +import java.awt.*; +import java.awt.event.*; +import java.io.*; +import javax.swing.border.*; +import javax.swing.filechooser.FileFilter; +import java.util.Locale; +import java.util.Vector; +import java.util.Hashtable; +import java.util.StringTokenizer; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import java.io.IOException; +import javax.xml.parsers.ParserConfigurationException; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +/** +* +* The main UI window. +* Has a desktop for child frames, a menu, toolbars, a palette panel, and a statusbar. +* The code is mainly dominated by +* 1) setting up the various menus and toolbars; and +* 2) providing action handlers for menu items and tool buttons. +* +**/ + +public class TMUI extends JFrame { + + // tool types + public static final int SELECT_TOOL = 1; + public static final int ZOOM_TOOL = 2; + public static final int PICKUP_TOOL = 3; + public static final int BRUSH_TOOL = 4; + public static final int LINE_TOOL = 5; + public static final int FILL_TOOL = 6; + public static final int REPLACE_TOOL = 7; + public static final int MOVE_TOOL = 8; + + private int tool = SELECT_TOOL; + private int previousTool; + + private int maxRecentFiles = 10; + private Vector recentFiles = new Vector(); + private Vector colorcodecs; + private Vector tilecodecs; + private Vector filefilters; + private Vector palettefilters; + private Vector filelisteners; + + private TMSelectionCanvas copiedSelection=null; + + // UI components + private mxScrollableDesktop desktop = new mxScrollableDesktop(); + private TMStatusBar statusBar = new TMStatusBar(); + private JToolBar toolBar = new JToolBar(JToolBar.HORIZONTAL); + private JToolBar toolPalette = new JToolBar(JToolBar.VERTICAL); + private JToolBar selectionToolBar = new JToolBar(JToolBar.VERTICAL); + private JToolBar navBar = new JToolBar(JToolBar.HORIZONTAL); + private JMenuBar menuBar = new JMenuBar(); + private JPanel toolPane = new JPanel(); // the drawing tools and such + private JPanel toolBarPane = new JPanel(); // the program toolbars + private JPanel bottomPane = new JPanel(); // palette and statusbar + private TMPalettePane palettePane; + + // file choosers + private TMApprovedFileOpenChooser fileOpenChooser = new TMApprovedFileOpenChooser(); + private TMApprovedFileSaveChooser fileSaveChooser = new TMApprovedFileSaveChooser(); + private TMApprovedFileOpenChooser bitmapOpenChooser = new TMApprovedFileOpenChooser(); + private TMApprovedFileSaveChooser bitmapSaveChooser = new TMApprovedFileSaveChooser(); + private TMApprovedFileOpenChooser paletteOpenChooser = new TMApprovedFileOpenChooser(); + + private TMBitmapFilters bmf = new TMBitmapFilters(); + private TMFileFilter allFilter = new AllFilter(); + + // custom dialogs + private TMGoToDialog goToDialog; + private TMNewFileDialog newFileDialog; + private TMCustomCodecDialog customCodecDialog; + private TMStretchDialog stretchDialog; + private TMCanvasSizeDialog canvasSizeDialog; + private TMBlockSizeDialog blockSizeDialog; + private TMAddToTreeDialog addBookmarkDialog; + private TMAddToTreeDialog addPaletteDialog; + private TMOrganizeTreeDialog organizeBookmarksDialog; + private TMOrganizeTreeDialog organizePalettesDialog; + private TMNewPaletteDialog newPaletteDialog; + private TMPaletteSizeDialog paletteSizeDialog; + private TMImportInternalPaletteDialog importInternalPaletteDialog; + + // toolbar buttons + ClassLoader cl = getClass().getClassLoader(); + private ToolButton newButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/New24.gif"))); + private ToolButton openButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/Open24.gif"))); + private ToolButton saveButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/Save24.gif"))); + private ToolButton cutButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/Cut24.gif"))); + private ToolButton copyButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/Copy24.gif"))); + private ToolButton pasteButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/Paste24.gif"))); + private ToolButton undoButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/Undo24.gif"))); + private ToolButton redoButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/Redo24.gif"))); + private ToolButton gotoButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/Import24.gif"))); + private ToolButton addBookmarkButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/Bookmarks24.gif"))); + private ToolButton decWidthButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/DecWidth24.gif"))); + private ToolButton incWidthButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/IncWidth24.gif"))); + private ToolButton decHeightButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/DecHeight24.gif"))); + private ToolButton incHeightButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/IncHeight24.gif"))); + + // navigation bar buttons + private ToolButton minusPageButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/Rewind24.gif"))); + private ToolButton minusRowButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/StepBack24.gif"))); + private ToolButton minusTileButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/Back24.gif"))); + private ToolButton minusByteButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/Minus24.gif"))); + private ToolButton plusByteButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/Plus24.gif"))); + private ToolButton plusTileButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/Forward24.gif"))); + private ToolButton plusRowButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/StepForward24.gif"))); + private ToolButton plusPageButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/FastForward24.gif"))); + + // tool palette buttons + private ToolToggleButton selectButton = new ToolToggleButton(new ImageIcon(cl.getResource("tm/icons/Selection24.gif"))); + private ToolToggleButton zoomButton = new ToolToggleButton(new ImageIcon(cl.getResource("tm/icons/Zoom24.gif"))); + private ToolToggleButton pickupButton = new ToolToggleButton(new ImageIcon(cl.getResource("tm/icons/Dropper24.gif"))); + private ToolToggleButton brushButton = new ToolToggleButton(new ImageIcon(cl.getResource("tm/icons/Brush24.gif"))); + private ToolToggleButton lineButton = new ToolToggleButton(new ImageIcon(cl.getResource("tm/icons/Line24.gif"))); + private ToolToggleButton fillButton = new ToolToggleButton(new ImageIcon(cl.getResource("tm/icons/Fill24.gif"))); + private ToolToggleButton replaceButton = new ToolToggleButton(new ImageIcon(cl.getResource("tm/icons/ColorReplacer24.gif"))); + private ToolToggleButton moveButton = new ToolToggleButton(new ImageIcon(cl.getResource("tm/icons/Mover24.gif"))); + + // selection palette buttons + private ToolButton mirrorButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/Mirror24.gif"))); + private ToolButton flipButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/Flip24.gif"))); + private ToolButton rotateRightButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/RotateRight24.gif"))); + private ToolButton rotateLeftButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/RotateLeft24.gif"))); + private ToolButton shiftLeftButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/ShiftLeft24.gif"))); + private ToolButton shiftRightButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/ShiftRight24.gif"))); + private ToolButton shiftUpButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/ShiftUp24.gif"))); + private ToolButton shiftDownButton = new ToolButton(new ImageIcon(cl.getResource("tm/icons/ShiftDown24.gif"))); + + // File menu + private JMenu fileMenu = new JMenu("File"); + private JMenuItem newMenuItem = new JMenuItem("New..."); + private JMenuItem openMenuItem = new JMenuItem("Open..."); + private JMenu reopenMenu = new JMenu("Reopen"); + private JMenuItem closeMenuItem = new JMenuItem("Close"); + private JMenuItem closeAllMenuItem = new JMenuItem("Close All"); + private JMenuItem saveMenuItem = new JMenuItem("Save"); + private JMenuItem saveAsMenuItem = new JMenuItem("Save As..."); + private JMenuItem saveAllMenuItem = new JMenuItem("Save All"); + private JMenuItem exitMenuItem = new JMenuItem("Exit"); + // Edit menu + private JMenu editMenu = new JMenu("Edit"); + private JMenuItem undoMenuItem = new JMenuItem("Undo"); + private JMenuItem redoMenuItem = new JMenuItem("Redo"); + private JMenuItem cutMenuItem = new JMenuItem("Cut"); + private JMenuItem copyMenuItem = new JMenuItem("Copy"); + private JMenuItem pasteMenuItem = new JMenuItem("Paste"); + private JMenuItem clearMenuItem = new JMenuItem("Clear"); + private JMenuItem selectAllMenuItem = new JMenuItem("Select All"); + private JMenuItem copyToMenuItem = new JMenuItem("Copy To..."); + private JMenuItem pasteFromMenuItem = new JMenuItem("Paste From..."); + // Image menu + private JMenu imageMenu = new JMenu("Image"); + private JMenuItem mirrorMenuItem = new JMenuItem("Mirror"); + private JMenuItem flipMenuItem = new JMenuItem("Flip"); + private JMenuItem rotateRightMenuItem = new JMenuItem("Rotate Right"); + private JMenuItem rotateLeftMenuItem = new JMenuItem("Rotate Left"); + private JMenuItem shiftLeftMenuItem = new JMenuItem("Shift Left"); + private JMenuItem shiftRightMenuItem = new JMenuItem("Shift Right"); + private JMenuItem shiftUpMenuItem = new JMenuItem("Shift Up"); + private JMenuItem shiftDownMenuItem = new JMenuItem("Shift Down"); + private JMenuItem canvasSizeMenuItem = new JMenuItem("Canvas Size..."); + private JMenuItem stretchMenuItem = new JMenuItem("Stretch..."); + // View menu + private JMenu viewMenu = new JMenu("View"); + private JCheckBoxMenuItem statusBarMenuItem = new JCheckBoxMenuItem("Statusbar"); + private JCheckBoxMenuItem toolBarMenuItem = new JCheckBoxMenuItem("Toolbar"); + private JMenu tileCodecMenu = new JMenu("Codec"); + private JMenu zoomMenu = new JMenu("Zoom"); + private JMenuItem zoomInMenuItem = new JMenuItem("In"); + private JMenuItem zoomOutMenuItem = new JMenuItem("Out"); + private JMenuItem _100MenuItem = new JMenuItem("100%"); + private JMenuItem _200MenuItem = new JMenuItem("200%"); + private JMenuItem _400MenuItem = new JMenuItem("400%"); + private JMenuItem _800MenuItem = new JMenuItem("800%"); + private JMenuItem _1600MenuItem = new JMenuItem("1600%"); + private JMenuItem _3200MenuItem = new JMenuItem("3200%"); + private JMenu blockSizeMenu = new JMenu("Block Size"); + private JCheckBoxMenuItem sizeBlockToCanvasMenuItem = new JCheckBoxMenuItem("Full Canvas"); + private JMenuItem customBlockSizeMenuItem = new JMenuItem("Custom..."); + private JRadioButtonMenuItem rowInterleaveBlocksMenuItem = new JRadioButtonMenuItem("Row-interleave Blocks"); + private JMenu modeMenu = new JMenu("Mode"); + private JRadioButtonMenuItem _1DimensionalMenuItem = new JRadioButtonMenuItem("1-Dimensional"); + private JRadioButtonMenuItem _2DimensionalMenuItem = new JRadioButtonMenuItem("2-Dimensional"); + private JCheckBoxMenuItem blockGridMenuItem = new JCheckBoxMenuItem("Block Grid"); + private JCheckBoxMenuItem tileGridMenuItem = new JCheckBoxMenuItem("Tile Grid"); + private JCheckBoxMenuItem pixelGridMenuItem = new JCheckBoxMenuItem("Pixel Grid"); + // Navigate menu + private JMenu navigateMenu = new JMenu("Navigate"); + private JMenuItem goToMenuItem = new JMenuItem("Go To..."); + private JMenuItem goToAgainMenuItem = new JMenuItem("Go To Again"); + private JMenuItem addToBookmarksMenuItem = new JMenuItem("Add To Bookmarks..."); + private JMenuItem organizeBookmarksMenuItem = new JMenuItem("Organize Bookmarks..."); + // private JMenuItem saveBookmarksMenuItem = new JMenuItem("Save Bookmarks"); + // Palette menu + private JMenu paletteMenu = new JMenu("Palette"); + private JMenuItem editColorsMenuItem = new JMenuItem("Edit Colors..."); + private JMenu colorCodecMenu = new JMenu("Format"); + private JMenu paletteEndiannessMenu = new JMenu("Endianness"); + private JRadioButtonMenuItem paletteLittleEndianMenuItem = new JRadioButtonMenuItem("Little"); + private JRadioButtonMenuItem paletteBigEndianMenuItem = new JRadioButtonMenuItem("Big"); + private JRadioButtonMenuItem dummyPaletteMenuItem = new JRadioButtonMenuItem(); + private JMenuItem paletteSizeMenuItem = new JMenuItem("Size..."); + private JMenuItem newPaletteMenuItem = new JMenuItem("New..."); + private JMenu importPaletteMenu = new JMenu("Import From"); + private JMenuItem importInternalPaletteMenuItem = new JMenuItem("This File..."); + private JMenuItem importExternalPaletteMenuItem = new JMenuItem("Another File..."); + private JMenuItem addToPalettesMenuItem = new JMenuItem("Add To Palettes..."); + private JMenuItem organizePalettesMenuItem = new JMenuItem("Organize Palettes..."); +// private JMenuItem savePalettesMenuItem = new JMenuItem("Save Palettes"); +// private JMenuItem exportPaletteMenuItem = new JMenuItem("Export..."); // tpl, c, asm, java? + // Window menu + private JMenu windowMenu = new JMenu("Window"); + private JMenuItem newWindowMenuItem = new JMenuItem("New Window"); + private JMenuItem tileMenuItem = new JMenuItem("Tile"); + private JMenuItem cascadeMenuItem = new JMenuItem("Cascade"); + private JMenuItem arrangeIconsMenuItem = new JMenuItem("Arrange Icons"); + // Help menu + private JMenu helpMenu = new JMenu("Help"); + private JMenuItem helpTopicsMenuItem = new JMenuItem("Help Topics"); + private JMenuItem tipMenuItem = new JMenuItem("Tip of the Millennium..."); + private JMenuItem aboutMenuItem = new JMenuItem("About Tile Molester..."); + + // button groups + private ButtonGroup toolButtonGroup = new ButtonGroup(); + private ButtonGroup colorCodecButtonGroup = new ButtonGroup(); + private ButtonGroup tileCodecButtonGroup = new ButtonGroup(); + private ButtonGroup paletteButtonGroup = new ButtonGroup(); + private ButtonGroup modeButtonGroup = new ButtonGroup(); + private ButtonGroup paletteEndiannessButtonGroup = new ButtonGroup(); + + private Hashtable tileCodecButtonHashtable = new Hashtable(); + private Hashtable colorCodecButtonHashtable = new Hashtable(); + private Hashtable paletteButtonHashtable = new Hashtable(); + private Hashtable fileListenerHashtable = new Hashtable(); + + private Xlator xl; + private File settingsFile = new File("settings.xml"); + + private Locale locale = Locale.getDefault(); + private boolean viewStatusBar=true; + private boolean viewToolBar=true; + + private String lastPath = ""; + + +/** +* +* Creates a Tile Molester UI. +* +**/ + + public TMUI() { + + super("Tile Molester"); + + //I tried to change the UI but it seems innatural + /*try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (UnsupportedLookAndFeelException e) { + e.printStackTrace(); + }*/ + + setIconImage(new ImageIcon(cl.getResource("tm/icons/TMIcon.gif")).getImage()); + + if (settingsFile.exists()) { + // load settings from file + loadSettings(); + } + else { + // assume this is the first time program is run + selectLanguage(); + // File bookmarksDir = new File("bookmarks"); + // bookmarksDir.mkdir(); + // copy bookmarks.dtd to bookmarksDir + // File palettesDir = new File("palettes"); + // palettesDir.mkdir(); + // copy palettes.dtd to palettesDir +/* File resourcesDir = new File("resources"); + if (!resourcesDir.exists()) { + resourcesDir.mkdir(); + File resourceDTDFile = new File(resourcesDir, "tmres.dtd"); + try { + FileWriter fw = new FileWriter(resourceDTDFile); + fw.write(""+ + "\n"+ + "\n"+ + "\n"+ + "\n"+ + "\n"+ + "\n"+ + "\n"+ + "\n"+ + "\n"+ + "\n"+ + "\n"+ + "\n"+ + ""); + fw.close(); + } + catch (Exception e) { } + }*/ + } + setLocale(locale); + Locale.setDefault(locale); + JComponent.setDefaultLocale(this.locale); + + // show splash screen + new TMSplashScreen(this); + +// create a translator + try { + xl = new Xlator("languages/language", locale); + } catch (Exception e) { + JOptionPane.showMessageDialog(this, + xlate("Error reading language file:")+"\n"+e.getMessage(), + "Tile Molester", + JOptionPane.ERROR_MESSAGE); + System.exit(0); + } + +///////// Translate items + + // File menu + fileMenu.setText(xlate("File")); + newMenuItem.setText(xlate("New")); + openMenuItem.setText(xlate("Open")); + reopenMenu.setText(xlate("Reopen")); + closeMenuItem.setText(xlate("Close")); + closeAllMenuItem.setText(xlate("Close_All")); + saveMenuItem.setText(xlate("Save")); + saveAsMenuItem.setText(xlate("Save_As")); + saveAllMenuItem.setText(xlate("Save_All")); + exitMenuItem.setText(xlate("Exit")); + // Edit menu + editMenu.setText(xlate("Edit")); + undoMenuItem.setText(xlate("Undo")); + redoMenuItem.setText(xlate("Redo")); + cutMenuItem.setText(xlate("Cut")); + copyMenuItem.setText(xlate("Copy")); + pasteMenuItem.setText(xlate("Paste")); + clearMenuItem.setText(xlate("Clear")); + selectAllMenuItem.setText(xlate("Select_All")); + copyToMenuItem.setText(xlate("Copy_To")); + pasteFromMenuItem.setText(xlate("Paste_From")); + pasteFromMenuItem.setText(xlate("New_Selection")); + pasteFromMenuItem.setText(xlate("Apply_Selection")); + // Image menu + imageMenu.setText(xlate("Image")); + mirrorMenuItem.setText(xlate("Mirror")); + flipMenuItem.setText(xlate("Flip")); + rotateRightMenuItem.setText(xlate("Rotate_Right")); + rotateLeftMenuItem.setText(xlate("Rotate_Left")); + shiftLeftMenuItem.setText(xlate("Shift_Left")); + shiftRightMenuItem.setText(xlate("Shift_Right")); + shiftUpMenuItem.setText(xlate("Shift_Up")); + shiftDownMenuItem.setText(xlate("Shift_Down")); + canvasSizeMenuItem.setText(xlate("Canvas_Size")); + stretchMenuItem.setText(xlate("Stretch")); + // View menu + viewMenu.setText(xlate("View")); + statusBarMenuItem.setText(xlate("Statusbar")); + toolBarMenuItem.setText(xlate("Toolbar")); + tileCodecMenu.setText(xlate("Codec")); + zoomMenu.setText(xlate("Zoom")); + zoomInMenuItem.setText(xlate("In")); + zoomOutMenuItem.setText(xlate("Out")); + _100MenuItem.setText(xlate("100%")); + _200MenuItem.setText(xlate("200%")); + _400MenuItem.setText(xlate("400%")); + _800MenuItem.setText(xlate("800%")); + _1600MenuItem.setText(xlate("1600%")); + _3200MenuItem.setText(xlate("3200%")); + modeMenu.setText(xlate("Mode")); + _1DimensionalMenuItem.setText(xlate("1_Dimensional")); + _2DimensionalMenuItem.setText(xlate("2_Dimensional")); + blockSizeMenu.setText(xlate("Block_Size")); + sizeBlockToCanvasMenuItem.setText(xlate("Full_Canvas")); + customBlockSizeMenuItem.setText(xlate("Custom_Block_Size")); + rowInterleaveBlocksMenuItem.setText(xlate("Row_Interleave_Blocks")); + blockGridMenuItem.setText(xlate("Block_Grid")); + tileGridMenuItem.setText(xlate("Tile_Grid")); + pixelGridMenuItem.setText(xlate("Pixel_Grid")); + // Navigate menu + navigateMenu.setText(xlate("Navigate")); + goToMenuItem.setText(xlate("Go_To")); + goToAgainMenuItem.setText(xlate("Go_To_Again")); + addToBookmarksMenuItem.setText(xlate("Add_To_Bookmarks")); + organizeBookmarksMenuItem.setText(xlate("Organize_Bookmarks")); + // Palette menu + paletteMenu.setText(xlate("Palette")); + editColorsMenuItem.setText(xlate("Edit_Colors")); + colorCodecMenu.setText(xlate("Format")); + paletteEndiannessMenu.setText(xlate("Endianness")); + paletteLittleEndianMenuItem.setText(xlate("Little_Endian")); + paletteBigEndianMenuItem.setText(xlate("Big_Endian")); + paletteSizeMenuItem.setText(xlate("Size")); + newPaletteMenuItem.setText(xlate("New")); + importPaletteMenu.setText(xlate("Import_From")); + importInternalPaletteMenuItem.setText(xlate("This_File")); + importExternalPaletteMenuItem.setText(xlate("Another_File")); + addToPalettesMenuItem.setText(xlate("Add_To_Palettes")); + organizePalettesMenuItem.setText(xlate("Organize_Palettes")); + // Window menu + windowMenu.setText(xlate("Window")); + newWindowMenuItem.setText(xlate("New_Window")); + tileMenuItem.setText(xlate("Tile")); + cascadeMenuItem.setText(xlate("Cascade")); + arrangeIconsMenuItem.setText(xlate("Arrange_Icons")); + // Help menu + helpMenu.setText(xlate("Help")); + helpTopicsMenuItem.setText(xlate("Help_Topics")); + tipMenuItem.setText(xlate("Tip_of_the_Millennium")); + aboutMenuItem.setText(xlate("About_Tile_Molester")); + + UIManager.put("OptionPane.yesButtonText", xlate("Yes")); + UIManager.put("OptionPane.noButtonText", xlate("No")); + UIManager.put("OptionPane.cancelButtonText", xlate("Cancel")); + UIManager.put("OptionPane.okButtonText", xlate("OK")); + + fileOpenChooser.setDialogTitle(xlate("Open_File_Dialog_Title")); + fileSaveChooser.setDialogTitle(xlate("Save_As_Dialog_Title")); + bitmapOpenChooser.setDialogTitle(xlate("Paste_From_Dialog_Title")); + bitmapSaveChooser.setDialogTitle(xlate("Copy_To_Dialog_Title")); + paletteOpenChooser.setDialogTitle(xlate("Open_Palette_Dialog_Title")); + +///////// Read specs + try { + TMSpecReader.readSpecsFromFile(new File("tmspec.xml")); + } + catch (SAXParseException e) { + JOptionPane.showMessageDialog(this, + xlate("Parser_Parse_Error")+"\n"+ + e.getMessage()+"\n"+ + "("+e.getSystemId()+",\n"+ + "line "+e.getLineNumber()+")\n", + "Tile Molester", + JOptionPane.ERROR_MESSAGE); + System.exit(0); + } + catch (SAXException e) { + JOptionPane.showMessageDialog(this, + xlate("Parser_Parse_Error")+"\n"+e.getMessage(), + "Tile Molester", + JOptionPane.ERROR_MESSAGE); + System.exit(0); + } + catch (ParserConfigurationException e) { + JOptionPane.showMessageDialog(this, + xlate("Parser_Config_Error")+"\n"+e.getMessage(), + "Tile Molester", + JOptionPane.ERROR_MESSAGE); + System.exit(0); + } + catch (IOException e) { + JOptionPane.showMessageDialog(this, + xlate("Parser_IO_Error")+"\n"+e.getMessage(), + "Tile Molester", + JOptionPane.ERROR_MESSAGE); + System.exit(0); + } + + colorcodecs = TMSpecReader.getColorCodecs(); + tilecodecs = TMSpecReader.getTileCodecs(); + filefilters = TMSpecReader.getFileFilters(); + palettefilters = TMSpecReader.getPaletteFilters(); + filelisteners = TMSpecReader.getFileListeners(); + + tilecodecs.add(new _3BPPLinearTileCodec()); +////////// + + // create dialogs. + goToDialog = new TMGoToDialog(this, xl); + newFileDialog = new TMNewFileDialog(this, xl); +// customCodecDialog = new TMCustomCodecDialog(this, "Custom Codec", true, xl); + stretchDialog = new TMStretchDialog(this, xl); + canvasSizeDialog = new TMCanvasSizeDialog(this, xl); + blockSizeDialog = new TMBlockSizeDialog(this, xl); + addBookmarkDialog = new TMAddToTreeDialog(this, "Add_To_Bookmarks_Dialog_Title", xl); + addPaletteDialog = new TMAddToTreeDialog(this, "Add_To_Palettes_Dialog_Title", xl); + organizeBookmarksDialog = new TMOrganizeTreeDialog(this, "Organize_Bookmarks_Dialog_Title", xl); + organizePalettesDialog = new TMOrganizeTreeDialog(this, "Organize_Palettes_Dialog_Title", xl); + newPaletteDialog = new TMNewPaletteDialog(this, xl); + paletteSizeDialog = new TMPaletteSizeDialog(this, xl); + importInternalPaletteDialog = new TMImportInternalPaletteDialog(this, xl); + + newPaletteDialog.setCodecs(colorcodecs); + importInternalPaletteDialog.setCodecs(colorcodecs); + + //Set up the GUI. + // main contentpane + JPanel pane = new JPanel(); + setContentPane(pane); + pane.setDoubleBuffered(true); + pane.setLayout(new BorderLayout()); + + // main toolbar + initToolBar(); + initNavBar(); + toolBarPane.setLayout(new FlowLayout(FlowLayout.LEFT)); + toolBarPane.add(toolBar); + toolBarPane.add(navBar); + pane.add(toolBarPane, BorderLayout.NORTH); + + // desktop + pane.add(new JScrollPane(desktop), BorderLayout.CENTER); + + // palette pane & statusbar + palettePane = new TMPalettePane(this); + statusBar.setBorder(new BevelBorder(BevelBorder.LOWERED)); + bottomPane.setLayout(new BorderLayout()); + bottomPane.add(palettePane, BorderLayout.CENTER); + bottomPane.add(statusBar, BorderLayout.SOUTH); + pane.add(bottomPane, BorderLayout.SOUTH); + + // tool palettes + initToolPalette(); + initSelectionToolBar(); + JPanel barPane = new JPanel(); + barPane.setLayout(new GridLayout(1, 2)); + barPane.add(selectionToolBar); + barPane.add(toolPalette); + toolPane.setLayout(new BorderLayout()); + toolPane.add(barPane, BorderLayout.NORTH); + pane.add(toolPane, BorderLayout.WEST); + + // menus + initMenuBar(); + setJMenuBar(menuBar); + buildReopenMenu(); + + initTileCodecUIStuff(); + buildColorCodecsMenu(); + initPaletteOpenChooser(); + + // Set up file save chooser. + fileSaveChooser.setAcceptAllFileFilterUsed(false); + fileSaveChooser.addChoosableFileFilter(allFilter); + fileSaveChooser.setFileFilter(allFilter); + + // Set up bitmap open chooser. + bitmapOpenChooser.setAcceptAllFileFilterUsed(false); + bitmapOpenChooser.addChoosableFileFilter(bmf.supported); + bitmapOpenChooser.addChoosableFileFilter(bmf.gif); + bitmapOpenChooser.addChoosableFileFilter(bmf.jpeg); + bitmapOpenChooser.addChoosableFileFilter(bmf.png); + bitmapOpenChooser.addChoosableFileFilter(bmf.bmp); + bitmapOpenChooser.addChoosableFileFilter(bmf.pcx); + bitmapOpenChooser.setFileFilter(bmf.supported); + + // Set up bitmap save chooser. + bitmapSaveChooser.setAcceptAllFileFilterUsed(false); + bitmapSaveChooser.addChoosableFileFilter(bmf.gif); + bitmapSaveChooser.addChoosableFileFilter(bmf.jpeg); + bitmapSaveChooser.addChoosableFileFilter(bmf.png); + bitmapSaveChooser.addChoosableFileFilter(bmf.bmp); + bitmapSaveChooser.addChoosableFileFilter(bmf.pcx); + bitmapSaveChooser.setFileFilter(bmf.png); + + setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + doExitCommand(); + } + public void windowActivated(WindowEvent e) { +// HACK to fix the GUI after running FCEU in fullscreen mode +// int state = getExtendedState(); +// setExtendedState(JFrame.ICONIFIED); +// setExtendedState(state); + } + }); + + // Center the frame + int inset = 128; + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + setBounds(inset, inset, + screenSize.width - inset*2, + screenSize.height-inset*2); + + //Make dragging faster: + desktop.putClientProperty("JDesktopPane.dragMode", "outline"); + + // MDI menus and such shouldn't be shown until file loaded. + disableMDIStuff(); + + toolBarPane.setVisible(viewToolBar); + + // Show and maximize. + setVisible(true); + setExtendedState(JFrame.MAXIMIZED_BOTH); + } + +/** +* +* Saves program settings to file. +* +**/ + + public void saveSettings() { + StringBuffer sb = new StringBuffer(); + sb.append("\n"); + sb.append("\n"); + sb.append("\n"); + + sb.append(makePropertyTag("locale", locale.toString())); + sb.append(makePropertyTag("viewStatusBar", ""+viewStatusBar)); + sb.append(makePropertyTag("viewToolBar", ""+viewToolBar)); + sb.append(makePropertyTag("maxRecentFiles", ""+maxRecentFiles)); + + File recentFile = null; + //To remember last path + for (int i=0; i\n"); + + // write to file + try { + FileWriter fw = new FileWriter(settingsFile); + fw.write(sb.toString()); + fw.close(); + } + catch (Exception e) { + JOptionPane.showMessageDialog(this, + xlate("Save_Settings_Error")+"\n"+e.getMessage(), + "Tile Molester", + JOptionPane.ERROR_MESSAGE); + } + } + +/** +* +* Makes a property tag with the given key and value. +* +**/ + + public String makePropertyTag(String key, String value) { + return " \n"; + } + +/** +* +* Loads program settings from file. +* +**/ + + public void loadSettings() { + Document doc = null; + try { + doc = XMLParser.parse(settingsFile); + } + catch (Exception e) { + JOptionPane.showMessageDialog(this, + xlate("Load_Settings_Error")+"\n"+e.getMessage(), + "Tile Molester", + JOptionPane.ERROR_MESSAGE); + } + if (doc == null) return; + + Element settings = doc.getDocumentElement(); + NodeList properties = settings.getElementsByTagName("property"); + // process all the properties + for (int i=0; i 0? + File resourceFile = TMFileResources.getResourceFileFor(img.getFile()); + try { + File res = new File("./resources"); + if (!res.exists()) { + res.mkdir(); + } + FileWriter fw = new FileWriter(resourceFile); + fw.write(img.getResources().toXML()); + fw.close(); + } + catch (Exception e) { + JOptionPane.showMessageDialog(this, + xlate("Save_Resources_Error")+"\n"+e.getMessage(), + "Tile Molester", + JOptionPane.ERROR_MESSAGE); + } + } + + public void saveBookmarks() { + // TODO + } + + public void savePalettes() { + // TODO + } + +/** +* +* Handles menu command "Close All". +* Does the same as "Close", only for all the current frames. +* +**/ + + public void doCloseAllCommand() { + JInternalFrame[] frames = desktop.getAllFrames(); + for (int i=0; i= 0; i--) { + if (!frames[i].isIcon()) { + frames[i].setLocation(xpos, ypos); + xpos += FRAME_OFFSET; + ypos += FRAME_OFFSET; + } + } + desktop.revalidate(); + } + +/** +* +* Handles menu command "Arrange Icons". +* +**/ + + public void doArrangeIconsCommand() { + JInternalFrame[] frames = desktop.getAllFrames(); + int xpos=0; + int ypos=0; + for (int i=0; i