Merge trunk to the cpcmode5 branch. This gets us a more recent grafx2 with the cpcmode5 drawing. Now to make this mode optional so users can still work in regular mode :)

git-svn-id: svn://pulkomandy.tk/GrafX2/branches/cpcmode5@1719 416bcca6-2ee7-4201-b75f-2eb2f807beb1
This commit is contained in:
Adrien Destugues 2011-02-13 21:49:31 +00:00
parent 4e60f5ad74
commit eba26aaa96
65 changed files with 8669 additions and 3286 deletions

View File

@ -1,5 +1,6 @@
# Grafx2 - The Ultimate 256-color bitmap paint program
#
# Copyright 2011 Pawel Góralski
# Copyright 2009 Per Olofsson
# Copyright 2008 Peter Gordon
# Copyright 2008-2010 Yves Rizoud
@ -25,6 +26,7 @@
bindir = $(exec_prefix)/bin
datarootdir = $(prefix)/share
datadir = $(datarootdir)
pixmapdir = $(datarootdir)/icons
# Compile with OPTIM=0 to disable gcc optimizations, to enable debug.
STRIP = strip
@ -42,8 +44,8 @@ ifdef COMSPEC
RMDIR = rmdir
CP = cp
BIN = ../bin/grafx2.exe
COPT = -W -Wall -Wdeclaration-after-statement -O$(OPTIM) -g -ggdb `sdl-config --cflags` $(TTFCOPT) $(JOYCOPT) $(LUACOPT) $(LAYERCOPT)
LOPT = `sdl-config --libs` -lSDL_image $(TTFLOPT) -lpng $(LUALOPT)
COPT = -W -Wall -Wdeclaration-after-statement -O$(OPTIM) -g -ggdb `sdl-config --cflags` $(TTFCOPT) $(JOYCOPT) $(VKEYCOPT) $(LUACOPT) $(LAYERCOPT)
LOPT = `sdl-config --libs` -lSDL_image $(TTFLOPT) -lpng14 $(LUALOPT)
LUALOPT = -llua
CC = gcc
OBJDIR = ../obj/win32
@ -52,7 +54,7 @@ ifdef COMSPEC
PLATFORMOBJ = $(OBJDIR)/winres.o
PLATFORM = win32
#some misc files we have to add to the release archive under windows.
PLATFORMFILES = bin/SDL.dll bin/SDL_image.dll bin/libpng13.dll bin/zlib1.dll $(TTFLIBS)
PLATFORMFILES = bin/SDL.dll bin/SDL_image.dll bin/libpng14-14.dll bin/zlib1.dll $(TTFLIBS)
ZIP = zip
else
@ -88,7 +90,7 @@ else
FWDIR = /Library/Frameworks
SDLCOPT = -arch i386 -I$(FWDIR)/SDL.framework/Headers -I$(FWDIR)/SDL_image.framework/Headers -I$(FWDIR)/SDL_ttf.framework/Headers -D_THREAD_SAFE
SDLLOPT = -arch i386 -L/usr/lib -framework SDL -framework SDL_image -framework SDL_ttf -framework Cocoa -framework Carbon -framework OpenGL
COPT = -D__macosx__ -D__linux__ -W -Wall -Wdeclaration-after-statement -O$(OPTIM) -std=c99 -c -g $(SDLCOPT) $(TTFCOPT) -I/usr/X11/include
COPT = -D_DARWIN_C_SOURCE -D__macosx__ -D__linux__ -W -Wall -Wdeclaration-after-statement -O$(OPTIM) -std=c99 -c -g $(SDLCOPT) $(TTFCOPT) -I/usr/X11/include
LOPT = $(SDLLOPT) -L/usr/X11/lib -R/usr/X11/lib -lpng
# Use gcc for compiling. Use ncc to build a callgraph and analyze the code.
CC = gcc
@ -152,8 +154,15 @@ else
RMDIR = rmdir
CP = cp
BIN = ../bin/grafx2
COPT = -W -Wall -c -g `sdl-config --cflags` $(TTFCOPT) -I/boot/common/include
LOPT = `sdl-config --libs` -lSDL_image -lpng -ljpeg -lz $(TTFLOPT)
ifeq ($(NOLUA),1)
LUACOPT =
LUALOPT =
else
LUACOPT = -D__ENABLE_LUA__
LUALOPT = -llua
endif
COPT = -W -Wall -c -g `sdl-config --cflags` $(TTFCOPT) -I/boot/common/include $(LUACOPT)
LOPT = `sdl-config --libs` -lSDL_image -lpng -ljpeg -lz $(TTFLOPT) -lfreetype -lbe $(LUALOPT)
CC = gcc
OBJDIR = ../obj/haiku
ZIP = zip
@ -197,19 +206,15 @@ else
CP = cp
ZIP = zip
PLATFORMFILES = gfx2.png
ifneq ($(ATARICROSS),1)
ifeq ($(NOLUA),1)
LUACOPT =
LUALOPT =
else
ifeq (`pkg-config --exists lua --print-errors`,"")
LUACOPT = `pkg-config lua --cflags`
LUALOPT = `pkg-config lua --libs`
else
LUACOPT = `pkg-config lua5.1 --cflags`
LUALOPT = `pkg-config lua5.1 --libs`
endif
LUACOPT = `pkg-config lua --cflags --silence-errors ||pkg-config lua5.1 --cflags --silence-errors ||pkg-config lua-5.1 --cflags`
LUALOPT = `pkg-config lua --libs --silence-errors ||pkg-config lua5.1 --libs --silence-errors ||pkg-config lua-5.1 --libs`
endif
endif
# These can only be used under linux and maybe freebsd. They allow to compile for the gp2x or to create a windows binary
ifdef WIN32CROSS
#cross compile a Win32 executable
@ -225,18 +230,41 @@ else
#cross compile an exec for the gp2x
CC = /opt/open2x/gcc-4.1.1-glibc-2.3.6/arm-open2x-linux/bin/arm-open2x-linux-gcc
BIN = ../bin/grafx2.gpe
COPT = -W -Wall -Wdeclaration-after-statement -pedantic -std=c99 -static -g -O$(OPTIM) -I/opt/open2x/gcc-4.1.1-glibc-2.3.6/include `/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin/sdl-config --cflags` $(TTFCOPT) -D__GP2X__ $(TTFCOPT) $(JOYCOPT) $(LUACOPT) $(LAYERCOPT)
COPT = -W -Wall -Wdeclaration-after-statement -pedantic -std=c99 -static -g -O$(OPTIM) -I/opt/open2x/gcc-4.1.1-glibc-2.3.6/include `/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin/sdl-config --cflags` $(TTFCOPT) -D__GP2X__ $(TTFCOPT) $(JOYCOPT) $(VKEYCOPT) $(LUACOPT) $(LAYERCOPT)
LOPT = -static -lSDL_image `/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin/sdl-config --static-libs` -ljpeg -lpng -lz -lm $(TTFLOPT) $(LUALOPT)
OBJDIR = ../obj/gp2x
NOTTF = 1
PLATFORM = gp2x
STRIP = /opt/open2x/gcc-4.1.1-glibc-2.3.6/arm-open2x-linux/bin/arm-open2x-linux-strip
JOYCOPT = -DUSE_JOYSTICK
else ifdef AROS32CROSS
#cross compile an Aros 32 bit executable
BIN = ../bin/grafx2
COPT = -Wall -g `i386-linux-aros-sdl-config --cflags` $(TTFCOPT)
LOPT = -lSDL_image `i386-linux-aros-sdl-config --libs` -lpng -ljpeg -lz $(TTFLOPT) -lfreetype2shared
CC = i386-aros-gcc
OBJDIR = ../obj/aros
STRIP = strip --strip-unneeded --remove-section .comment
PLATFORM = AROS
ZIP = lha
ZIPOPT = a
else ifdef ATARICROSS
#cross compile an exec for atari TOS/MiNT machine
CC = m68k-atari-mint-gcc
BIN = ../bin/grafx2.ttp
LUALOPT = -llua
OBJDIR = ../obj/m68k-atari-mint
PLATFORM = m68k-atari-mint
STRIP = m68k-atari-mint-strip -s
X11LOPT =
COPT = -W -Wall -m68020-60 -fomit-frame-pointer -pedantic -std=c99 -Wdeclaration-after-statement -D__MINT__ -DNO_INLINE_MATH -O$(OPTIM) -c -I$(prefix)/include `$(prefix)/bin/libpng12-config --cflags` `$(prefix)/bin/sdl-config --cflags` $() $(JOYCOPT) $(LAYERCOPT) $(LUACOPT)
LOPT = -static -m68020-60 -lSDL_image `$(prefix)/bin/sdl-config --libs` -L$(prefix)/lib -ltiff -ljpeg `$(prefix)/bin/libpng12-config --libs` -lz -lm $(TTFLOPT) -lfreetype $(LUALOPT) $(LAYERLOPT)
else
# Compiles a regular linux executable for the native platform
BIN = ../bin/grafx2
COPT = -W -Wall -Wdeclaration-after-statement -std=c99 -c -g `sdl-config --cflags` $(TTFCOPT) $(LUACOPT)
COPT = -W -Wall -Wdeclaration-after-statement -std=c99 -c -g `sdl-config --cflags` $(TTFCOPT) $(LUACOPT) $(JOYCOPT) $(VKEYCOPT) -O$(OPTIM)
LOPT = `sdl-config --libs` -lSDL_image $(TTFLOPT) -lpng $(LUALOPT) -lm
# Use gcc for compiling. Use ncc to build a callgraph and analyze the code.
CC = gcc
@ -258,6 +286,7 @@ endif
### BUILD SETTINGS are set according to vars set in the platform selection, the "overridable defaults", and environment variables set before launching make
#TrueType is optional: make NOTTF=1 to disable support and dependencies.
ifndef ($(ATARICROSS,1))
ifeq ($(NOTTF),1)
TTFCOPT = -DNOTTF=1
TTFLOPT =
@ -265,10 +294,23 @@ ifeq ($(NOTTF),1)
TTFLABEL = -nottf
else
TTFCOPT =
TTFLOPT = -L/usr/local/lib -lSDL_ttf $(X11LOPT)
TTFLOPT = -L$(prefix)/lib -lSDL_ttf $(X11LOPT)
TTFLIBS = bin/libfreetype-6.dll bin/SDL_ttf.dll
TTFLABEL =
endif
else
ifeq ($(NOTTF),1)
TTFCOPT = -DNOTTF=1
TTFLOPT =
TTFLIBS =
TTFLABEL = -nottf
else
TTFCOPT =
TTFLOPT = -L$(prefix)/lib -lSDL_ttf $(X11LOPT)
TTFLIBS =
TTFLABEL =
endif
endif
#Lua scripting is optional too
ifeq ($(NOLUA),1)
@ -289,6 +331,14 @@ ifeq ($(USE_JOYSTICK),1)
JOYCOPT = -DUSE_JOYSTICK
endif
#To enable virtual keyboard input (mouse-driven), make VIRT_KEY=1
#This is automatically enabled on some platforms, but this
#switch allows you to test the virtual keyboard on any other platform.
ifeq ($(VIRT_KEY),1)
VKEYCOPT = -DVIRT_KEY
endif
#To speed up rendering, can disable the layered editing
# with NOLAYERS=1
ifeq ($(NOLAYERS),1)
@ -304,11 +354,16 @@ endif
# This is the list of the objects we want to build. Dependancies are built by "make depend" automatically.
OBJ = $(OBJDIR)/main.o $(OBJDIR)/init.o $(OBJDIR)/graph.o $(OBJDIR)/sdlscreen.o $(OBJDIR)/misc.o $(OBJDIR)/special.o $(OBJDIR)/buttons.o $(OBJDIR)/palette.o $(OBJDIR)/help.o $(OBJDIR)/operatio.o $(OBJDIR)/pages.o $(OBJDIR)/loadsave.o $(OBJDIR)/readline.o $(OBJDIR)/engine.o $(OBJDIR)/filesel.o $(OBJDIR)/op_c.o $(OBJDIR)/readini.o $(OBJDIR)/saveini.o $(OBJDIR)/shade.o $(OBJDIR)/keyboard.o $(OBJDIR)/io.o $(OBJDIR)/version.o $(OBJDIR)/text.o $(OBJDIR)/SFont.o $(OBJDIR)/setup.o $(OBJDIR)/pxsimple.o $(OBJDIR)/pxtall.o $(OBJDIR)/pxwide.o $(OBJDIR)/pxdouble.o $(OBJDIR)/pxtriple.o $(OBJDIR)/pxtall2.o $(OBJDIR)/pxwide2.o $(OBJDIR)/pxquad.o $(OBJDIR)/windows.o $(OBJDIR)/brush.o $(OBJDIR)/realpath.o $(OBJDIR)/mountlist.o $(OBJDIR)/input.o $(OBJDIR)/hotkeys.o $(OBJDIR)/transform.o $(OBJDIR)/pversion.o $(OBJDIR)/factory.o $(PLATFORMOBJ) $(OBJDIR)/fileformats.o $(OBJDIR)/miscfileformats.o $(OBJDIR)/libraw2crtc.o $(OBJDIR)/brush_ops.o $(OBJDIR)/buttons_effects.o $(OBJDIR)/layers.o $(OBJDIR)/oldies.o
SKIN_FILES = ../share/grafx2/skins/skin_classic.png ../share/grafx2/skins/skin_modern.png ../share/grafx2/skins/skin_DPaint.png ../share/grafx2/skins/font_Classic.png ../share/grafx2/skins/font_Fun.png ../share/grafx2/skins/font_Fairlight.png ../share/grafx2/skins/font_Melon.png ../share/grafx2/skins/font_DPaint.png ../share/grafx2/skins/skin_scenish.png ../share/grafx2/skins/font_Seen.png
SKIN_FILES = ../share/grafx2/skins/skin_classic.png ../share/grafx2/skins/skin_modern.png ../share/grafx2/skins/skin_DPaint.png ../share/grafx2/skins/font_Classic.png ../share/grafx2/skins/font_Fun.png ../share/grafx2/skins/font_Fairlight.png ../share/grafx2/skins/font_Melon.png ../share/grafx2/skins/font_DPaint.png ../share/grafx2/skins/skin_scenish.png ../share/grafx2/skins/font_Seen.png ../share/grafx2/skins/skin_Aurora.png ../share/grafx2/skins/skin_Clax3.gif ../share/grafx2/skins/skin_Clax2.gif ../share/grafx2/skins/skin_Clax4.gif
SCRIPT_FILES1 = ../share/grafx2/scripts/bru_db_Amigaball.lua ../share/grafx2/scripts/bru_db_ColorSphere.lua ../share/grafx2/scripts/bru_db_FindAA.lua ../share/grafx2/scripts/bru_db_Fisheye.lua ../share/grafx2/scripts/bru_db_GrayscaleAvg.lua ../share/grafx2/scripts/bru_db_GrayscaleDesat.lua ../share/grafx2/scripts/bru_db_Halfsmooth.lua ../share/grafx2/scripts/bru_db_Mandelbrot.lua ../share/grafx2/scripts/bru_db_Waves.lua ../share/grafx2/scripts/pal_db_Desaturate.lua ../share/grafx2/scripts/pal_db_ExpandColors.lua ../share/grafx2/scripts/pal_db_FillColorCube.lua ../share/grafx2/scripts/pal_db_InvertedRGB.lua ../share/grafx2/scripts/pal_db_Set3bit.lua ../share/grafx2/scripts/pal_db_Set6bit.lua ../share/grafx2/scripts/pal_db_SetC64Palette.lua ../share/grafx2/scripts/pal_db_ShiftHue.lua ../share/grafx2/scripts/pic_db_Pic2isometric.lua ../share/grafx2/scripts/pic_db_Rainbow-Dark2Bright.lua ../share/grafx2/scripts/pic_db_SierpinskyCarpet.lua
SCRIPT_FILES2 = ../share/grafx2/scripts/pic_db_SierpinskyTriangle.lua ../share/grafx2/scripts/pic_ni_Colorspace12bit.lua ../share/grafx2/scripts/pic_ni_Colorspace15bit.lua ../share/grafx2/scripts/pic_ni_Colorspace18bit.lua ../share/grafx2/scripts/pic_ni_GlassGridFilter.lua ../share/grafx2/scripts/pic_ni_Grid8.lua ../share/grafx2/scripts/pic_ni_Grid8red.lua ../share/grafx2/scripts/pic_ni_GridIso.lua ../share/grafx2/scripts/pic_ni_PaletteX1.lua ../share/grafx2/scripts/pic_ni_PaletteX8.lua ../share/grafx2/scripts/scn_db_RemapImage2RGB.lua ../share/grafx2/scripts/scn_db_RemapImage2RGB_ed.lua ../share/grafx2/scripts/scn_db_RemapImageTo3bitPal.lua
SCRIPT_FILES1= SCRIPT_FILES1 SCRIPT_FILES2
SCRIPT_FILES2 = ../share/grafx2/scripts/pic_db_SierpinskyTriangle.lua ../share/grafx2/scripts/pic_ni_GlassGridFilter.lua ../share/grafx2/scripts/scn_db_RemapImage2RGB.lua ../share/grafx2/scripts/scn_db_RemapImage2RGB_ed.lua ../share/grafx2/scripts/scn_db_RemapImageTo3bitPal.lua
SCRIPT_FILES= $(SCRIPT_FILES1) $(SCRIPT_FILES2)
SCRIPTLIB_FILES = ../share/grafx2/scripts/libs/memory.lua
FONT_FILES = ../share/grafx2/fonts/8pxfont.png ../share/grafx2/fonts/Tuffy.ttf ../share/grafx2/fonts/PF_Arma_5__.png ../share/grafx2/fonts/PF_Easta_7_.png ../share/grafx2/fonts/PF_Easta_7__.png ../share/grafx2/fonts/PF_Ronda_7__.png ../share/grafx2/fonts/PF_Tempesta_5.png ../share/grafx2/fonts/PF_Tempesta_5_.png ../share/grafx2/fonts/PF_Tempesta_5__.png ../share/grafx2/fonts/PF_Tempesta_5___.png ../share/grafx2/fonts/PF_Tempesta_7.png ../share/grafx2/fonts/PF_Tempesta_7_.png ../share/grafx2/fonts/PF_Tempesta_7__.png ../share/grafx2/fonts/PF_Tempesta_7___.png ../share/grafx2/fonts/PF_Westa_7_.png ../share/grafx2/fonts/PF_Westa_7__.png
ifeq ($(PLATFORM),Darwin)
all : $(MACAPPEXE)
@ -316,11 +371,11 @@ $(MACAPPEXE) : $(BIN)
rm -rf Grafx2.app
mkdir -p Grafx2.app Grafx2.app/Contents Grafx2.app/Contents/Frameworks Grafx2.app/Contents/MacOS Grafx2.app/Contents/Resources
echo 'APPL????' > Grafx2.app/Contents/PkgInfo
cp Info.plist Grafx2.app/Contents
cp ../Info.plist Grafx2.app/Contents
cp -r English.lproj Grafx2.app/Contents/Resources
cp -r fonts Grafx2.app/Contents/Resources
cp -r skins Grafx2.app/Contents/Resources
cp -r gfx2def.ini Grafx2.app/Contents/Resources
cp -r ../share/grafx2/fonts Grafx2.app/Contents/Resources
cp -r ../share/grafx2/skins Grafx2.app/Contents/Resources
cp -r ../share/grafx2/gfx2def.ini Grafx2.app/Contents/Resources
cp -Rp $(FWDIR)/SDL.framework Grafx2.app/Contents/Frameworks
cp -Rp $(FWDIR)/SDL_image.framework Grafx2.app/Contents/Frameworks
cp -Rp $(FWDIR)/SDL_ttf.framework Grafx2.app/Contents/Frameworks
@ -341,9 +396,9 @@ ziprelease: version $(BIN) release
echo `sed "s/.*=\"\(.*\)\";/\1/" pversion.c`.`svnversion` | tr " :" "_-" | sed -e "s/\(wip\)\\./\1/I" > $(OBJDIR)/versiontag
tar cvzf "../src-`cat $(OBJDIR)/versiontag`.tgz" --strip=1 ../src/*.c ../src/*.h ../src/Makefile ../src/Makefile.dep ../src/gfx2.ico
cd .. && $(ZIP) $(ZIPOPT) "grafx2-`cat $(OBJDIR:../%=%)/versiontag`$(TTFLABEL)-$(PLATFORM).$(ZIP)" $(BIN:../%=%) share/grafx2/gfx2def.ini $(SCRIPT_FILES:../%=%) $(SKIN_FILES:../%=%) share/grafx2/gfx2.gif share/icons/grafx2.svg doc/README.txt doc/COMPILING.txt doc/gpl-2.0.txt share/grafx2/fonts/8pxfont.png doc/README-zlib1.txt doc/README-SDL.txt doc/README-SDL_image.txt doc/README-SDL_ttf.txt doc/README-lua.txt share/grafx2/fonts/Tuffy.ttf src-`cat $(OBJDIR:../%=%)/versiontag`.tgz $(PLATFORMFILES:../%=%)
cd .. && $(ZIP) $(ZIPOPT) "grafx2-`cat $(OBJDIR:../%=%)/versiontag`$(TTFLABEL)-$(PLATFORM).$(ZIP)" $(BIN:../%=%) share/grafx2/gfx2def.ini $(SCRIPT_FILES:../%=%) $(SCRIPTLIB_FILES:../%=%) $(SKIN_FILES:../%=%) share/grafx2/gfx2.gif share/icons/grafx2.svg doc/README.txt doc/COMPILING.txt doc/gpl-2.0.txt doc/PF_fonts.txt $(FONT_FILES:../%=%) doc/README-zlib1.txt doc/README-SDL.txt doc/README-SDL_image.txt doc/README-SDL_ttf.txt doc/README-lua.txt src-`cat $(OBJDIR:../%=%)/versiontag`.tgz $(PLATFORMFILES:../%=%)
$(DELCOMMAND) "../src-`cat $(OBJDIR)/versiontag`.tgz"
tar cvzf "../grafx2-`cat $(OBJDIR)/versiontag`$(TTFLABEL)-src.tgz" --strip=1 --transform 's,^,grafx2/,g' ../src/*.c ../src/*.h ../src/Makefile ../src/Makefile.dep ../share/grafx2/gfx2def.ini $(SCRIPT_FILES) $(SKIN_FILES) ../src/gfx2.ico ../share/grafx2/gfx2.gif ../share/icons/grafx2.svg ../doc/README.txt ../doc/COMPILING.txt ../doc/gpl-2.0.txt ../misc/unix/grafx2.1 ../misc/unix/grafx2.xpm ../misc/unix/grafx2.desktop ../share/grafx2/fonts/8pxfont.png ../share/grafx2/fonts/Tuffy.ttf
tar cvzf "../grafx2-`cat $(OBJDIR)/versiontag`$(TTFLABEL)-src.tgz" --strip=1 --transform 's,^,grafx2/,g' ../src/*.c ../src/*.h ../src/Makefile ../src/Makefile.dep ../share/grafx2/gfx2def.ini $(SCRIPT_FILES) $(SCRIPTLIB_FILES) $(SKIN_FILES) ../src/gfx2.ico ../share/grafx2/gfx2.gif ../share/icons/grafx2.svg ../doc/README.txt ../doc/COMPILING.txt ../doc/gpl-2.0.txt ../doc/PF_fonts.txt ../misc/unix/grafx2.1 ../misc/unix/grafx2.xpm ../misc/unix/grafx2.desktop $(FONT_FILES)
$(DELCOMMAND) "$(OBJDIR)/versiontag"
testsed :
@ -400,8 +455,9 @@ install : $(BIN)
test -d $(DESTDIR)$(datadir)/grafx2/fonts || $(MKDIR) $(DESTDIR)$(datadir)/grafx2/fonts
test -d $(DESTDIR)$(datadir)/grafx2/skins || $(MKDIR) $(DESTDIR)$(datadir)/grafx2/skins
test -d $(DESTDIR)$(datadir)/grafx2/scripts || $(MKDIR) $(DESTDIR)$(datadir)/grafx2/scripts
test -d $(DESTDIR)$(datadir)/grafx2/scripts/libs || $(MKDIR) $(DESTDIR)$(datadir)/grafx2/scripts/libs
test -d $(DESTDIR)$(datadir)/applications || $(MKDIR) $(DESTDIR)$(datadir)/applications
test -d $(DESTDIR)$(datadir)/icons || $(MKDIR) $(DESTDIR)$(datadir)/icons
test -d $(DESTDIR)$(pixmapdir) || $(MKDIR) $(DESTDIR)$(pixmapdir)
# Copy files
$(CP) $(BIN) $(DESTDIR)$(bindir)
$(CP) ../share/grafx2/gfx2def.ini $(DESTDIR)$(datadir)/grafx2/
@ -409,10 +465,11 @@ install : $(BIN)
$(CP) ../share/grafx2/fonts/* $(DESTDIR)$(datadir)/grafx2/fonts/
$(CP) $(SKIN_FILES) $(DESTDIR)$(datadir)/grafx2/skins/
$(CP) $(SCRIPT_FILES) $(DESTDIR)$(datadir)/grafx2/scripts/
$(CP) $(SCRIPTLIB_FILES) $(DESTDIR)$(datadir)/grafx2/scripts/libs/
# Icon and desktop file for debian
$(CP) ../misc/unix/grafx2.desktop $(DESTDIR)$(datadir)/applications/
$(CP) ../misc/unix/grafx2.xpm $(DESTDIR)$(datadir)/icons/
$(CP) ../share/icons/grafx2.svg $(DESTDIR)$(datadir)/icons/
$(CP) ../misc/unix/grafx2.xpm $(DESTDIR)$(pixmapdir)
$(CP) ../share/icons/grafx2.svg $(DESTDIR)$(pixmapdir)
@echo Install complete
# Linux uninstallation of the program
@ -424,13 +481,15 @@ uninstall :
$(if $(wildcard $(DESTDIR)$(datadir)/grafx2/fonts),,$(RMDIR) $(DESTDIR)$(datadir)/grafx2/fonts)
$(DELCOMMAND) $(SKIN_FILES:../share%=$(DESTDIR)$(datadir)%)
$(if $(wildcard $(DESTDIR)$(datadir)/grafx2/skins),,$(RMDIR) $(DESTDIR)$(datadir)/grafx2/skins)
$(DELCOMMAND) $(SCRIPTLIB_FILES:../share%=$(DESTDIR)$(datadir)%)
$(if $(wildcard $(DESTDIR)$(datadir)/grafx2/scripts/libs),,$(RMDIR) $(DESTDIR)$(datadir)/grafx2/scripts/libs)
$(DELCOMMAND) $(SCRIPT_FILES:../share%=$(DESTDIR)$(datadir)%)
$(if $(wildcard $(DESTDIR)$(datadir)/grafx2/scripts),,$(RMDIR) $(DESTDIR)$(datadir)/grafx2/scripts)
$(if $(wildcard $(DESTDIR)$(datadir)/grafx2),,$(RMDIR) $(DESTDIR)$(datadir)/grafx2)
# Icon and desktop file for debian
$(DELCOMMAND) $(DESTDIR)$(datadir)/applications/grafx2.desktop
$(DELCOMMAND) $(DESTDIR)$(datadir)/icons/grafx2.xpm
$(DELCOMMAND) $(DESTDIR)$(datadir)/icons/grafx2.svg
$(DELCOMMAND) $(DESTDIR)$(pixmapdir)/grafx2.xpm
$(DELCOMMAND) $(DESTDIR)$(pixmapdir)/grafx2.svg
@echo Uninstall complete
endif

View File

@ -1,3 +1,4 @@
$(OBJDIR)/SFont.o: SFont.c SFont.h
$(OBJDIR)/brush.o: brush.c global.h struct.h const.h graph.h misc.h errors.h \
windows.h sdlscreen.h brush.h
$(OBJDIR)/brush_ops.o: brush_ops.c brush.h struct.h const.h buttons.h engine.h \
@ -5,12 +6,13 @@ $(OBJDIR)/brush_ops.o: brush_ops.c brush.h struct.h const.h buttons.h engine.h \
$(OBJDIR)/buttons.o: buttons.c const.h struct.h global.h misc.h graph.h engine.h \
readline.h filesel.h loadsave.h init.h buttons.h operatio.h pages.h \
palette.h errors.h readini.h saveini.h shade.h io.h help.h text.h \
sdlscreen.h windows.h brush.h input.h special.h
sdlscreen.h windows.h brush.h input.h special.h setup.h
$(OBJDIR)/buttons_effects.o: buttons_effects.c buttons.h struct.h const.h engine.h \
global.h graph.h help.h input.h misc.h readline.h sdlscreen.h windows.h
global.h graph.h help.h input.h misc.h readline.h sdlscreen.h windows.h \
brush.h
$(OBJDIR)/engine.o: engine.c const.h struct.h global.h graph.h misc.h special.h \
buttons.h operatio.h shade.h errors.h sdlscreen.h windows.h brush.h \
input.h engine.h pages.h layers.h
input.h engine.h pages.h layers.h factory.h loadsave.h io.h
$(OBJDIR)/factory.o: factory.c brush.h struct.h const.h buttons.h engine.h errors.h \
filesel.h loadsave.h global.h graph.h io.h misc.h pages.h readline.h \
sdlscreen.h windows.h palette.h input.h help.h
@ -21,7 +23,8 @@ $(OBJDIR)/filesel.o: filesel.c const.h struct.h global.h misc.h errors.h io.h \
help.h filesel.h
$(OBJDIR)/graph.o: graph.c global.h struct.h const.h engine.h buttons.h pages.h \
errors.h sdlscreen.h graph.h misc.h pxsimple.h pxtall.h pxwide.h \
pxdouble.h pxtriple.h pxwide2.h pxtall2.h pxquad.h windows.h input.h
pxdouble.h pxtriple.h pxwide2.h pxtall2.h pxquad.h windows.h input.h \
brush.h
$(OBJDIR)/help.o: help.c const.h struct.h global.h misc.h engine.h helpfile.h \
help.h sdlscreen.h text.h keyboard.h windows.h input.h hotkeys.h \
errors.h pages.h
@ -29,9 +32,9 @@ $(OBJDIR)/hotkeys.o: hotkeys.c struct.h const.h global.h hotkeys.h
$(OBJDIR)/init.o: init.c buttons.h struct.h const.h errors.h global.h graph.h \
init.h io.h factory.h help.h hotkeys.h keyboard.h loadsave.h misc.h \
mountlist.h operatio.h palette.h sdlscreen.h setup.h transform.h \
windows.h layers.h
windows.h layers.h special.h
$(OBJDIR)/input.o: input.c global.h struct.h const.h keyboard.h sdlscreen.h \
windows.h errors.h misc.h input.h
windows.h errors.h misc.h buttons.h input.h loadsave.h
$(OBJDIR)/io.o: io.c struct.h const.h io.h realpath.h
$(OBJDIR)/keyboard.o: keyboard.c global.h struct.h const.h keyboard.h
$(OBJDIR)/layers.o: layers.c const.h struct.h global.h windows.h engine.h pages.h \
@ -39,18 +42,20 @@ $(OBJDIR)/layers.o: layers.c const.h struct.h global.h windows.h engine.h pages.
$(OBJDIR)/libraw2crtc.o: libraw2crtc.c const.h global.h struct.h loadsave.h
$(OBJDIR)/loadsave.o: loadsave.c buttons.h struct.h const.h errors.h global.h io.h \
loadsave.h misc.h graph.h op_c.h pages.h palette.h sdlscreen.h windows.h \
engine.h
engine.h brush.h setup.h
$(OBJDIR)/main.o: main.c const.h struct.h global.h graph.h misc.h init.h buttons.h \
engine.h pages.h loadsave.h sdlscreen.h errors.h readini.h saveini.h \
io.h text.h setup.h windows.h brush.h palette.h realpath.h
io.h text.h setup.h windows.h brush.h palette.h realpath.h input.h
$(OBJDIR)/misc.o: misc.c struct.h const.h sdlscreen.h global.h errors.h buttons.h \
engine.h misc.h keyboard.h windows.h palette.h input.h graph.h pages.h
$(OBJDIR)/miscfileformats.o: miscfileformats.c engine.h struct.h const.h errors.h \
global.h io.h libraw2crtc.h loadsave.h misc.h sdlscreen.h windows.h
$(OBJDIR)/mountlist.o: mountlist.c mountlist.h
$(OBJDIR)/op_c.o: op_c.c op_c.h struct.h const.h errors.h
$(OBJDIR)/mountlist.o: mountlist.c
$(OBJDIR)/op_c.o: op_c.c op_c.h struct.h const.h errors.h global.h engine.h \
windows.h
$(OBJDIR)/operatio.o: operatio.c const.h struct.h global.h misc.h engine.h graph.h \
operatio.h buttons.h pages.h errors.h sdlscreen.h brush.h windows.h
operatio.h buttons.h pages.h errors.h sdlscreen.h brush.h windows.h \
input.h
$(OBJDIR)/pages.o: pages.c global.h struct.h const.h pages.h errors.h loadsave.h \
misc.h windows.h
$(OBJDIR)/palette.o: palette.c const.h struct.h global.h misc.h engine.h readline.h \
@ -63,34 +68,35 @@ $(OBJDIR)/pxquad.o: pxquad.c global.h struct.h const.h sdlscreen.h misc.h graph.
pxquad.h
$(OBJDIR)/pxsimple.o: pxsimple.c global.h struct.h const.h sdlscreen.h misc.h \
graph.h pxsimple.h
$(OBJDIR)/pxtall2.o: pxtall2.c global.h struct.h const.h sdlscreen.h misc.h graph.h \
pxtall2.h
$(OBJDIR)/pxtall.o: pxtall.c global.h struct.h const.h sdlscreen.h misc.h graph.h \
pxtall.h pxsimple.h
$(OBJDIR)/pxtall2.o: pxtall2.c global.h struct.h const.h sdlscreen.h misc.h graph.h \
pxtall2.h
$(OBJDIR)/pxtriple.o: pxtriple.c global.h struct.h const.h sdlscreen.h misc.h \
graph.h pxtriple.h
$(OBJDIR)/pxwide2.o: pxwide2.c global.h struct.h const.h sdlscreen.h misc.h graph.h \
pxwide2.h
$(OBJDIR)/pxwide.o: pxwide.c global.h struct.h const.h sdlscreen.h misc.h graph.h \
pxwide.h
$(OBJDIR)/readini.o: readini.c const.h errors.h global.h struct.h misc.h readini.h
$(OBJDIR)/pxwide2.o: pxwide2.c global.h struct.h const.h sdlscreen.h misc.h graph.h \
pxwide2.h
$(OBJDIR)/readini.o: readini.c const.h errors.h global.h struct.h misc.h readini.h \
setup.h
$(OBJDIR)/readline.o: readline.c const.h struct.h global.h misc.h errors.h \
sdlscreen.h readline.h windows.h input.h
$(OBJDIR)/realpath.o: realpath.c
$(OBJDIR)/saveini.o: saveini.c const.h global.h struct.h readini.h io.h errors.h \
misc.h saveini.h
misc.h saveini.h setup.h
$(OBJDIR)/sdlscreen.o: sdlscreen.c global.h struct.h const.h sdlscreen.h errors.h \
misc.h
$(OBJDIR)/setup.o: setup.c struct.h const.h io.h setup.h
$(OBJDIR)/SFont.o: SFont.c SFont.h
$(OBJDIR)/shade.o: shade.c global.h struct.h const.h graph.h engine.h errors.h \
misc.h readline.h help.h sdlscreen.h windows.h input.h shade.h
$(OBJDIR)/special.o: special.c const.h struct.h global.h graph.h engine.h windows.h \
special.h pages.h misc.h buttons.h
$(OBJDIR)/text.o: text.c SFont.h struct.h const.h global.h sdlscreen.h io.h \
errors.h
errors.h windows.h misc.h setup.h
$(OBJDIR)/tiles.o: tiles.c
$(OBJDIR)/transform.o: transform.c global.h struct.h const.h transform.h engine.h \
sdlscreen.h windows.h input.h help.h misc.h readline.h buttons.h pages.h
$(OBJDIR)/version.o: version.c
$(OBJDIR)/windows.o: windows.c windows.h struct.h const.h engine.h errors.h \
global.h graph.h input.h misc.h readline.h sdlscreen.h
global.h graph.h input.h misc.h op_c.h readline.h sdlscreen.h palette.h

View File

@ -69,7 +69,7 @@ static Uint32 GetPixel(SDL_Surface *Surface, Sint32 X, Sint32 Y)
SFont_Font* SFont_InitFont(SDL_Surface* Surface)
{
int x = 0, i = 0;
int x = 0, i = 33;
Uint32 pixel;
SFont_Font* Font;
Uint32 pink;
@ -78,21 +78,42 @@ SFont_Font* SFont_InitFont(SDL_Surface* Surface)
return NULL;
Font = (SFont_Font *) malloc(sizeof(SFont_Font));
memset(Font, 0, sizeof(SFont_Font));
Font->Surface = Surface;
SDL_LockSurface(Surface);
pink = SDL_MapRGB(Surface->format, 255, 0, 255);
pink = GetPixel(Surface, 0, 0);
while (x < Surface->w) {
if (GetPixel(Surface, x, 0) == pink) {
Font->CharPos[i++]=x;
while((x < Surface->w) && (GetPixel(Surface, x, 0)== pink))
if (GetPixel(Surface, x, 0) != pink) {
Font->CharBegin[i]=x;
while((x < Surface->w) && (GetPixel(Surface, x, 0)!= pink))
x++;
Font->CharPos[i++]=x;
Font->CharWidth[i]=x-Font->CharBegin[i];
i++;
}
x++;
}
Font->MaxPos = x-1;
// Create lowercase characters, if not present
for (i=0; i <26; i++)
{
if (Font->CharWidth['a'+i]==0)
{
Font->CharBegin['a'+i]=Font->CharBegin['A'+i];
Font->CharWidth['a'+i]=Font->CharWidth['A'+i];
}
}
// Determine space width.
// This strange format doesn't allow font designer to write explicit
// space as a character.
// Rule: A space should be as large as the character " if available,
// or 'a' if it's not.
Font->Space = Font->CharWidth[(int)'"'];
if (Font->Space<2)
Font->Space = Font->CharWidth[(int)'a'];
pixel = GetPixel(Surface, 0, Surface->h-1);
SDL_UnlockSurface(Surface);
@ -111,7 +132,6 @@ void SFont_Write(SDL_Surface *Surface, const SFont_Font *Font,
int x, int y, const char *text)
{
const char* c;
int charoffset;
SDL_Rect srcrect, dstrect;
if(text == NULL)
@ -123,42 +143,39 @@ void SFont_Write(SDL_Surface *Surface, const SFont_Font *Font,
srcrect.h = dstrect.h = Font->Surface->h - 1;
for(c = text; *c != '\0' && x <= Surface->w ; c++) {
charoffset = ((int) (*c - 33)) * 2 + 1;
// skip spaces and nonprintable characters
if (*c == ' ' || charoffset < 0 || charoffset > Font->MaxPos) {
x += Font->CharPos[2]-Font->CharPos[1];
if (*c == ' ' || Font->CharWidth[(int)*c]==0) {
x += Font->Space;
continue;
}
srcrect.w = Font->CharPos[charoffset+2] - Font->CharPos[charoffset];
srcrect.w = Font->CharWidth[(int)*c];
dstrect.w = srcrect.w;
srcrect.x = Font->CharPos[charoffset];
srcrect.x = Font->CharBegin[(int)*c];
dstrect.x = x;
SDL_BlitSurface(Font->Surface, &srcrect, Surface, &dstrect);
x += Font->CharPos[charoffset+1] - Font->CharPos[charoffset];
x += Font->CharWidth[(int)*c];
}
}
int SFont_TextWidth(const SFont_Font *Font, const char *text)
{
const char* c;
int charoffset=0;
int width = 0;
if(text == NULL)
return 0;
for(c = text; *c != '\0'; c++) {
charoffset = ((int) *c - 33) * 2 + 1;
// skip spaces and nonprintable characters
if (*c == ' ' || charoffset < 0 || charoffset > Font->MaxPos) {
width += Font->CharPos[2]-Font->CharPos[1];
if (*c == ' ' || Font->CharWidth[(int)*c]==0) {
width += Font->Space;
continue;
}
width += Font->CharPos[charoffset+1] - Font->CharPos[charoffset];
width += Font->CharWidth[(int)*c];
}
return width;

View File

@ -56,8 +56,9 @@ extern "C" {
/// and call InitFont( YourFont );
typedef struct {
SDL_Surface *Surface;
int CharPos[512];
int MaxPos;
int CharBegin[256];
int CharWidth[256];
int Space;
} SFont_Font;
///

View File

@ -587,66 +587,97 @@ void Display_paintbrush(short x,short y,byte color,byte is_preview)
}
}
///
/// Changes the Brush size, discarding its previous content.
/// @return 0 OK, 1 Failed
byte Realloc_brush(word new_brush_width, word new_brush_height)
/// @return 0 on success, non-zero on failure (memory?).
/// @param new_brush: Optionally, you can provide an already allocated new
/// brush - otherwise, this function performs the allocation.
/// @param old_brush: If the caller passes NULL, this function will free the old
/// pixel data. If the caller provides the address of a (free) byte
/// pointer, the function will make it point to the original pixel data,
/// in this case it will be the caller's responsibility to free() it
/// (after transferring pixels to Brush, usually).
byte Realloc_brush(word new_brush_width, word new_brush_height, byte *new_brush, byte **old_brush)
{
byte return_code=0;
byte *new_smear_brush;
byte *new_brush_remapped;
word new_smear_brush_width;
word new_smear_brush_height;
byte new_brush_is_provided;
new_brush_is_provided = (new_brush!=NULL);
if (!new_brush_is_provided)
{
new_brush=(byte *)malloc(((long)new_brush_height)*new_brush_width);
if (new_brush == NULL)
{
Error(0);
if (old_brush)
*old_brush=NULL;
return 1;
}
}
new_smear_brush_width=(new_brush_width>MAX_PAINTBRUSH_SIZE)?new_brush_width:MAX_PAINTBRUSH_SIZE;
new_smear_brush_height=(new_brush_height>MAX_PAINTBRUSH_SIZE)?new_brush_height:MAX_PAINTBRUSH_SIZE;
new_smear_brush=NULL;
if ( (((long)Smear_brush_height)*Smear_brush_width) !=
(((long)new_smear_brush_width)*new_smear_brush_height) )
{
new_smear_brush=(byte *)malloc(((long)new_smear_brush_height)*new_smear_brush_width);
if (new_smear_brush == NULL)
{
Error(0);
if (old_brush)
*old_brush=NULL;
if (!new_brush_is_provided)
free(new_brush);
return 2;
}
}
new_brush_remapped=NULL;
if ( (((long)Brush_height)*Brush_width) !=
(((long)new_brush_height)*new_brush_width) )
{
free(Brush);
Brush=(byte *)malloc(((long)new_brush_height)*new_brush_width);
if (Brush == NULL)
new_brush_remapped=(byte *)malloc(((long)new_brush_height)*new_brush_width);
if (new_brush_remapped == NULL)
{
Error(0);
return_code=1;
Brush=(byte *)malloc(1*1);
if(Brush == NULL)
{
Error(ERROR_MEMORY);
exit(ERROR_MEMORY);
}
new_brush_height=new_brush_width=1;
*Brush=Fore_color;
free(new_smear_brush);
if (old_brush)
*old_brush=NULL;
if (!new_brush_is_provided)
free(new_brush);
return 3;
}
}
// All allocations successful: can replace globals
Brush_width=new_brush_width;
Brush_height=new_brush_height;
Brush_original_back_color=Back_color;
free(Smear_brush);
Smear_brush_width=(Brush_width>MAX_PAINTBRUSH_SIZE)?Brush_width:MAX_PAINTBRUSH_SIZE;
Smear_brush_height=(Brush_height>MAX_PAINTBRUSH_SIZE)?Brush_height:MAX_PAINTBRUSH_SIZE;
Smear_brush=(byte *)malloc(((long)Smear_brush_height)*Smear_brush_width);
if (Smear_brush == NULL) // Failed to allocate the smear brush
if (new_smear_brush)
{
Error(0);
return_code=1;
free(Brush);
Brush=(byte *)malloc(1*1);
if(Brush == NULL)
{
Error(ERROR_MEMORY);
exit(ERROR_MEMORY);
}
Brush_height=1;
Brush_width=1;
Smear_brush=(byte *)malloc(MAX_PAINTBRUSH_SIZE*MAX_PAINTBRUSH_SIZE);
if(Smear_brush == NULL)
{
Error(ERROR_MEMORY);
exit(ERROR_MEMORY);
}
Smear_brush_height=MAX_PAINTBRUSH_SIZE;
Smear_brush_width=MAX_PAINTBRUSH_SIZE;
free(Smear_brush);
Smear_brush=new_smear_brush;
}
return return_code;
Smear_brush_width=new_smear_brush_width;
Smear_brush_height=new_smear_brush_height;
// Save or free the old brush pixels
if (old_brush)
*old_brush=Brush_original_pixels;
else
free(old_brush);
Brush_original_pixels=new_brush;
// Assign new brush
if (new_brush_remapped)
{
free(Brush);
Brush=new_brush_remapped;
}
return 0;
}
@ -828,7 +859,7 @@ void Capture_brush(short start_x,short start_y,short end_x,short end_y,short cle
if (start_y+new_brush_height>Main_image_height)
new_brush_height=Main_image_height-start_y;
if (Realloc_brush(new_brush_width, new_brush_height) != 0)
if (Realloc_brush(new_brush_width, new_brush_height, NULL, NULL))
return; // Unable to allocate the new brush, keep the old one.
Copy_image_to_brush(start_x,start_y,Brush_width,Brush_height,Main_image_width);
@ -843,6 +874,10 @@ void Capture_brush(short start_x,short start_y,short end_x,short end_y,short cle
}
Update_part_of_screen(start_x,start_y,Brush_width,Brush_height);
}
// Grab palette
memcpy(Brush_original_palette, Main_palette,sizeof(T_Palette));
// Remap (no change)
Remap_brush();
// On centre la prise sur la brosse
Brush_offset_X=(Brush_width>>1);
@ -851,32 +886,25 @@ void Capture_brush(short start_x,short start_y,short end_x,short end_y,short cle
}
void Rotate_90_deg()
void Rotate_90_deg(void)
{
short temp;
byte * new_brush;
new_brush=(byte *)malloc(((size_t)Brush_height)*Brush_width);
if (new_brush)
byte * old_brush;
if (Realloc_brush(Brush_height, Brush_width, NULL, &old_brush))
{
Rotate_90_deg_lowlevel(Brush,new_brush,Brush_width,Brush_height);
free(Brush);
Brush=new_brush;
temp=Brush_width;
Brush_width=Brush_height;
Brush_height=temp;
temp=Smear_brush_width;
Smear_brush_width=Smear_brush_height;
Smear_brush_height=temp;
// On centre la prise sur la brosse
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
}
else
Error(0);
return;
}
Rotate_90_deg_lowlevel(old_brush,Brush_original_pixels,Brush_height,Brush_width);
free(old_brush);
// Remap according to the last used remap table
Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
// On centre la prise sur la brosse
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
}
@ -884,34 +912,45 @@ void Remap_brush(void)
{
short x_pos; // Variable de balayage de la brosse
short y_pos; // Variable de balayage de la brosse
byte used[256]; // Tableau de booléens "La couleur est utilisée"
int color;
// On commence par initialiser le tableau de booléens à faux
for (color=0;color<=255;color++)
used[color]=0;
Brush_colormap[color]=0;
// On calcule la table d'utilisation des couleurs
for (y_pos=0;y_pos<Brush_height;y_pos++)
for (x_pos=0;x_pos<Brush_width;x_pos++)
used[Read_pixel_from_brush(x_pos,y_pos)]=1;
Brush_colormap[*(Brush_original_pixels + y_pos * Brush_width + x_pos)]=1;
// On n'est pas censé remapper la couleur de transparence, sinon la brosse
// changera de forme, donc on dit pour l'instant qu'elle n'est pas utilisée
// ainsi on ne s'embêtera pas à la recalculer
used[Back_color]=0;
Brush_colormap[Back_color]=0;
// On va maintenant se servir de la table "used" comme table de
// On va maintenant se servir de la table comme table de
// conversion: pour chaque indice, la table donne une couleur de
// remplacement.
// Note : Seules les couleurs utilisées on besoin d'êtres recalculées: les
// autres ne seront jamais consultées dans la nouvelle table de
// conversion puisque elles n'existent pas dans la brosse, donc elles
// ne seront pas utilisées par Remap_brush_LOWLEVEL.
// ne seront pas utilisées par Remap_general_lowlevel.
for (color=0;color<=255;color++)
if (used[color] != 0)
used[color]=Best_color(Spare_palette[color].R,Spare_palette[color].G,Spare_palette[color].B);
if (Brush_colormap[color] != 0)
{
byte r,g,b;
r=Brush_original_palette[color].R;
g=Brush_original_palette[color].G;
b=Brush_original_palette[color].B;
// When remapping to same palette, ensure we keep same color index
if (r==Main_palette[color].R && g==Main_palette[color].G && b==Main_palette[color].B)
Brush_colormap[color]=color;
else
// Usual method: closest by r g b
Brush_colormap[color]=Best_color_perceptual(r,g,b);
}
// Il reste une couleur non calculée dans la table qu'il faut mettre à
// jour: c'est la couleur de fond. On l'avait inhibée pour éviter son
@ -919,13 +958,13 @@ void Remap_brush(void)
// la brosse, on va mettre dans la table une relation d'équivalence entre
// les deux palettes: comme on ne veut pas que la couleur soit remplacée,
// on va dire qu'on veut qu'elle soit remplacée par la couleur en question.
used[Back_color]=Back_color;
Brush_colormap[Back_color]=Back_color;
// Maintenant qu'on a une super table de conversion qui n'a que le nom
// qui craint un peu, on peut faire l'échange dans la brosse de toutes les
// teintes.
Remap_general_lowlevel(used,Brush,Brush_width,Brush_height,Brush_width);
//Remap_brush_LOWLEVEL(used);
Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
}
@ -934,104 +973,97 @@ void Outline_brush(void)
{
long /*Pos,*/x_pos,y_pos;
byte state;
byte * new_brush;
byte * temp;
word width;
word height;
byte * old_brush;
word old_width;
word old_height;
int i;
width=Brush_width+2;
height=Brush_height+2;
new_brush=(byte *)malloc(((long)width)*height);
if (new_brush)
old_width=Brush_width;
old_height=Brush_height;
SWAP_PBYTES(Brush, Brush_original_pixels);
if(Realloc_brush(Brush_width+2, Brush_height+2, NULL, &old_brush))
{
// On remplit la bordure ajoutée par la Backcolor
memset(new_brush,Back_color,((long)width)*height);
Error(0);
SWAP_PBYTES(Brush, Brush_original_pixels);
return;
}
// On copie la brosse courante dans la nouvelle
Copy_part_of_image_to_another(Brush, // source
0, 0, Brush_width, Brush_height, Brush_width,
new_brush, // Destination
1, 1, width);
// On remplit la bordure ajoutée par la Backcolor
memset(Brush,Back_color,((long)Brush_width)*Brush_height);
// On intervertit la nouvelle et l'ancienne brosse:
temp=Brush;
Brush=new_brush;
Brush_width+=2;
Brush_height+=2;
width-=2;
height-=2;
// On copie la brosse courante dans la nouvelle
Copy_part_of_image_to_another(old_brush, // source
0, 0, old_width, old_height, old_width,
Brush, // Destination
1, 1, Brush_width);
// Si on "outline" avec une couleur différente de la Back_color on y va!
if (Fore_color!=Back_color)
// Si on "outline" avec une couleur différente de la Back_color on y va!
if (Fore_color!=Back_color)
{
// 1er balayage (horizontal)
for (y_pos=1; y_pos<Brush_height-1; y_pos++)
{
// 1er balayage (horizontal)
for (y_pos=1; y_pos<Brush_height-1; y_pos++)
{
state=0;
for (x_pos=1; x_pos<Brush_width-1; x_pos++)
{
if (temp[((y_pos-1)*width)+x_pos-1]==Back_color)
{
if (state != 0)
{
Pixel_in_brush(x_pos,y_pos,Fore_color);
state=0;
}
}
else if (state == 0)
{
Pixel_in_brush(x_pos-1,y_pos,Fore_color);
state=1;
}
}
// Cas du dernier pixel à droite de la ligne
if (state != 0)
Pixel_in_brush(x_pos,y_pos,Fore_color);
}
// 2ème balayage (vertical)
state=0;
for (x_pos=1; x_pos<Brush_width-1; x_pos++)
{
state=0;
for (y_pos=1; y_pos<Brush_height-1; y_pos++)
if (old_brush[((y_pos-1)*old_width)+x_pos-1]==Back_color)
{
if (temp[((y_pos-1)*width)+x_pos-1]==Back_color)
if (state != 0)
{
if (state != 0)
{
Pixel_in_brush(x_pos,y_pos,Fore_color);
state=0;
}
}
else if (state == 0)
{
Pixel_in_brush(x_pos,y_pos-1,Fore_color);
state=1;
Pixel_in_brush(x_pos,y_pos,Fore_color);
state=0;
}
}
// Cas du dernier pixel en bas de la colonne
if (state != 0)
Pixel_in_brush(x_pos,y_pos,Fore_color);
else if (state == 0)
{
Pixel_in_brush(x_pos-1,y_pos,Fore_color);
state=1;
}
}
// Cas du dernier pixel à droite de la ligne
if (state != 0)
Pixel_in_brush(x_pos,y_pos,Fore_color);
}
// On recentre la prise sur la brosse
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
free(temp); // Libération de l'ancienne brosse
temp = NULL;
// Réallocation d'un buffer de Smear
free(Smear_brush);
Smear_brush_width=(Brush_width>MAX_PAINTBRUSH_SIZE)?Brush_width:MAX_PAINTBRUSH_SIZE;
Smear_brush_height=(Brush_height>MAX_PAINTBRUSH_SIZE)?Brush_height:MAX_PAINTBRUSH_SIZE;
Smear_brush=(byte *)malloc(((long)Smear_brush_width)*Smear_brush_height);
// 2ème balayage (vertical)
for (x_pos=1; x_pos<Brush_width-1; x_pos++)
{
state=0;
for (y_pos=1; y_pos<Brush_height-1; y_pos++)
{
if (old_brush[((y_pos-1)*old_width)+x_pos-1]==Back_color)
{
if (state != 0)
{
Pixel_in_brush(x_pos,y_pos,Fore_color);
state=0;
}
}
else if (state == 0)
{
Pixel_in_brush(x_pos,y_pos-1,Fore_color);
state=1;
}
}
// Cas du dernier pixel en bas de la colonne
if (state != 0)
Pixel_in_brush(x_pos,y_pos,Fore_color);
}
}
else
Error(0); // Pas assez de mémoire!
// Adopt the current palette.
memcpy(Brush_original_palette, Main_palette,sizeof(T_Palette));
memcpy(Brush_original_pixels, Brush, (long)Brush_width*Brush_height);
for (i=0; i<256; i++)
Brush_colormap[i]=i;
//--
// On recentre la prise sur la brosse
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
free(old_brush); // Libération de l'ancienne brosse
}
@ -1039,112 +1071,105 @@ void Nibble_brush(void)
{
long x_pos,y_pos;
byte state;
byte * new_brush;
byte * temp;
word width;
word height;
byte * old_brush;
word old_width;
word old_height;
int i;
if ( (Brush_width>2) && (Brush_height>2) )
{
width=Brush_width-2;
height=Brush_height-2;
new_brush=(byte *)malloc(((long)width)*height);
if (new_brush)
old_width=Brush_width;
old_height=Brush_height;
SWAP_PBYTES(Brush, Brush_original_pixels);
if (Realloc_brush(Brush_width-2, Brush_height-2, NULL, &old_brush))
{
// On copie la brosse courante dans la nouvelle
Copy_part_of_image_to_another(Brush, // source
1,
1,
width,
height,
Brush_width,
new_brush, // Destination
0,
0,
width);
Error(0);
SWAP_PBYTES(Brush, Brush_original_pixels);
return;
}
// On copie l'ancienne brosse dans la nouvelle
Copy_part_of_image_to_another(old_brush, // source
1,
1,
old_width-2,
old_height-2,
old_width,
Brush, // Destination
0,
0,
Brush_width);
// On intervertit la nouvelle et l'ancienne brosse:
temp=Brush;
Brush=new_brush;
Brush_width-=2;
Brush_height-=2;
width+=2;
height+=2;
// 1er balayage (horizontal)
for (y_pos=0; y_pos<Brush_height; y_pos++)
{
state=(temp[(y_pos+1)*width]!=Back_color);
for (x_pos=0; x_pos<Brush_width; x_pos++)
{
if (temp[((y_pos+1)*width)+x_pos+1]==Back_color)
{
if (state != 0)
{
if (x_pos>0)
Pixel_in_brush(x_pos-1,y_pos,Back_color);
state=0;
}
}
else
{
if (state == 0)
{
Pixel_in_brush(x_pos,y_pos,Back_color);
state=1;
}
}
}
// Cas du dernier pixel à droite de la ligne
if (temp[((y_pos+1)*width)+x_pos+1]==Back_color)
Pixel_in_brush(x_pos-1,y_pos,Back_color);
}
// 2ème balayage (vertical)
// 1er balayage (horizontal)
for (y_pos=0; y_pos<Brush_height; y_pos++)
{
state=(old_brush[(y_pos+1)*old_width]!=Back_color);
for (x_pos=0; x_pos<Brush_width; x_pos++)
{
state=(temp[width+x_pos+1]!=Back_color);;
for (y_pos=0; y_pos<Brush_height; y_pos++)
if (old_brush[((y_pos+1)*old_width)+x_pos+1]==Back_color)
{
if (temp[((y_pos+1)*width)+x_pos+1]==Back_color)
if (state != 0)
{
if (state)
{
if (y_pos>0)
Pixel_in_brush(x_pos,y_pos-1,Back_color);
state=0;
}
}
else
{
if (state == 0)
{
Pixel_in_brush(x_pos,y_pos,Back_color);
state=1;
}
if (x_pos>0)
Pixel_in_brush(x_pos-1,y_pos,Back_color);
state=0;
}
}
else
{
if (state == 0)
{
Pixel_in_brush(x_pos,y_pos,Back_color);
state=1;
}
}
// Cas du dernier pixel en bas de la colonne
if (temp[((y_pos+1)*width)+x_pos+1]==Back_color)
Pixel_in_brush(x_pos,y_pos-1,Back_color);
}
// On recentre la prise sur la brosse
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
free(temp); // Libération de l'ancienne brosse
temp = NULL;
// Réallocation d'un buffer de Smear
free(Smear_brush);
Smear_brush_width=(Brush_width>MAX_PAINTBRUSH_SIZE)?Brush_width:MAX_PAINTBRUSH_SIZE;
Smear_brush_height=(Brush_height>MAX_PAINTBRUSH_SIZE)?Brush_height:MAX_PAINTBRUSH_SIZE;
Smear_brush=(byte *)malloc(((long)Smear_brush_width)*Smear_brush_height);
// Cas du dernier pixel à droite de la ligne
if (old_brush[((y_pos+1)*old_width)+x_pos+1]==Back_color)
Pixel_in_brush(x_pos-1,y_pos,Back_color);
}
else
Error(0); // Pas assez de mémoire!
// 2ème balayage (vertical)
for (x_pos=0; x_pos<Brush_width; x_pos++)
{
state=(old_brush[old_width+x_pos+1]!=Back_color);;
for (y_pos=0; y_pos<Brush_height; y_pos++)
{
if (old_brush[((y_pos+1)*old_width)+x_pos+1]==Back_color)
{
if (state)
{
if (y_pos>0)
Pixel_in_brush(x_pos,y_pos-1,Back_color);
state=0;
}
}
else
{
if (state == 0)
{
Pixel_in_brush(x_pos,y_pos,Back_color);
state=1;
}
}
}
// Cas du dernier pixel en bas de la colonne
if (old_brush[((y_pos+1)*old_width)+x_pos+1]==Back_color)
Pixel_in_brush(x_pos,y_pos-1,Back_color);
}
free(old_brush);
// Adopt the current palette.
memcpy(Brush_original_palette, Main_palette,sizeof(T_Palette));
memcpy(Brush_original_pixels, Brush, (long)Brush_width*Brush_height);
for (i=0; i<256; i++)
Brush_colormap[i]=i;
//--
// On recentre la prise sur la brosse
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
}
}
@ -1162,7 +1187,6 @@ void Capture_brush_with_lasso(int vertices, short * points,short clear)
word new_brush_width;
word new_brush_height;
// On recherche les bornes de la brosse:
for (temp=0; temp<2*vertices; temp+=2)
{
@ -1204,46 +1228,15 @@ void Capture_brush_with_lasso(int vertices, short * points,short clear)
new_brush_width=(end_x-start_x)+1;
new_brush_height=(end_y-start_y)+1;
if ( (((long)Brush_height)*Brush_width) !=
(((long)new_brush_height)*new_brush_width) )
{
free(Brush);
Brush=(byte *)malloc(((long)new_brush_height)*new_brush_width);
if (!Brush)
{
Error(0);
Brush=(byte *)malloc(1*1);
if(Brush==NULL) Error(ERROR_MEMORY);
new_brush_height=new_brush_width=1;
*Brush=Fore_color;
}
}
Brush_width=new_brush_width;
Brush_height=new_brush_height;
free(Smear_brush);
Smear_brush_width=(Brush_width>MAX_PAINTBRUSH_SIZE)?Brush_width:MAX_PAINTBRUSH_SIZE;
Smear_brush_height=(Brush_height>MAX_PAINTBRUSH_SIZE)?Brush_height:MAX_PAINTBRUSH_SIZE;
Smear_brush=(byte *)malloc(((long)Smear_brush_height)*Smear_brush_width);
if (!Smear_brush) // On ne peut même pas allouer la brosse du smear!
if (Realloc_brush(new_brush_width, new_brush_height, NULL, NULL))
{
Error(0);
free(Brush);
Brush=(byte *)malloc(1*1);
if(Brush==NULL) Error(ERROR_MEMORY);
Brush_height=1;
Brush_width=1;
Smear_brush=(byte *)malloc(MAX_PAINTBRUSH_SIZE*MAX_PAINTBRUSH_SIZE);
Smear_brush_height=MAX_PAINTBRUSH_SIZE;
Smear_brush_width=MAX_PAINTBRUSH_SIZE;
return;
}
Brush_offset_X=start_x;
Brush_offset_Y=start_y;
Pixel_figure=Pixel_figure_in_brush;
memset(Brush,Back_color,(long)Brush_width*Brush_height);
@ -1271,6 +1264,13 @@ void Capture_brush_with_lasso(int vertices, short * points,short clear)
if (clear)
Pixel_in_current_screen(x_pos,y_pos,Back_color,0);
}
// Grab palette
memcpy(Brush_original_palette, Main_palette,sizeof(T_Palette));
// Init colormap
for (temp=0; temp<256; temp++)
Brush_colormap[temp]=temp;
// Copy Brush to original
memcpy(Brush_original_pixels, Brush, (long)Brush_width*Brush_height);
// On centre la prise sur la brosse
Brush_offset_X=(Brush_width>>1);
@ -1304,50 +1304,27 @@ void Stretch_brush(short x1, short y1, short x2, short y2)
}
new_brush_height++;
// Free some memory
free(Smear_brush);
Smear_brush = NULL;
if ((new_brush=((byte *)malloc(new_brush_width*new_brush_height))))
new_brush=((byte *)malloc(new_brush_width*new_brush_height));
if (!new_brush)
{
Rescale(Brush, Brush_width, Brush_height, new_brush, new_brush_width, new_brush_height, x2<x1, y2<y1);
free(Brush);
Brush=new_brush;
Brush_width=new_brush_width;
Brush_height=new_brush_height;
Smear_brush_width=(Brush_width>MAX_PAINTBRUSH_SIZE)?Brush_width:MAX_PAINTBRUSH_SIZE;
Smear_brush_height=(Brush_height>MAX_PAINTBRUSH_SIZE)?Brush_height:MAX_PAINTBRUSH_SIZE;
Smear_brush=(byte *)malloc(((long)Smear_brush_height)*Smear_brush_width);
if (!Smear_brush) // On ne peut même pas allouer la brosse du smear!
{
Error(0);
free(Brush);
Brush=(byte *)malloc(1*1);
Brush_height=1;
Brush_width=1;
Smear_brush=(byte *)malloc(MAX_PAINTBRUSH_SIZE*MAX_PAINTBRUSH_SIZE);
Smear_brush_height=MAX_PAINTBRUSH_SIZE;
Smear_brush_width=MAX_PAINTBRUSH_SIZE;
}
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
}
else
{
// Ici la libération de mémoire n'a pas suffi donc on remet dans l'état
// où c'etait avant. On a juste à réallouer la Smear_brush car il y a
// normalement la place pour elle puisque rien d'autre n'a pu être alloué
// entre temps.
Smear_brush=(byte *)malloc(((long)Smear_brush_height)*Smear_brush_width);
Error(0);
return;
}
Rescale(Brush_original_pixels, Brush_width, Brush_height, new_brush, new_brush_width, new_brush_height, x2<x1, y2<y1);
if (Realloc_brush(new_brush_width, new_brush_height, new_brush, NULL))
{
free(new_brush);
Error(0);
return;
}
// Remap according to the last used remap table
Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
}
@ -1578,9 +1555,6 @@ void Distort_brush(short x1, short y1, short x2, short y2, short x3, short y3, s
short min_x, max_x, min_y, max_y;
short width, height;
byte * new_brush;
byte * new_smear_brush;
short new_smear_brush_width;
short new_smear_brush_height;
// Move all coordinates to start on (0,0)
min_x=Min4(x1,x2,x3,x4);
@ -1601,24 +1575,11 @@ void Distort_brush(short x1, short y1, short x2, short y2, short x3, short y3, s
width=Max(max_x-min_x, 1);
height=Max(max_y-min_y, 1);
new_smear_brush_width=(width>MAX_PAINTBRUSH_SIZE)?width:MAX_PAINTBRUSH_SIZE;
new_smear_brush_height=(height>MAX_PAINTBRUSH_SIZE)?height:MAX_PAINTBRUSH_SIZE;
new_smear_brush=(byte *)malloc(((long)new_smear_brush_height)*new_smear_brush_width);
if (! new_smear_brush)
{
// Out of memory while allocating new smear brush
Error(0);
return;
}
new_brush=((byte *)malloc((long)width*height));
if (!new_brush)
{
// Out of memory while allocating new brush
Error(0);
free(new_smear_brush);
new_smear_brush = NULL;
return;
}
@ -1631,18 +1592,14 @@ void Distort_brush(short x1, short y1, short x2, short y2, short x3, short y3, s
Distort_buffer_width=width;
Draw_brush_linear_distort(0, 0, (Brush_width<<16), (Brush_height<<16), (x1<<16), (y1<<16), (x2<<16), (y2<<16), (x3<<16), (y3<<16), (x4<<16), (y4<<16));
// Free old brushes
free(Smear_brush);
free(Brush);
// Point to the new ones
Brush=new_brush;
Brush_width=width;
Brush_height=height;
Smear_brush=new_smear_brush;
Smear_brush_width=new_smear_brush_width;
Smear_brush_height=new_smear_brush_height;
if (Realloc_brush(width, height, new_brush, NULL))
{
free(new_brush);
Error(0);
return;
}
// Remap according to the last used remap table
Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
// Re-center brush handle
Brush_offset_X=(Brush_width>>1);
@ -1867,7 +1824,7 @@ void Compute_quad_texture(int x1,int y1,int xt1,int yt1,
xt=Round((float)(ScanY_Xt[0][y])+(temp*(ScanY_Xt[1][y]-ScanY_Xt[0][y])));
yt=Round((float)(ScanY_Yt[0][y])+(temp*(ScanY_Yt[1][y]-ScanY_Yt[0][y])));
if (xt>=0 && yt>=0)
buffer[x+(y*width)]=Read_pixel_from_brush(xt,yt);
buffer[x+(y*width)]=*(Brush_original_pixels + yt * Brush_width + xt);
}
for (; x<width; x++)
buffer[x+(y*width)]=Back_color;
@ -1920,54 +1877,32 @@ void Rotate_brush(float angle)
new_brush_width=x_max+1-x_min;
new_brush_height=y_max+1-y_min;
free(Smear_brush); // On libère un peu de mémoire
Smear_brush = NULL;
if ((new_brush=((byte *)malloc(new_brush_width*new_brush_height))))
new_brush=(byte *)malloc(new_brush_width*new_brush_height);
if (!new_brush)
{
// Et maintenant on calcule la nouvelle brosse tournée.
Compute_quad_texture(x1,y1, 0, 0,
x2,y2,Brush_width-1, 0,
x3,y3, 0,Brush_height-1,
x4,y4,Brush_width-1,Brush_height-1,
new_brush,new_brush_width,new_brush_height);
free(Brush);
Brush=new_brush;
Brush_width=new_brush_width;
Brush_height=new_brush_height;
Smear_brush_width=(Brush_width>MAX_PAINTBRUSH_SIZE)?Brush_width:MAX_PAINTBRUSH_SIZE;
Smear_brush_height=(Brush_height>MAX_PAINTBRUSH_SIZE)?Brush_height:MAX_PAINTBRUSH_SIZE;
Smear_brush=(byte *)malloc(((long)Smear_brush_height)*Smear_brush_width);
if (!Smear_brush) // On ne peut même pas allouer la brosse du smear!
{
Error(0);
free(Brush);
Brush=(byte *)malloc(1*1);
Brush_height=1;
Brush_width=1;
Smear_brush=(byte *)malloc(MAX_PAINTBRUSH_SIZE*MAX_PAINTBRUSH_SIZE);
Smear_brush_height=MAX_PAINTBRUSH_SIZE;
Smear_brush_width=MAX_PAINTBRUSH_SIZE;
}
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
}
else
{
// Ici la libération de mémoire n'a pas suffit donc on remet dans l'état
// où c'etait avant. On a juste à réallouer la Smear_brush car il y a
// normalement la place pour elle puisque rien d'autre n'a pu être alloué
// entre temps.
Smear_brush=(byte *)malloc(((long)Smear_brush_height)*Smear_brush_width);
Error(0);
return;
}
// Et maintenant on calcule la nouvelle brosse tournée.
Compute_quad_texture(x1,y1, 0, 0,
x2,y2,Brush_width-1, 0,
x3,y3, 0,Brush_height-1,
x4,y4,Brush_width-1,Brush_height-1,
new_brush,new_brush_width,new_brush_height);
if (Realloc_brush(new_brush_width, new_brush_height, new_brush, NULL))
{
free(new_brush);
return;
}
// Remap according to the last used remap table
Remap_general_lowlevel(Brush_colormap,Brush_original_pixels,Brush,Brush_width,Brush_height,Brush_width);
// Center offsets
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
}
@ -2090,3 +2025,25 @@ void Rotate_brush_preview(float angle)
end_y=Max(Max(y1,y2),Max(y3,y4));
Update_part_of_screen(start_x,start_y,end_x-start_x+1,end_y-start_y+1);
}
/*
/// Sets brush's original palette and color mapping.
void Brush_set_palette(T_Palette *palette)
{
int i;
byte need_remap;
need_remap=0;
memcpy(Brush_original_palette,palette,sizeof(T_Palette));
for (i=0;i<256;i++)
{
if (Brush_original_palette[i].R!=Main_palette[i].R
|| Brush_original_palette[i].G!=Main_palette[i].G
|| Brush_original_palette[i].B!=Main_palette[i].B)
{
need_remap=1;
}
}
}
*/

View File

@ -111,10 +111,19 @@ void Capture_brush_with_lasso(int vertices, short * points,short clear);
///
/// Changes the Brush size, discarding its previous content.
/// @return 0 OK, 1 Failed
byte Realloc_brush(word new_brush_width, word new_brush_height);
/// Changes the Brush size.
/// @return 0 on success, non-zero on failure (memory?).
/// @param new_brush: Optionally, you can provide an already allocated new
/// brush - otherwise, this function performs the allocation.
/// @param old_brush: If the caller passes NULL, this function will free the old
/// pixel data. If the caller provides the address of a (free) byte
/// pointer, the function will make it point to the original pixel data,
/// in this case it will be the caller's responsibility to free() it
/// (after transferring pixels to Brush, usually).
byte Realloc_brush(word new_brush_width, word new_brush_height, byte *new_brush, byte **old_brush);
/// Sets brush's original palette and color mapping.
void Brush_set_palette(T_Palette *palette);
#endif

View File

@ -38,7 +38,7 @@
#include "sdlscreen.h"
#include "windows.h"
#if defined(__VBCC__)||defined(__GP2X__)
#if defined(__VBCC__) || defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__)
#define M_PI 3.141592653589793238462643
#endif
@ -251,6 +251,106 @@ void Colorpicker_0_1(void)
Unselect_button(BUTTON_COLORPICKER);
}
/////////////////////////////////////////////////////////// OPERATION_RMB_COLORPICK
byte Rightclick_colorpick(byte cursor_visible)
{
// Check if the rightclick colorpick should take over:
if (!Config.Right_click_colorpick)
return 0;
if (Mouse_K!=RIGHT_SIDE)
return 0;
// In these modes, the Foreground color is ignored,
// so the RMB should act as normal.
if (Shade_mode||Quick_shade_mode||Tiling_mode)
return 0;
Colorpicker_color=-1;
Colorpicker_X=-1;
Colorpicker_Y=-1;
if (cursor_visible)
Hide_cursor();
Start_operation_stack(OPERATION_RMB_COLORPICK);
Init_start_operation();
// Just an indicator to go to next step
Operation_push(1);
Rightclick_colorpick_2_1();
if (cursor_visible)
Display_cursor();
return 1;
}
void Rightclick_colorpick_2_1(void)
//
// Opération : OPERATION_RMB_COLORPICK
// Click Souris: 2
// Taille_Pile : 1
//
// Souris effacée: Non
//
{
char str[4];
if ( (Colorpicker_X!=Paintbrush_X)
|| (Colorpicker_Y!=Paintbrush_Y) )
{
if ( (Paintbrush_X>=0) && (Paintbrush_Y>=0)
&& (Paintbrush_X<Main_image_width)
&& (Paintbrush_Y<Main_image_height) )
Colorpicker_color=Read_pixel_from_current_screen(Paintbrush_X,Paintbrush_Y);
else
Colorpicker_color=0;
Colorpicker_X=Paintbrush_X;
Colorpicker_Y=Paintbrush_Y;
if (Menu_is_visible)
{
Print_coordinates();
Num2str(Colorpicker_color,str,3);
Print_in_menu(str,20);
Print_general(170*Menu_factor_X,Menu_status_Y," ",0,Colorpicker_color);
}
}
}
void Rightclick_colorpick_0_1(void)
//
// Opération : OPERATION_RMB_COLORPICK
// Click Souris: 0
// Taille_Pile : 1
//
// Souris effacée: Non
//
{
short dummy;
Hide_cursor();
Operation_pop(&dummy);
Set_fore_color(Colorpicker_color);
// Restore previous operation
Start_operation_stack(Operation_before_interrupt);
// Erase the color block which shows the picked color
if (Operation_before_interrupt!=OPERATION_REPLACE)
if ( (Mouse_Y<Menu_Y) && (Menu_is_visible) &&
( (!Main_magnifier_mode) || (Mouse_X<Main_separator_position) || (Mouse_X>=Main_X_zoom) ) )
Print_in_menu("X: Y: ",0);
Print_coordinates();
Display_cursor();
}
////////////////////////////////////////////////////// OPERATION_GRAB_BRUSH
@ -858,6 +958,10 @@ void Rotate_brush_1_5(void)
Operation_pop(&old_y);
Operation_pop(&old_x);
// On corrige les coordonnées de la ligne si la touche shift est appuyée...
if(SDL_GetModState() & KMOD_SHIFT)
Clamp_coordinates_regular_angle(Brush_rotation_center_X,Brush_rotation_center_Y,&Paintbrush_X,&Paintbrush_Y);
if ( (Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y) || (prev_state!=2) )
{
if ( (Brush_rotation_center_X==Paintbrush_X)
@ -921,6 +1025,10 @@ void Rotate_brush_0_5(void)
Operation_pop(&old_y);
Operation_pop(&old_x);
// On corrige les coordonnées de la ligne si la touche shift est appuyée...
if(SDL_GetModState() & KMOD_SHIFT)
Clamp_coordinates_regular_angle(Brush_rotation_center_X,Brush_rotation_center_Y,&Paintbrush_X,&Paintbrush_Y);
if ((Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y) || (prev_state!=3))
{
if ( (Brush_rotation_center_X==Paintbrush_X)

File diff suppressed because it is too large Load Diff

View File

@ -670,5 +670,9 @@ void Button_Smear_mode(void);
void Button_Brush_container(void);
byte Store_paintbrush(int index);
void Select_paintbrush(int index);
#endif

View File

@ -40,6 +40,7 @@
#include "sdlscreen.h"
#include "struct.h"
#include "windows.h"
#include "brush.h"
//---------- Menu dans lequel on tagge des couleurs (genre Stencil) ----------
void Menu_tag_colors(char * window_title, byte * table, byte * mode, byte can_cancel, const char *help_section, word close_shortcut)
@ -279,7 +280,7 @@ void Button_Grid_menu(void)
{
case 3 :
Num2str(chosen_X,str,2);
Readline(39,26,str,2,1);
Readline(39,26,str,2,INPUT_TYPE_INTEGER);
chosen_X=atoi(str);
// On corrige les dimensions
if ((!chosen_X) || (chosen_X>80))
@ -301,7 +302,7 @@ void Button_Grid_menu(void)
break;
case 4 :
Num2str(chosen_Y,str,2);
Readline(39,47,str,2,1);
Readline(39,47,str,2,INPUT_TYPE_INTEGER);
chosen_Y=atoi(str);
// On corrige les dimensions
if ((!chosen_Y) || (chosen_Y>80))
@ -323,7 +324,7 @@ void Button_Grid_menu(void)
break;
case 5 :
Num2str(dx_selected,str,2);
Readline(97,26,str,2,1);
Readline(97,26,str,2,INPUT_TYPE_INTEGER);
dx_selected=atoi(str);
// On corrige les dimensions
if (dx_selected>79)
@ -338,7 +339,7 @@ void Button_Grid_menu(void)
break;
case 6 :
Num2str(dy_selected,str,2);
Readline(97,47,str,2,1);
Readline(97,47,str,2,INPUT_TYPE_INTEGER);
dy_selected=atoi(str);
// On corrige les dimensions
if (dy_selected>79)
@ -479,7 +480,7 @@ void Button_Smooth_menu(void)
Num2str(chosen_matrix[x][y],str,2);
Readline(matrix_input[x][y]->Pos_X+2,
matrix_input[x][y]->Pos_Y+2,
str,2,1);
str,2,INPUT_TYPE_INTEGER);
chosen_matrix[x][y]=atoi(str);
Display_cursor();
}
@ -553,6 +554,9 @@ void Button_Colorize_mode(void)
break;
case 2 :
Effect_function=Effect_substractive_colorize;
break;
case 3 :
Effect_function=Effect_alpha_colorize;
}
Shade_mode=0;
Quick_shade_mode=0;
@ -572,10 +576,12 @@ void Button_Colorize_display_selection(int mode)
Print_in_window(4,37," ",MC_Black,MC_Light);
Print_in_window(4,57," ",MC_Black,MC_Light);
Print_in_window(4,74," ",MC_Black,MC_Light);
Print_in_window(4,91," ",MC_Black,MC_Light);
// Partie droite
Print_in_window(129,37," ",MC_Black,MC_Light);
Print_in_window(129,57," ",MC_Black,MC_Light);
Print_in_window(129,74," ",MC_Black,MC_Light);
Print_in_window(129,91," ",MC_Black,MC_Light);
// Ensuite, on affiche la flèche là où il le faut:
switch(mode)
@ -588,6 +594,9 @@ void Button_Colorize_display_selection(int mode)
break;
case 2 : // Méthode soustractive
y_pos=74;
break;
case 3 : // Méthode alpha
y_pos=91;
}
Print_in_window(4,y_pos,"\020",MC_Black,MC_Light);
Print_in_window(129,y_pos,"\021",MC_Black,MC_Light);
@ -600,7 +609,7 @@ void Button_Colorize_menu(void)
short clicked_button;
char str[4];
Open_window(140,118,"Transparency");
Open_window(140,135,"Transparency");
Print_in_window(16,23,"Opacity:",MC_Dark,MC_Light);
Window_set_input_button(87,21,3); // 1
@ -610,9 +619,10 @@ void Button_Colorize_menu(void)
Window_set_normal_button(16,54,108,14,"Additive" ,2,1,SDLK_d); // 3
Window_set_normal_button(16,71,108,14,"Subtractive",1,1,SDLK_s); // 4
Window_set_normal_button(16,88,108,14,"Alpha",1,1,SDLK_a); // 4
Window_set_normal_button(16,94, 51,14,"Cancel" ,0,1,KEY_ESC); // 5
Window_set_normal_button(73,94, 51,14,"OK" ,0,1,SDLK_RETURN); // 6
Window_set_normal_button(16,111, 51,14,"Cancel" ,0,1,KEY_ESC); // 5
Window_set_normal_button(73,111, 51,14,"OK" ,0,1,SDLK_RETURN); // 6
Num2str(Colorize_opacity,str,3);
Window_input_content(Window_special_button_list,str);
@ -632,7 +642,7 @@ void Button_Colorize_menu(void)
{
case 1: // Zone de saisie de l'opacité
Num2str(chosen_opacity,str,3);
Readline(89,23,str,3,1);
Readline(89,23,str,3,INPUT_TYPE_INTEGER);
chosen_opacity=atoi(str);
// On corrige le pourcentage
if (chosen_opacity>100)
@ -643,9 +653,10 @@ void Button_Colorize_menu(void)
}
Display_cursor();
break;
case 2: // Méthode interpolée
case 3: // Méthode additive
case 4: // Méthode soustractive
case 2: // Interpolated method
case 3: // Additive method
case 4: // Substractive method
case 5: // Alpha method
selected_mode=clicked_button-2;
Hide_cursor();
Button_Colorize_display_selection(selected_mode);
@ -654,13 +665,13 @@ void Button_Colorize_menu(void)
if (Is_shortcut(Key,0x100+BUTTON_HELP))
Window_help(BUTTON_EFFECTS, "TRANSPARENCY");
else if (Is_shortcut(Key,SPECIAL_COLORIZE_MENU))
clicked_button=6;
clicked_button=7;
}
while (clicked_button<5);
while (clicked_button<6);
Close_window();
if (clicked_button==6) // OK
if (clicked_button==7) // OK
{
Colorize_opacity =chosen_opacity;
Colorize_current_mode=selected_mode;
@ -724,7 +735,7 @@ void Button_Tiling_menu(void)
if (clicked_button==3) // Zone de saisie du décalage X
{
Num2str(chosen_offset_x,str,4);
Readline(93,23,str,4,1);
Readline(93,23,str,4,INPUT_TYPE_INTEGER);
chosen_offset_x=atoi(str);
// On corrige le décalage en X
if (chosen_offset_x>=Brush_width)
@ -739,7 +750,7 @@ void Button_Tiling_menu(void)
if (clicked_button==4) // Zone de saisie du décalage Y
{
Num2str(chosen_offset_y,str,4);
Readline(93,37,str,4,1);
Readline(93,37,str,4,INPUT_TYPE_INTEGER);
chosen_offset_y=atoi(str);
// On corrige le décalage en Y
if (chosen_offset_y>=Brush_height)
@ -975,8 +986,8 @@ void Button_Sieve_menu(void)
{
clicked_button=Window_clicked_button();
origin_x=Window_pos_X+(Menu_factor_X*Window_special_button_list->Pos_X);
origin_y=Window_pos_Y+(Menu_factor_Y*Window_special_button_list->Pos_Y);
origin_x=Window_pos_X+(Menu_factor_X*Window_special_button_list->Pos_X);
origin_y=Window_pos_Y+(Menu_factor_Y*Window_special_button_list->Pos_Y);
switch (clicked_button)
@ -1063,15 +1074,22 @@ void Button_Sieve_menu(void)
break;
case 7 : // Transfer to brush
Brush_width=Sieve_width;
Brush_height=Sieve_height;
free(Brush);
Brush=(byte *)malloc(((long)Brush_height)*Brush_width);
if (Realloc_brush(Sieve_width, Sieve_height, NULL, NULL))
break;
for (y_pos=0; y_pos<Sieve_height; y_pos++)
for (x_pos=0; x_pos<Sieve_width; x_pos++)
Pixel_in_brush(x_pos,y_pos,(Sieve[x_pos][y_pos])?Fore_color:Back_color);
*(Brush_original_pixels + y_pos * Brush_width + x_pos) = (Sieve[x_pos][y_pos])?Fore_color:Back_color;
// Grab palette
memcpy(Brush_original_palette, Main_palette,sizeof(T_Palette));
// Remap (no change)
Remap_brush();
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH);
break;

View File

@ -37,7 +37,6 @@
#define BETA1 98 ///< Version number for gfx2.cfg (3/4)
#define BETA2 0 ///< Version number for gfx2.cfg (4/4)
#define MAX_VIDEO_MODES 100 ///< Maximum number of video modes Grafx2 can propose.
#define NB_SHORTCUTS 183 ///< Number of actions that can have a key combination associated to it.
#define NB_ZOOM_FACTORS 15 ///< Number of zoom levels available in the magnifier.
#define MENU_WIDTH 254 ///< Width of the menu (not counting the palette)
#define MENU_HEIGHT 44 ///< Height of the menu.
@ -45,9 +44,10 @@
#define CURSOR_SPRITE_WIDTH 15 ///< Width of a mouse cursor sprite.
#define CURSOR_SPRITE_HEIGHT 15 ///< Height of a mouse cursor sprite.
#define NB_EFFECTS_SPRITES 9 ///< Number of effect sprites.
#define NB_MENU_SPRITES 20 ///< Number of menu sprites.
#define MENU_SPRITE_WIDTH 14 ///< Width of a menu sprite in pixels
#define MENU_SPRITE_HEIGHT 14 ///< Height of a menu sprite in pixels
#define MENU_SPRITE_WIDTH 16 ///< Width of a menu sprite in pixels
#define MENU_SPRITE_HEIGHT 16 ///< Height of a menu sprite in pixels
#define EFFECT_SPRITE_WIDTH 14 ///< Width of an effect sprite in pixels
#define EFFECT_SPRITE_HEIGHT 14 ///< Height of an effect sprite in pixels
#define LAYER_SPRITE_WIDTH 14 ///< Width of a layer button in pixels
#define LAYER_SPRITE_HEIGHT 10 ///< Height of a layer button in pixels
#define PAINTBRUSH_WIDTH 16 ///< Width of a preset paintbrush sprite
@ -120,6 +120,7 @@ enum FILE_FORMATS
FORMAT_KCF,
FORMAT_PAL,
FORMAT_SCR,
FORMAT_XPM,
FORMAT_MISC, ///< Must be last of enum: others formats recognized by SDL_image
};
@ -210,9 +211,17 @@ enum PAINTBRUSH_SHAPES
PAINTBRUSH_SHAPE_DIAMOND,
PAINTBRUSH_SHAPE_SIEVE_ROUND,
PAINTBRUSH_SHAPE_SIEVE_SQUARE,
PAINTBRUSH_SHAPE_RESERVED1, ///< Reserved for future use
PAINTBRUSH_SHAPE_RESERVED2, ///< Reserved for future use
PAINTBRUSH_SHAPE_RESERVED3, ///< Reserved for future use
PAINTBRUSH_SHAPE_RESERVED4, ///< Reserved for future use
PAINTBRUSH_SHAPE_RESERVED5, ///< Reserved for future use
PAINTBRUSH_SHAPE_RESERVED6, ///< Reserved for future use
PAINTBRUSH_SHAPE_RESERVED7, ///< Reserved for future use
PAINTBRUSH_SHAPE_RESERVED8, ///< Reserved for future use
PAINTBRUSH_SHAPE_MISC, ///< A raw monochrome bitmap, can't be resized. This must be the last of the preset paintbrush types.
PAINTBRUSH_SHAPE_POINT, ///< Used to reduce the paintbrush to a single pixel, during operations like floodfill.
PAINTBRUSH_SHAPE_NONE, ///< Used to display no cursor at all (colorpicker)
PAINTBRUSH_SHAPE_NONE, ///< Used to display no cursor at all (colorpicker)
PAINTBRUSH_SHAPE_COLOR_BRUSH, ///< User's brush, in color mode
PAINTBRUSH_SHAPE_MONO_BRUSH, ///< User's brush, in mono mode
PAINTBRUSH_SHAPE_MAX ///< Upper limit.
@ -222,6 +231,8 @@ enum PAINTBRUSH_SHAPES
#define BUTTON_RELEASED 0
/// State of a menu button that is being pressed.
#define BUTTON_PRESSED 1
/// State of a button temporarily highligted
#define BUTTON_HIGHLIGHTED 2
/// The different modes of the Shade
enum SHADE_MODES
@ -243,7 +254,9 @@ enum CHUNKS_CFG
CHUNK_SMOOTH = 6, ///< Smooth effect settings
CHUNK_EXCLUDE_COLORS = 7, ///< List of excluded colors
CHUNK_QUICK_SHADE = 8, ///< QShade effect settings
CHUNK_GRID = 9,
CHUNK_GRID = 9, ///< Grid settings
CHUNK_BRUSH =10, ///< Paintbrushes
CHUNK_SCRIPTS =11, ///< Callable scripts
CHUNK_MAX
};
@ -257,7 +270,8 @@ enum ICON_TYPES
ICON_NETWORK, ///< "Network" drive
ICON_STAR, ///< Star (favorite)
ICON_DROPDOWN, ///< Dropdown arrow
NB_ICON_SPRITES ///< Number of 8x8 icons
NB_ICON_SPRITES, ///< Number of 8x8 icons
ICON_NONE ///< None of the above
};
/// Identifiers for the buttons in the menu.
@ -316,6 +330,24 @@ enum BUTTON_NUMBERS
NB_BUTTONS ///< Number of buttons in the menu bar.
};
enum MENU_SPRITE
{
MENU_SPRITE_COLOR_BRUSH=0,
MENU_SPRITE_MONO_BRUSH,
MENU_SPRITE_DISCONTINUOUS_DRAW,
MENU_SPRITE_POINT_DRAW,
MENU_SPRITE_CONTOUR_DRAW,
MENU_SPRITE_4_POINTS_CURVE,
MENU_SPRITE_K_LINE,
MENU_SPRITE_CENTERED_LINES,
MENU_SPRITE_ELLIPSES,
MENU_SPRITE_POLYFORM,
MENU_SPRITE_REPLACE,
MENU_SPRITE_GRAD_ELLIPSE,
MENU_SPRITE_VERTICAL_PALETTE_SCROLL,
NB_MENU_SPRITES ///< Number of menu sprites.
};
///
/// Identifiers of special actions that can have a keyboard shortcut.
/// They are special in the sense that there's no button in the menu for them,
@ -364,6 +396,10 @@ enum SPECIAL_ACTIONS
SPECIAL_GET_BRUSH_COLORS,
SPECIAL_RECOLORIZE_BRUSH,
SPECIAL_ROTATE_ANY_ANGLE,
SPECIAL_BRUSH_DOUBLE,
SPECIAL_BRUSH_DOUBLE_WIDTH,
SPECIAL_BRUSH_DOUBLE_HEIGHT,
SPECIAL_BRUSH_HALVE,
SPECIAL_LOAD_BRUSH,
SPECIAL_SAVE_BRUSH,
SPECIAL_INVERT_SIEVE,
@ -435,8 +471,22 @@ enum SPECIAL_ACTIONS
SPECIAL_LAYER7_TOGGLE,
SPECIAL_LAYER8_SELECT,
SPECIAL_LAYER8_TOGGLE,
SPECIAL_REPEAT_SCRIPT,
SPECIAL_RUN_SCRIPT_1,
SPECIAL_RUN_SCRIPT_2,
SPECIAL_RUN_SCRIPT_3,
SPECIAL_RUN_SCRIPT_4,
SPECIAL_RUN_SCRIPT_5,
SPECIAL_RUN_SCRIPT_6,
SPECIAL_RUN_SCRIPT_7,
SPECIAL_RUN_SCRIPT_8,
SPECIAL_RUN_SCRIPT_9,
SPECIAL_RUN_SCRIPT_10,
SPECIAL_CYCLE_MODE,
SPECIAL_FORMAT_CHECKER,
SPECIAL_FORMAT_CHECKER_MENU,
NB_SPECIAL_SHORTCUTS ///< Number of special shortcuts
};
@ -448,7 +498,7 @@ enum OPERATIONS
OPERATION_POINT_DRAW, ///< Freehand point-by-point draw
OPERATION_FILLED_CONTOUR, ///< Filled contour
OPERATION_LINE, ///< Lines
OPERATION_K_LIGNE, ///< Linked lines
OPERATION_K_LINE, ///< Linked lines
OPERATION_CENTERED_LINES, ///< Centered lines
OPERATION_EMPTY_RECTANGLE, ///< Empty rectangle
OPERATION_FILLED_RECTANGLE, ///< Filled rectangle
@ -476,6 +526,7 @@ enum OPERATIONS
OPERATION_STRETCH_BRUSH, ///< Stretch brush
OPERATION_DISTORT_BRUSH, ///< Distort brush
OPERATION_GRAD_RECTANGLE, ///< Gradient-filled rectangle
OPERATION_RMB_COLORPICK, ///< Colorpick on right mouse button
NB_OPERATIONS ///< Number of operations handled by the engine
};

File diff suppressed because it is too large Load Diff

View File

@ -30,7 +30,7 @@
#include "struct.h"
void Main_handler (void);
void Draw_menu_button_frame(byte btn_number,byte pressed);
void Draw_menu_button (byte btn_number,byte pressed);
void Unselect_button (int btn_number);
void Select_button (int btn_number,byte click);
void Open_window (word width,word height, const char * title);
@ -40,25 +40,25 @@ void Open_popup (word x_pos, word y_pos, word width, word height);
void Close_popup (void);
void Window_draw_normal_bouton(word x_pos,word y_pos,word width,word height,
char * title,byte undersc_letter,byte clickable);
const char * title,byte undersc_letter,byte clickable);
void Window_select_normal_button(word x_pos,word y_pos,word width,word height);
void Window_unselect_normal_button(word x_pos,word y_pos,word width,word height);
void Window_draw_palette_bouton(word x_pos,word y_pos);
void Compute_slider_cursor_height(T_Scroller_button * button);
void Compute_slider_cursor_length(T_Scroller_button * button);
void Window_draw_slider(T_Scroller_button * button);
void Window_draw_scroller_bouton(T_Scroller_button * button);
void Window_draw_scroller_button(T_Scroller_button * button);
void Window_input_content(T_Special_button * button, char * content);
void Window_clear_input_button(T_Special_button * button);
void Window_draw_input_bouton(word x_pos, word y_pos, word width_in_characters);
T_Normal_button * Window_set_normal_button(word x_pos, word y_pos,
word width, word height, char * title, byte undersc_letter,
word width, word height, const char * title, byte undersc_letter,
byte clickable, word shortcut);
T_Normal_button * Window_set_repeatable_button(word x_pos, word y_pos,
word width, word height, char * title, byte undersc_letter,
word width, word height, const char * title, byte undersc_letter,
byte clickable, word shortcut);
T_Palette_button * Window_set_palette_button(word x_pos, word y_pos);
@ -69,6 +69,10 @@ T_Scroller_button * Window_set_scroller_button(word x_pos, word y_pos,
word height, word nb_elements, word nb_elements_visible,
word initial_position);
T_Scroller_button * Window_set_horizontal_scroller_button(word x_pos, word y_pos,
word height, word nb_elements, word nb_elements_visible,
word initial_position);
T_Special_button * Window_set_special_button(word x_pos, word y_pos, word width,
word height);
@ -111,4 +115,9 @@ void Pixel_background(int x_pos, int y_pos, byte color);
/// Updates the status bar line with a color number.
/// Used when hovering the menu palette.
void Status_print_palette_color(byte color);
/// Puts the user in wait mode for the specified time ( in 1/100s),
/// though the mouse still works.
void Delay_with_active_mouse(int delay);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,13 @@
/* vim:expandtab:ts=2 sw=2:
*/
void Button_Brush_Factory(void);
void Repeat_script(void);
/// Lua scripts bound to shortcut keys.
extern char * Bound_script[10];
///
/// Run a lua script linked to a shortcut, 0-9.
/// Before: Cursor hidden
/// After: Cursor shown
void Run_numbered_script(byte index);

View File

@ -2,6 +2,7 @@
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2009 Petter Lindquist
Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet
@ -27,6 +28,19 @@
#ifndef __no_pnglib__
#include <png.h>
#if (PNG_LIBPNG_VER_MAJOR <= 1) && (PNG_LIBPNG_VER_MINOR < 4)
// Compatibility layer to allow us to use libng 1.4 or any older one.
// This function is renamed in 1.4
#define png_set_expand_gray_1_2_4_to_8(x) png_set_gray_1_2_4_to_8(x)
// Wrappers that are mandatory in 1.4. Older version allowed direct access.
#define png_get_rowbytes(png_ptr,info_ptr) ((info_ptr)->rowbytes)
#define png_get_image_width(png_ptr,info_ptr) ((info_ptr)->width)
#define png_get_image_height(png_ptr,info_ptr) ((info_ptr)->height)
#define png_get_bit_depth(png_ptr,info_ptr) ((info_ptr)->bit_depth)
#define png_get_color_type(png_ptr,info_ptr) ((info_ptr)->color_type)
#endif
#endif
#include <stdlib.h>
@ -59,11 +73,11 @@ void Test_IMG(T_IO_Context * context)
if ((file=fopen(filename, "rb")))
{
// Lecture et vérification de la signature
if (Read_bytes(file,IMG_header.Filler1,sizeof(IMG_header.Filler1))
if (Read_bytes(file,IMG_header.Filler1,6)
&& Read_word_le(file,&(IMG_header.Width))
&& Read_word_le(file,&(IMG_header.Height))
&& Read_bytes(file,IMG_header.Filler2,sizeof(IMG_header.Filler2))
&& Read_bytes(file,IMG_header.Palette,sizeof(IMG_header.Palette))
&& Read_bytes(file,IMG_header.Filler2,118)
&& Read_bytes(file,IMG_header.Palette,sizeof(T_Palette))
)
{
if ( (!memcmp(IMG_header.Filler1,signature,6))
@ -94,11 +108,11 @@ void Load_IMG(T_IO_Context * context)
{
file_size=File_length_file(file);
if (Read_bytes(file,IMG_header.Filler1,sizeof(IMG_header.Filler1))
if (Read_bytes(file,IMG_header.Filler1,6)
&& Read_word_le(file,&(IMG_header.Width))
&& Read_word_le(file,&(IMG_header.Height))
&& Read_bytes(file,IMG_header.Filler2,sizeof(IMG_header.Filler2))
&& Read_bytes(file,IMG_header.Palette,sizeof(IMG_header.Palette))
&& Read_bytes(file,IMG_header.Filler2,118)
&& Read_bytes(file,IMG_header.Palette,sizeof(T_Palette))
)
{
@ -167,11 +181,11 @@ void Save_IMG(T_IO_Context * context)
memcpy(IMG_header.Palette,context->Palette,sizeof(T_Palette));
if (Write_bytes(file,IMG_header.Filler1,sizeof(IMG_header.Filler1))
if (Write_bytes(file,IMG_header.Filler1,6)
&& Write_word_le(file,IMG_header.Width)
&& Write_word_le(file,IMG_header.Height)
&& Write_bytes(file,IMG_header.Filler2,sizeof(IMG_header.Filler2))
&& Write_bytes(file,IMG_header.Palette,sizeof(IMG_header.Palette))
&& Write_bytes(file,IMG_header.Filler2,118)
&& Write_bytes(file,IMG_header.Palette,sizeof(T_Palette))
)
{
@ -204,7 +218,6 @@ void Save_IMG(T_IO_Context * context)
//////////////////////////////////// LBM ////////////////////////////////////
#pragma pack(1)
typedef struct
{
word Width;
@ -221,7 +234,6 @@ typedef struct
word X_screen;
word Y_screen;
} T_LBM_Header;
#pragma pack()
byte * LBM_buffer;
FILE *LBM_file;
@ -375,28 +387,42 @@ void Test_LBM(T_IO_Context * context)
}
}
// ------------------------- Attendre une section -------------------------
byte Wait_for(byte * expected_section)
{
// Valeur retournée: 1=Section trouvée, 0=Section non trouvée (erreur)
dword Taille_section;
byte section_read[4];
// Inspired by Allegro: storing a 4-character identifier as a 32bit litteral
#define ID4(a,b,c,d) ((((a)&255)<<24) | (((b)&255)<<16) | (((c)&255)<<8) | (((d)&255)))
/// Skips the current section in an ILBM file.
/// This function should be called while the file pointer is right
/// after the 4-character code that identifies the section.
int LBM_Skip_section(void)
{
dword size;
if (!Read_dword_be(LBM_file,&size))
return 0;
if (size&1)
size++;
if (fseek(LBM_file,size,SEEK_CUR))
return 0;
return 1;
}
// ------------------------- Attendre une section -------------------------
byte LBM_Wait_for(byte * expected_section)
{
// Valeur retournée: 1=Section trouvée, 0=Section non trouvée (erreur)
byte section_read[4];
if (! Read_bytes(LBM_file,section_read,4))
return 0;
while (memcmp(section_read,expected_section,4)) // Sect. pas encore trouvée
{
if (!LBM_Skip_section())
return 0;
if (! Read_bytes(LBM_file,section_read,4))
return 0;
while (memcmp(section_read,expected_section,4)) // Sect. pas encore trouvée
{
if (!Read_dword_be(LBM_file,&Taille_section))
return 0;
if (Taille_section&1)
Taille_section++;
if (fseek(LBM_file,Taille_section,SEEK_CUR))
return 0;
if (! Read_bytes(LBM_file,section_read,4))
return 0;
}
return 1;
}
return 1;
}
// Les images ILBM sont stockés en bitplanes donc on doit trifouiller les bits pour
// en faire du chunky
@ -509,7 +535,7 @@ void Load_LBM(T_IO_Context * context)
byte temp_byte;
short b256;
dword nb_colors;
dword image_size;
dword section_size;
short x_pos;
short y_pos;
short counter;
@ -531,7 +557,7 @@ void Load_LBM(T_IO_Context * context)
Read_bytes(LBM_file,section,4);
Read_dword_be(LBM_file,&dummy);
Read_bytes(LBM_file,format,4);
if (!Wait_for((byte *)"BMHD"))
if (!LBM_Wait_for((byte *)"BMHD"))
File_error=1;
Read_dword_be(LBM_file,&dummy);
@ -551,7 +577,7 @@ void Load_LBM(T_IO_Context * context)
&& (Read_word_be(LBM_file,&header.Y_screen))
&& header.Width && header.Height)
{
if ( (header.BitPlanes) && (Wait_for((byte *)"CMAP")) )
if ( (header.BitPlanes) && (LBM_Wait_for((byte *)"CMAP")) )
{
Read_dword_be(LBM_file,&nb_colors);
nb_colors/=3;
@ -604,16 +630,73 @@ void Load_LBM(T_IO_Context * context)
if (Read_byte(LBM_file,&temp_byte))
File_error=2;
if ( (Wait_for((byte *)"BODY")) && (!File_error) )
// Keep reading sections until we find the body
while (1)
{
Read_dword_be(LBM_file,&image_size);
//swab((char *)&header.Width ,(char *)&context->Width,2);
//swab((char *)&header.Height,(char *)&context->Height,2);
if (! Read_bytes(LBM_file,section,4))
{
File_error=2;
break;
}
// Found body : stop searching
if (!memcmp(section,"BODY",4))
break;
else if (!memcmp(section,"CRNG",4))
{
// Handle CRNG
// The content of a CRNG is as follows:
word padding;
word rate;
word flags;
byte min_col;
byte max_col;
//
if ( (Read_dword_be(LBM_file,&section_size))
&& (Read_word_be(LBM_file,&padding))
&& (Read_word_be(LBM_file,&rate))
&& (Read_word_be(LBM_file,&flags))
&& (Read_byte(LBM_file,&min_col))
&& (Read_byte(LBM_file,&max_col)))
{
if (section_size == 8 && min_col != max_col)
{
// Valid cycling range
if (max_col<min_col)
SWAP_BYTES(min_col,max_col)
context->Cycle_range[context->Color_cycles].Start=min_col;
context->Cycle_range[context->Color_cycles].End=max_col;
context->Cycle_range[context->Color_cycles].Inverse=(flags&2)?1:0;
context->Cycle_range[context->Color_cycles].Speed=(flags&1) ? rate/78 : 0;
context->Color_cycles++;
}
}
else
{
File_error=2;
break;
}
}
else
{
// ignore any number of unknown sections
if (!LBM_Skip_section())
{
File_error=2;
break;
}
}
}
if ( !File_error )
{
Read_dword_be(LBM_file,&section_size);
context->Width = header.Width;
context->Height = header.Height;
//swab((char *)&header.X_screen,(char *)&Original_screen_X,2);
//swab((char *)&header.Y_screen,(char *)&Original_screen_Y,2);
Original_screen_X = header.X_screen;
Original_screen_Y = header.Y_screen;
@ -874,6 +957,7 @@ void Save_LBM(T_IO_Context * context)
byte temp_byte;
word real_width;
int file_size;
int i;
File_error=0;
Get_full_filename(filename, context->File_name, context->File_directory);
@ -890,7 +974,6 @@ void Save_LBM(T_IO_Context * context)
// On corrige la largeur de l'image pour qu'elle soit multiple de 2
real_width=context->Width+(context->Width&1);
//swab((byte *)&real_width,(byte *)&header.Width,2);
header.Width=context->Width;
header.Height=context->Height;
header.X_org=0;
@ -923,7 +1006,23 @@ void Save_LBM(T_IO_Context * context)
Write_dword_be(LBM_file,sizeof(T_Palette));
Write_bytes(LBM_file,context->Palette,sizeof(T_Palette));
for (i=0; i<context->Color_cycles; i++)
{
word flags=0;
flags|= context->Cycle_range[i].Speed?1:0; // Cycling or not
flags|= context->Cycle_range[i].Inverse?2:0; // Inverted
Write_bytes(LBM_file,"CRNG",4);
Write_dword_be(LBM_file,8); // Section size
Write_word_be(LBM_file,0); // Padding
Write_word_be(LBM_file,context->Cycle_range[i].Speed*78); // Rate
Write_word_be(LBM_file,flags); // Flags
Write_byte(LBM_file,context->Cycle_range[i].Start); // Min color
Write_byte(LBM_file,context->Cycle_range[i].End); // Max color
// No padding, size is multiple of 2
}
Write_bytes(LBM_file,"BODY",4);
Write_dword_be(LBM_file,0); // On mettra la taille à jour à la fin
@ -948,8 +1047,8 @@ void Save_LBM(T_IO_Context * context)
file_size=File_length(filename);
LBM_file=fopen(filename,"rb+");
fseek(LBM_file,820,SEEK_SET);
Write_dword_be(LBM_file,file_size-824);
fseek(LBM_file,820+context->Color_cycles*16,SEEK_SET);
Write_dword_be(LBM_file,file_size-824-context->Color_cycles*16);
if (!File_error)
{
@ -1554,7 +1653,6 @@ void Save_BMP(T_IO_Context * context)
//////////////////////////////////// GIF ////////////////////////////////////
#pragma pack(1)
typedef struct
{
word Width; // Width of the complete image area
@ -1573,7 +1671,6 @@ typedef struct
byte Indicator; // Misc image information
byte Nb_bits_pixel; // Nb de bits par pixel
} T_GIF_IDB; // Image Descriptor Block
#pragma pack()
typedef struct
{
@ -1735,7 +1832,7 @@ void Load_GIF(T_IO_Context * context)
word color_index; // index de traitement d'une couleur
byte size_to_read; // Nombre de données à lire (divers)
byte block_identifier; // Code indicateur du type de bloc en cours
word initial_nb_bits; // Nb de bits au début du traitement LZW
byte initial_nb_bits; // Nb de bits au début du traitement LZW
word special_case=0; // Mémoire pour le cas spécial
word old_code=0; // Code précédent
word byte_read; // Sauvegarde du code en cours de lecture
@ -1787,8 +1884,6 @@ void Load_GIF(T_IO_Context * context)
// Ordre de Classement = (LSDB.Aspect and $80)
nb_colors=(1 << ((LSDB.Resol & 0x07)+1));
initial_nb_bits=(LSDB.Resol & 0x07)+2;
if (LSDB.Resol & 0x80)
{
// Palette globale dispo:
@ -1796,24 +1891,12 @@ void Load_GIF(T_IO_Context * context)
if (Config.Clear_palette)
memset(context->Palette,0,sizeof(T_Palette));
// On peut maintenant charger la nouvelle palette:
if (!(LSDB.Aspect & 0x80))
// Palette dans l'ordre:
for(color_index=0;color_index<nb_colors;color_index++)
{
Read_byte(GIF_file,&(context->Palette[color_index].R));
Read_byte(GIF_file,&(context->Palette[color_index].G));
Read_byte(GIF_file,&(context->Palette[color_index].B));
}
else
// Load the palette
for(color_index=0;color_index<nb_colors;color_index++)
{
// Palette triée par composantes:
for (color_index=0;color_index<nb_colors;color_index++)
Read_byte(GIF_file,&(context->Palette[color_index].R));
for (color_index=0;color_index<nb_colors;color_index++)
Read_byte(GIF_file,&(context->Palette[color_index].G));
for (color_index=0;color_index<nb_colors;color_index++)
Read_byte(GIF_file,&(context->Palette[color_index].B));
Read_byte(GIF_file,&(context->Palette[color_index].R));
Read_byte(GIF_file,&(context->Palette[color_index].G));
Read_byte(GIF_file,&(context->Palette[color_index].B));
}
}
@ -1924,6 +2007,57 @@ void Load_GIF(T_IO_Context * context)
}
}
}
else if (!memcmp(aeb,"CRNG\0\0\0\0" "1.0",0x0B))
{
// Color animation. Similar to a LBM CRNG chunk.
word rate;
word flags;
byte min_col;
byte max_col;
//
Read_byte(GIF_file,&size_to_read);
for(;size_to_read>0 && !File_error;size_to_read-=6)
{
if ( (Read_word_be(GIF_file,&rate))
&& (Read_word_be(GIF_file,&flags))
&& (Read_byte(GIF_file,&min_col))
&& (Read_byte(GIF_file,&max_col)))
{
if (min_col != max_col)
{
// Valid cycling range
if (max_col<min_col)
SWAP_BYTES(min_col,max_col)
context->Cycle_range[context->Color_cycles].Start=min_col;
context->Cycle_range[context->Color_cycles].End=max_col;
context->Cycle_range[context->Color_cycles].Inverse=(flags&2)?1:0;
context->Cycle_range[context->Color_cycles].Speed=(flags&1)?rate/78:0;
context->Color_cycles++;
}
}
else
{
File_error=1;
}
}
// Read end-of-block delimiter
if (!File_error)
Read_byte(GIF_file,&size_to_read);
if (size_to_read!=0)
File_error=1;
}
else
{
// Unknown extension, skip.
Read_byte(GIF_file,&size_to_read);
while (size_to_read!=0 && !File_error)
{
fseek(GIF_file,size_to_read,SEEK_CUR);
Read_byte(GIF_file,&size_to_read);
}
}
}
else
{
@ -1961,7 +2095,6 @@ void Load_GIF(T_IO_Context * context)
&& Read_word_le(GIF_file,&(IDB.Image_width))
&& Read_word_le(GIF_file,&(IDB.Image_height))
&& Read_byte(GIF_file,&(IDB.Indicator))
&& Read_byte(GIF_file,&(IDB.Nb_bits_pixel))
&& IDB.Image_width && IDB.Image_height)
{
@ -1974,42 +2107,38 @@ void Load_GIF(T_IO_Context * context)
{
// Palette locale dispo
if (Config.Clear_palette)
memset(context->Palette,0,sizeof(T_Palette));
nb_colors=(1 << ((IDB.Indicator & 0x07)+1));
initial_nb_bits=(IDB.Indicator & 0x07)+2;
if (!(IDB.Indicator & 0x40))
// Palette dans l'ordre:
for(color_index=0;color_index<nb_colors;color_index++)
{
Read_byte(GIF_file,&(context->Palette[color_index].R));
Read_byte(GIF_file,&(context->Palette[color_index].G));
Read_byte(GIF_file,&(context->Palette[color_index].B));
}
else
{
// Palette triée par composantes:
for (color_index=0;color_index<nb_colors;color_index++)
Read_byte(GIF_file,&(context->Palette[color_index].R));
for (color_index=0;color_index<nb_colors;color_index++)
Read_byte(GIF_file,&(context->Palette[color_index].G));
for (color_index=0;color_index<nb_colors;color_index++)
Read_byte(GIF_file,&(context->Palette[color_index].B));
// Load the palette
for(color_index=0;color_index<nb_colors;color_index++)
{
Read_byte(GIF_file,&(context->Palette[color_index].R));
Read_byte(GIF_file,&(context->Palette[color_index].G));
Read_byte(GIF_file,&(context->Palette[color_index].B));
}
}
Palette_loaded(context);
File_error=0;
if (!Read_byte(GIF_file,&(initial_nb_bits)))
File_error=1;
value_clr =nb_colors+0;
value_eof =nb_colors+1;
alphabet_free=nb_colors+2;
GIF_nb_bits =initial_nb_bits;
value_clr =(1<<initial_nb_bits)+0;
value_eof =(1<<initial_nb_bits)+1;
alphabet_free=(1<<initial_nb_bits)+2;
GIF_nb_bits =initial_nb_bits + 1;
alphabet_max =((1 << GIF_nb_bits)-1);
GIF_interlaced =(IDB.Indicator & 0x40);
GIF_pass =0;
/*Init_lecture();*/
File_error=0;
GIF_finished_interlaced_image=0;
//////////////////////////////////////////// DECOMPRESSION LZW //
@ -2057,9 +2186,9 @@ void Load_GIF(T_IO_Context * context)
}
else // Code Clear rencontré
{
GIF_nb_bits =initial_nb_bits;
GIF_nb_bits =initial_nb_bits + 1;
alphabet_max =((1 << GIF_nb_bits)-1);
alphabet_free =nb_colors+2;
alphabet_free =(1<<initial_nb_bits)+2;
special_case =GIF_get_next_code();
old_code =GIF_current_code;
GIF_new_pixel(context, &IDB, GIF_current_code);
@ -2251,15 +2380,19 @@ void Save_GIF(T_IO_Context * context)
Write_byte(GIF_file,LSDB.Aspect) )
{
// Le LSDB a été correctement écrit.
int i;
// On sauve la palette
if (Write_bytes(GIF_file,context->Palette,768))
for(i=0;i<256 && !File_error;i++)
{
if (!Write_byte(GIF_file,context->Palette[i].R)
||!Write_byte(GIF_file,context->Palette[i].G)
||!Write_byte(GIF_file,context->Palette[i].B))
File_error=1;
}
if (!File_error)
{
// La palette a été correctement écrite.
// Le jour où on se servira des blocks d'extensions pour placer
// des commentaires, on le fera ici.
// Ecriture de la transparence
//Write_bytes(GIF_file,"\x21\xF9\x04\x01\x00\x00\xNN\x00",8);
@ -2275,6 +2408,26 @@ void Save_GIF(T_IO_Context * context)
Write_byte(GIF_file,strlen(context->Comment));
Write_bytes(GIF_file,context->Comment,strlen(context->Comment)+1);
}
// Write cycling colors
if (context->Color_cycles)
{
int i;
Write_bytes(GIF_file,"\x21\xff\x0B" "CRNG\0\0\0\0" "1.0",14);
Write_byte(GIF_file,context->Color_cycles*6);
for (i=0; i<context->Color_cycles; i++)
{
word flags=0;
flags|= context->Cycle_range[i].Speed?1:0; // Cycling or not
flags|= context->Cycle_range[i].Inverse?2:0; // Inverted
Write_word_be(GIF_file,context->Cycle_range[i].Speed*78); // Rate
Write_word_be(GIF_file,flags); // Flags
Write_byte(GIF_file,context->Cycle_range[i].Start); // Min color
Write_byte(GIF_file,context->Cycle_range[i].End); // Max color
}
Write_byte(GIF_file,0);
}
// Loop on all layers
for (current_layer=0;
@ -2282,7 +2435,7 @@ void Save_GIF(T_IO_Context * context)
current_layer++)
{
// Write a Graphic Control Extension
char GCE_block[] = "\x21\xF9\x04\x04\x05\x00\x00\x00";
byte GCE_block[] = "\x21\xF9\x04\x04\x05\x00\x00\x00";
// 'Default' values:
// Disposal method "Do not dispose"
// Duration 5/100s (minimum viable value for current web browsers)
@ -2542,7 +2695,6 @@ void Save_GIF(T_IO_Context * context)
//////////////////////////////////// PCX ////////////////////////////////////
#pragma pack(1)
typedef struct
{
byte Manufacturer; // |_ Il font chier ces cons! Ils auraient pu
@ -2564,7 +2716,6 @@ typedef struct
word Screen_Y; // | l'écran d'origine
byte Filler[54]; // Ca... J'adore!
} T_PCX_Header;
#pragma pack()
T_PCX_Header PCX_header;
@ -3010,14 +3161,14 @@ void Save_PCX(T_IO_Context * context)
Write_word_le(file,PCX_header.Y_max) &&
Write_word_le(file,PCX_header.X_dpi) &&
Write_word_le(file,PCX_header.Y_dpi) &&
Write_bytes(file,&(PCX_header.Palette_16c),sizeof(PCX_header.Palette_16c)) &&
Write_bytes(file,&(PCX_header.Palette_16c),48) &&
Write_bytes(file,&(PCX_header.Reserved),1) &&
Write_bytes(file,&(PCX_header.Plane),1) &&
Write_word_le(file,PCX_header.Bytes_per_plane_line) &&
Write_word_le(file,PCX_header.Palette_info) &&
Write_word_le(file,PCX_header.Screen_X) &&
Write_word_le(file,PCX_header.Screen_Y) &&
Write_bytes(file,&(PCX_header.Filler),sizeof(PCX_header.Filler)) )
Write_bytes(file,&(PCX_header.Filler),54) )
{
line_size=PCX_header.Bytes_per_plane_line*PCX_header.Plane;
@ -3102,7 +3253,7 @@ void Test_SCx(T_IO_Context * context)
if ((file=fopen(filename, "rb")))
{
// Lecture et vérification de la signature
if (Read_bytes(file,SCx_header.Filler1,sizeof(SCx_header.Filler1))
if (Read_bytes(file,SCx_header.Filler1,4)
&& Read_word_le(file, &(SCx_header.Width))
&& Read_word_le(file, &(SCx_header.Height))
&& Read_byte(file, &(SCx_header.Filler2))
@ -3138,7 +3289,7 @@ void Load_SCx(T_IO_Context * context)
{
file_size=File_length_file(file);
if (Read_bytes(file,SCx_header.Filler1,sizeof(SCx_header.Filler1))
if (Read_bytes(file,SCx_header.Filler1,4)
&& Read_word_le(file, &(SCx_header.Width))
&& Read_word_le(file, &(SCx_header.Height))
&& Read_byte(file, &(SCx_header.Filler2))
@ -3259,7 +3410,7 @@ void Save_SCx(T_IO_Context * context)
SCx_header.Filler2=0xAF;
SCx_header.Planes=0x00;
if (Write_bytes(file,SCx_header.Filler1,sizeof(SCx_header.Filler1))
if (Write_bytes(file,SCx_header.Filler1,4)
&& Write_word_le(file, SCx_header.Width)
&& Write_word_le(file, SCx_header.Height)
&& Write_byte(file, SCx_header.Filler2)
@ -3294,6 +3445,44 @@ void Save_SCx(T_IO_Context * context)
}
}
//////////////////////////////////// XPM ////////////////////////////////////
void Save_XPM(T_IO_Context* context)
{
FILE* file;
char filename[MAX_PATH_CHARACTERS];
int i,j;
Get_full_filename(filename, context->File_name, context->File_directory);
File_error = 0;
file = fopen(filename, "w");
if (file == NULL)
{
File_error = 1;
return;
}
fprintf(file, "/* XPM */\nstatic char* pixmap[] = {\n");
fprintf(file, "\"%d %d 256 2\",\n", context->Width, context->Height);
for (i = 0; i < 256; i++)
{
fprintf(file,"\"%2.2X c #%2.2x%2.2x%2.2x\",\n", i, context->Palette[i].R, context->Palette[i].G,
context->Palette[i].B);
}
for (j = 0; j < context->Height; j++)
{
fprintf(file, "\"");
for (i = 0; i < context->Width; i++)
{
fprintf(file, "%2.2X", Get_pixel(context, i, j));
}
fprintf(file,"\"\n");
}
fclose(file);
}
//////////////////////////////////// PNG ////////////////////////////////////
@ -3322,7 +3511,71 @@ void Test_PNG(T_IO_Context * context)
fclose(file);
}
}
/// Used by a callback in Load_PNG
T_IO_Context * PNG_current_context;
int PNG_read_unknown_chunk(__attribute__((unused)) png_structp ptr, png_unknown_chunkp chunk)
{
// png_unknown_chunkp members:
// png_byte name[5];
// png_byte *data;
// png_size_t size;
if (!strcmp((const char *)chunk->name, "crNg"))
{
// Color animation. Similar to a LBM CRNG chunk.
unsigned int i;
byte *chunk_ptr = chunk->data;
// Should be a multiple of 6
if (chunk->size % 6)
return (-1);
for(i=0;i<chunk->size/6 && i<16; i++)
{
word rate;
word flags;
byte min_col;
byte max_col;
// Rate (big-endian word)
rate = *(chunk_ptr++) << 8;
rate |= *(chunk_ptr++);
// Flags (big-endian)
flags = *(chunk_ptr++) << 8;
flags |= *(chunk_ptr++);
// Min color
min_col = *(chunk_ptr++);
// Max color
max_col = *(chunk_ptr++);
// Check validity
if (min_col != max_col)
{
// Valid cycling range
if (max_col<min_col)
SWAP_BYTES(min_col,max_col)
PNG_current_context->Cycle_range[i].Start=min_col;
PNG_current_context->Cycle_range[i].End=max_col;
PNG_current_context->Cycle_range[i].Inverse=(flags&2)?1:0;
PNG_current_context->Cycle_range[i].Speed=(flags&1) ? rate/78 : 0;
PNG_current_context->Color_cycles=i+1;
}
}
return (1); // >0 = success
}
return (0); /* did not recognize */
}
png_bytep * Row_pointers;
// -- Lire un fichier au format PNG -----------------------------------------
void Load_PNG(T_IO_Context * context)
@ -3360,6 +3613,7 @@ void Load_PNG(T_IO_Context * context)
{
png_byte color_type;
png_byte bit_depth;
png_voidp user_chunk_ptr;
// Setup a return point. If a pnglib loading error occurs
// in this if(), the else will be executed.
@ -3368,11 +3622,18 @@ void Load_PNG(T_IO_Context * context)
png_init_io(png_ptr, file);
// Inform pnglib we already loaded the header.
png_set_sig_bytes(png_ptr, 8);
// Hook the handler for unknown chunks
user_chunk_ptr = png_get_user_chunk_ptr(png_ptr);
png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr, &PNG_read_unknown_chunk);
// This is a horrid way to pass parameters, but we don't get
// much choice. PNG loader can't be reintrant.
PNG_current_context=context;
// Load file information
png_read_info(png_ptr, info_ptr);
color_type = info_ptr->color_type;
bit_depth = info_ptr->bit_depth;
color_type = png_get_color_type(png_ptr,info_ptr);
bit_depth = png_get_bit_depth(png_ptr,info_ptr);
// If it's any supported file
// (Note: As of writing this, this test covers every possible
@ -3425,9 +3686,9 @@ void Load_PNG(T_IO_Context * context)
}
}
if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA)
Pre_load(context,info_ptr->width,info_ptr->height,File_length_file(file),FORMAT_PNG,PIXEL_SIMPLE,1);
Pre_load(context,png_get_image_width(png_ptr,info_ptr),png_get_image_height(png_ptr,info_ptr),File_length_file(file),FORMAT_PNG,PIXEL_SIMPLE,1);
else
Pre_load(context, info_ptr->width,info_ptr->height,File_length_file(file),FORMAT_PNG,context->Ratio,0);
Pre_load(context,png_get_image_width(png_ptr,info_ptr),png_get_image_height(png_ptr,info_ptr),File_length_file(file),FORMAT_PNG,context->Ratio,0);
if (File_error==0)
{
@ -3535,8 +3796,8 @@ void Load_PNG(T_IO_Context * context)
}
}
context->Width=info_ptr->width;
context->Height=info_ptr->height;
context->Width=png_get_image_width(png_ptr,info_ptr);
context->Height=png_get_image_height(png_ptr,info_ptr);
png_set_interlace_handling(png_ptr);
png_read_update_info(png_ptr, info_ptr);
@ -3556,7 +3817,7 @@ void Load_PNG(T_IO_Context * context)
// 8bpp
for (y=0; y<context->Height; y++)
Row_pointers[y] = (png_byte*) malloc(info_ptr->rowbytes);
Row_pointers[y] = (png_byte*) malloc(png_get_rowbytes(png_ptr,info_ptr));
row_pointers_allocated = 1;
png_read_image(png_ptr, Row_pointers);
@ -3575,7 +3836,7 @@ void Load_PNG(T_IO_Context * context)
// It's a preview
// Unfortunately we need to allocate loads of memory
for (y=0; y<context->Height; y++)
Row_pointers[y] = (png_byte*) malloc(info_ptr->rowbytes);
Row_pointers[y] = (png_byte*) malloc(png_get_rowbytes(png_ptr,info_ptr));
row_pointers_allocated = 1;
png_read_image(png_ptr, Row_pointers);
@ -3646,6 +3907,8 @@ void Save_PNG(T_IO_Context * context)
byte * pixel_ptr;
png_structp png_ptr;
png_infop info_ptr;
png_unknown_chunk crng_chunk;
byte cycle_data[16*6]; // Storage for color-cycling data, referenced by crng_chunk
Get_full_filename(filename, context->File_name, context->File_directory);
File_error=0;
@ -3674,9 +3937,15 @@ void Save_PNG(T_IO_Context * context)
{
// Commentaires texte PNG
// Cette partie est optionnelle
#ifdef PNG_iTXt_SUPPORTED
png_text text_ptr[2] = {
{-1, "Software", "Grafx2", 6, 0, NULL, NULL},
{-1, "Title", NULL, 0, 0, NULL, NULL}
#else
png_text text_ptr[2] = {
{-1, "Software", "Grafx2", 6},
{-1, "Title", NULL, 0}
#endif
};
int nb_text_chunks=1;
if (context->Comment[0])
@ -3710,7 +3979,58 @@ void Save_PNG(T_IO_Context * context)
break;
default:
break;
}
}
// Write cycling colors
if (context->Color_cycles)
{
// Save a chunk called 'crNg'
// The case is selected by the following rules from PNG standard:
// char 1: non-mandatory = lowercase
// char 2: private (not standard) = lowercase
// char 3: reserved = always uppercase
// char 4: can be copied by editors = lowercase
// First, turn our nice structure into byte array
// (just to avoid padding in structures)
byte *chunk_ptr = cycle_data;
int i;
for (i=0; i<context->Color_cycles; i++)
{
word flags=0;
flags|= context->Cycle_range[i].Speed?1:0; // Cycling or not
flags|= context->Cycle_range[i].Inverse?2:0; // Inverted
// Big end of Rate
*(chunk_ptr++) = (context->Cycle_range[i].Speed*78) >> 8;
// Low end of Rate
*(chunk_ptr++) = (context->Cycle_range[i].Speed*78) & 0xFF;
// Big end of Flags
*(chunk_ptr++) = (flags) >> 8;
// Low end of Flags
*(chunk_ptr++) = (flags) & 0xFF;
// Min color
*(chunk_ptr++) = context->Cycle_range[i].Start;
// Max color
*(chunk_ptr++) = context->Cycle_range[i].End;
}
// Build one unknown_chuck structure
memcpy(crng_chunk.name, "crNg",5);
crng_chunk.data=cycle_data;
crng_chunk.size=context->Color_cycles*6;
crng_chunk.location=PNG_HAVE_PLTE;
// Give it to libpng
png_set_unknown_chunks(png_ptr, info_ptr, &crng_chunk, 1);
// libpng seems to ignore the location I provided earlier.
png_set_unknown_chunk_location(png_ptr, info_ptr, 0, PNG_HAVE_PLTE);
}
png_write_info(png_ptr, info_ptr);
/* ecriture des pixels de l'image */

View File

@ -2,6 +2,7 @@
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2009 Franck Charlet
Copyright 2008 Peter Gordon
Copyright 2008 Yves Rizoud
@ -22,14 +23,22 @@
along with Grafx2; if not, see <http://www.gnu.org/licenses/>
*/
#include <SDL_syswm.h>
#if defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__)
#include <proto/dos.h>
#include <sys/types.h>
#include <dirent.h>
#define isHidden(x) (0)
#elif defined (__MINT__)
#include <mint/sysbind.h>
#include <dirent.h>
#define isHidden(x) (0)
#elif defined(__WIN32__)
#include <dirent.h>
#include <windows.h>
#include <commdlg.h>
#define isHidden(x) (GetFileAttributesA((x)->d_name)&FILE_ATTRIBUTE_HIDDEN)
#else
#include <dirent.h>
@ -62,12 +71,66 @@
#include "help.h"
#include "filesel.h"
#define NORMAL_FILE_COLOR MC_Light // color du texte pour une ligne de fichier non sélectionné
#define NORMAL_DIRECTORY_COLOR MC_Dark // color du texte pour une ligne de répertoire non sélectionné
#define NORMAL_BACKGROUND_COLOR MC_Black // color du fond pour une ligne non sélectionnée
#define SELECTED_FILE_COLOR MC_White // color du texte pour une ligne de fichier sélectionnée
#define SELECTED_DIRECTORY_COLOR MC_Light // color du texte pour une ligne de repértoire sélectionnée
#define SELECTED_BACKGROUND_COLOR MC_Dark // color du fond pour une ligne sélectionnée
#define NORMAL_FILE_COLOR MC_Light // color du texte pour une ligne de
// fichier non sélectionné
#define NORMAL_DIRECTORY_COLOR MC_Dark // color du texte pour une ligne de
// répertoire non sélectionné
#define NORMAL_BACKGROUND_COLOR MC_Black // color du fond pour une ligne
// non sélectionnée
#define SELECTED_FILE_COLOR MC_White // color du texte pour une ligne de
// fichier sélectionnée
#define SELECTED_DIRECTORY_COLOR MC_Light // color du texte pour une ligne de
// repértoire sélectionnée
#define SELECTED_BACKGROUND_COLOR MC_Dark // color du fond pour une ligne
// sélectionnée
// -- Native fileselector for WIN32
// Returns 0 if all ok, something else if failed
byte Native_filesel(byte load)
{
//load = load;
#ifdef __WIN32__
OPENFILENAME ofn;
char szFileName[MAX_PATH] = "";
SDL_SysWMinfo wminfo;
HWND hwnd;
SDL_VERSION(&wminfo.version);
SDL_GetWMInfo(&wminfo);
hwnd = wminfo.window;
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.lpstrFilter = "Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0";
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_EXPLORER;
if(load) ofn.Flags |= OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
ofn.lpstrDefExt = "txt";
if(load)
{
if (GetOpenFileName(&ofn))
// Do something usefull with the filename stored in szFileName
return 0;
else
// error - check if its just user pressing cancel or something else
return CommDlgExtendedError();
} else if(GetSaveFileName(&ofn)) {
return 0;
} else {
// Check if cancel
return CommDlgExtendedError();
}
#else
return 255; // fail !
#endif
}
// -- "Standard" fileselector for other platforms
// -- Fileselector data
@ -86,7 +149,7 @@ static char Selector_filename[256];
void Recount_files(T_Fileselector *list)
{
T_Fileselector_item *item;
list->Nb_files=0;
list->Nb_directories=0;
list->Nb_elements=0;
@ -146,30 +209,48 @@ void Free_fileselector_list(T_Fileselector *list)
Recount_files(list);
}
char * Format_filename(const char * fname, int type)
char * Format_filename(const char * fname, word max_length, int type)
{
static char result[19];
static char result[40];
int c;
int other_cursor;
int pos_last_dot;
// safety
if (max_length>40)
max_length=40;
if (strcmp(fname,PARENT_DIR)==0)
{
strcpy(result,"<-PARENT DIRECTORY");
// Append spaces
for (c=18; c<max_length-1; c++)
result[c]=' ';
result[c]='\0';
}
else if (fname[0]=='.' || type==1 || type==2)
{
// Files ".something" or drives or directories: Aligned left on 18 chars max
strcpy(result," ");
for (c=0;fname[c]!='\0' && c < 18;c++)
// Files ".something" or drives or directories: Aligned left on (max_length-1) chars max
// Initialize as all spaces
for (c=0; c<max_length-1; c++)
result[c]=' ';
result[c]='\0';
for (c=0;fname[c]!='\0' && c < max_length-1;c++)
result[c]=fname[c];
// A special character indicates the filename is truncated
if (c >= 18)
result[17]=ELLIPSIS_CHARACTER;
if (c >= max_length-1)
result[max_length-2]=ELLIPSIS_CHARACTER;
}
else
{
strcpy(result," . ");
// Initialize as all spaces
for (c = 0; c<max_length-1; c++)
result[c]=' ';
result[c]='\0';
result[max_length-5]='.';
// Look for the last dot in filename
pos_last_dot = -1;
for (c = 0; fname[c]!='\0'; c++)
@ -179,9 +260,9 @@ char * Format_filename(const char * fname, int type)
// Copy the part before the dot
for (c=0; c!=pos_last_dot && fname[c]!='\0'; c++)
{
if (c > 13)
if (c > max_length-6)
{
result[13]=ELLIPSIS_CHARACTER;
result[max_length-6]=ELLIPSIS_CHARACTER;
break;
}
result[c]=fname[c];
@ -190,7 +271,7 @@ char * Format_filename(const char * fname, int type)
// Ensuite on recopie la partie qui suit le point (si nécessaire):
if (pos_last_dot != -1)
{
for (c = pos_last_dot+1,other_cursor=15;fname[c]!='\0' && other_cursor < 18;c++,other_cursor++)
for (c = pos_last_dot+1,other_cursor=max_length-4;fname[c]!='\0' && other_cursor < max_length-1;c++,other_cursor++)
result[other_cursor]=fname[c];
}
}
@ -199,25 +280,29 @@ char * Format_filename(const char * fname, int type)
// -- Rajouter a la liste des elements de la liste un element ---------------
void Add_element_to_list(T_Fileselector *list, const char * fname, int type)
void Add_element_to_list(T_Fileselector *list, const char * full_name, const char *short_name, int type, byte icon)
// Cette procedure ajoute a la liste chainee un fichier passé en argument.
{
// Pointeur temporaire d'insertion
// Working element
T_Fileselector_item * temp_item;
// On alloue de la place pour un nouvel element
temp_item=(T_Fileselector_item *)malloc(sizeof(T_Fileselector_item));
// Allocate enough room for one struct + the visible label
temp_item=(T_Fileselector_item *)malloc(sizeof(T_Fileselector_item)+strlen(short_name));
// On met a jour le nouvel emplacement:
strcpy(temp_item->Short_name,Format_filename(fname, type));
strcpy(temp_item->Full_name,fname);
// Initialize element
strcpy(temp_item->Short_name,short_name);
strcpy(temp_item->Full_name,full_name);
temp_item->Type = type;
temp_item->Icon = icon;
// Doubly-linked
temp_item->Next =list->First;
temp_item->Previous=NULL;
if (list->First!=NULL)
list->First->Previous=temp_item;
// Put new element at the beginning
list->First=temp_item;
}
@ -275,8 +360,25 @@ void Read_list_of_files(T_Fileselector *list, byte selected_format)
// Après effacement, il ne reste ni fichier ni répertoire dans la liste
// On lit tous les répertoires:
#if defined (__MINT__)
static char path[1024];
static char path2[1024];
path[0]='\0';
path2[0]='\0';
char currentDrive='A';
currentDrive=currentDrive+Dgetdrv();
Dgetpath(path,0);
sprintf(path2,"%c:\%s",currentDrive,path);
strcat(path2,PATH_SEPARATOR);
current_directory=opendir(path2);
#else
current_path=getcwd(NULL,0);
current_directory=opendir(current_path);
#endif
while ((entry=readdir(current_directory)))
{
// On ignore le répertoire courant
@ -294,7 +396,7 @@ void Read_list_of_files(T_Fileselector *list, byte selected_format)
!isHidden(entry)))
{
// On rajoute le répertoire à la liste
Add_element_to_list(list, entry->d_name, 1);
Add_element_to_list(list, entry->d_name, Format_filename(entry->d_name, 19, 1), 1, ICON_NONE);
list->Nb_directories++;
}
else if (S_ISREG(Infos_enreg.st_mode) && //Il s'agit d'un fichier
@ -307,7 +409,7 @@ void Read_list_of_files(T_Fileselector *list, byte selected_format)
if (Check_extension(entry->d_name, ext))
{
// On rajoute le fichier à la liste
Add_element_to_list(list, entry->d_name, 0);
Add_element_to_list(list, entry->d_name, Format_filename(entry->d_name, 19, 0), 0, ICON_NONE);
list->Nb_files++;
// Stop searching
ext=NULL;
@ -323,12 +425,35 @@ void Read_list_of_files(T_Fileselector *list, byte selected_format)
}
#if defined(__MORPHOS__) || defined(__AROS__) || defined (__amigaos4__) || defined(__amigaos__)
Add_element_to_list(list, "/",1); // on amiga systems, / means parent. And there is no ..
Add_element_to_list(list, "/", Format_filename("/",19,1), 1, ICON_NONE); // on amiga systems, / means parent. And there is no ..
list->Nb_directories ++;
#elif defined (__MINT__)
T_Fileselector_item *item=NULL;
// check if ".." exists if not add it
// FreeMinT lists ".." already, but this is not so for TOS
// simply adding it will cause double PARENT_DIR under FreeMiNT
bool bFound= false;
for (item = list->First; (((item != NULL) && (bFound==false))); item = item->Next){
if (item->Type == 1){
if(strncmp(item->Full_name,"..",(sizeof(char)*2))==0) bFound=true;
}
}
if(!bFound){
Add_element_to_list(list, "..",1,Format_filename("/",19,1),ICON_NONE); // add if not present
list->Nb_directories ++;
}
#endif
closedir(current_directory);
#if defined (__MINT__)
#else
free(current_path);
#endif
current_path = NULL;
Recount_files(list);
@ -375,7 +500,7 @@ void Read_list_of_drives(T_Fileselector *list)
{
bstrtostr( dl->dol_Name, tmp, 254 );
strcat( tmp, ":" );
Add_element_to_list(list, tmp, 2 );
Add_element_to_list(list, tmp, Format_filename(tmp, 19, 2), 2, ICON_NONE );
list->Nb_directories++;
}
UnLockDosList( LDF_VOLUMES | LDF_READ );
@ -387,6 +512,8 @@ void Read_list_of_drives(T_Fileselector *list)
int drive_bits = GetLogicalDrives();
int drive_index;
int bit_index;
byte icon;
// Sous Windows, on a la totale, presque aussi bien que sous DOS:
drive_index = 0;
for (bit_index=0; bit_index<26 && drive_index<23; bit_index++)
@ -395,35 +522,51 @@ void Read_list_of_drives(T_Fileselector *list)
{
// On a ce lecteur, il faut maintenant déterminer son type "physique".
// pour profiter des jolies icones de X-man.
int drive_type;
char drive_path[]="A:\\";
// Cette API Windows est étrange, je dois m'y faire...
drive_path[0]='A'+bit_index;
switch (GetDriveType(drive_path))
{
case DRIVE_CDROM:
drive_type=ICON_CDROM;
icon=ICON_CDROM;
break;
case DRIVE_REMOTE:
drive_type=ICON_NETWORK;
icon=ICON_NETWORK;
break;
case DRIVE_REMOVABLE:
drive_type=ICON_FLOPPY_3_5;
icon=ICON_FLOPPY_3_5;
break;
case DRIVE_FIXED:
drive_type=ICON_HDD;
icon=ICON_HDD;
break;
default:
drive_type=ICON_NETWORK;
icon=ICON_NETWORK;
break;
}
drive_name[0]='A'+bit_index;
Add_element_to_list(list, drive_name,2);
Add_element_to_list(list, drive_name, Format_filename(drive_name,18,2), 2, icon);
list->Nb_directories++;
drive_index++;
}
}
}
#elif defined(__MINT__)
char drive_name[]="A:\\";
unsigned long drive_bits = Drvmap(); //get drive map bitfield
int drive_index;
int bit_index;
drive_index = 0;
for (bit_index=0; bit_index<32; bit_index++)
{
if ( (1 << bit_index) & drive_bits )
{
drive_name[0]='A'+bit_index;
Add_element_to_list(list, drive_name,Format_filename(drive_name,19,2),2,ICON_NONE);
list->Nb_directories++;
drive_index++;
}
}
#else
{
//Sous les différents unix, on va mettre
@ -440,11 +583,11 @@ void Read_list_of_drives(T_Fileselector *list)
#else
char * home_dir = getenv("HOME");
#endif
Add_element_to_list(list, "/", 2);
Add_element_to_list(list, "/", Format_filename("/",19,2), 2, ICON_NONE);
list->Nb_directories++;
if(home_dir)
{
Add_element_to_list(list, home_dir, 2);
Add_element_to_list(list, home_dir, Format_filename(home_dir, 19, 2), 2, ICON_NONE);
list->Nb_directories++;
}
@ -454,7 +597,7 @@ void Read_list_of_drives(T_Fileselector *list)
{
if(mount_points_list->me_dummy == 0 && strcmp(mount_points_list->me_mountdir,"/") && strcmp(mount_points_list->me_mountdir,"/home"))
{
Add_element_to_list(list, mount_points_list->me_mountdir,2);
Add_element_to_list(list, mount_points_list->me_mountdir, Format_filename(mount_points_list->me_mountdir, 19, 2), 2, ICON_NONE);
list->Nb_directories++;
}
next = mount_points_list -> me_next;
@ -473,6 +616,15 @@ void Read_list_of_drives(T_Fileselector *list)
Recount_files(list);
}
// Comparison of file names:
#ifdef WIN32
// case-insensitive
#define FILENAME_COMPARE strcasecmp
#else
// case-sensitive
#define FILENAME_COMPARE strcmp
#endif
// -- Tri de la liste des fichiers et répertoires ---------------------------
void Sort_list_of_files(T_Fileselector *list)
@ -514,7 +666,7 @@ void Sort_list_of_files(T_Fileselector *list)
// Si les deux éléments sont de même type et que le nom du suivant
// est plus petit que celui du courant -> need_swap
else if ( (current_item->Type==next_item->Type) &&
(strcmp(current_item->Full_name,next_item->Full_name)>0) )
(FILENAME_COMPARE(current_item->Full_name,next_item->Full_name)>0) )
need_swap=1;
@ -640,7 +792,14 @@ void Display_file_list(T_Fileselector *list, short offset_first,short selector_o
}
// On affiche l'élément
Print_in_window(8,95+index*8,current_item->Short_name,text_color,background_color);
if (current_item->Icon != ICON_NONE)
{
// Name preceded by an icon
Print_in_window(16,95+index*8,current_item->Short_name,text_color,background_color);
Window_display_icon_sprite(8,95+index*8,current_item->Icon);
} else
// Name without icon
Print_in_window(8,95+index*8,current_item->Short_name,text_color,background_color);
// On passe à la ligne suivante
selector_offset--;
@ -889,7 +1048,7 @@ void Prepare_and_display_filelist(short Position, short offset, T_Scroller_butto
{
button->Nb_elements=Filelist.Nb_elements;
button->Position=Position;
Compute_slider_cursor_height(button);
Compute_slider_cursor_length(button);
Window_draw_slider(button);
// On efface les anciens noms de fichier:
Window_rectangle(8-1,95-1,144+2,80+2,MC_Black);
@ -984,12 +1143,8 @@ short Find_file_in_fileselector(T_Fileselector *list, const char * fname)
return close_match;
}
void Highlight_file(char * fname)
void Highlight_file(short index)
{
short index;
index=Find_file_in_fileselector(&Filelist, fname);
if ((Filelist.Nb_elements<=10) || (index<5))
{
@ -1012,15 +1167,17 @@ void Highlight_file(char * fname)
}
char * Find_filename_match(T_Fileselector *list, char * fname)
short Find_filename_match(T_Fileselector *list, char * fname)
{
char * best_name_ptr;
short best_match;
T_Fileselector_item * current_item;
byte matching_letters=0;
byte counter;
best_name_ptr=NULL;
short item_number;
byte matching_letters=0;
byte counter;
best_match=-1;
item_number=0;
for (current_item=list->First; current_item!=NULL; current_item=current_item->Next)
{
if ( (!Config.Find_file_fast)
@ -1031,12 +1188,96 @@ char * Find_filename_match(T_Fileselector *list, char * fname)
if (counter>matching_letters)
{
matching_letters=counter;
best_name_ptr=current_item->Full_name;
best_match=item_number;
}
}
item_number++;
}
return best_name_ptr;
return best_match;
}
// Quicksearch system
char quicksearch_filename[MAX_PATH_CHARACTERS]="";
void Reset_quicksearch(void)
{
quicksearch_filename[0]='\0';
}
short Quicksearch(T_Fileselector *selector)
{
int len;
short most_matching_item;
// Autre => On se place sur le nom de fichier qui correspond
len=strlen(quicksearch_filename);
if (Key_ANSI>= ' ' && Key_ANSI < 255 && len<50)
{
quicksearch_filename[len]=Key_ANSI;
quicksearch_filename[len+1]='\0';
most_matching_item=Find_filename_match(selector, quicksearch_filename);
if ( most_matching_item >= 0 )
{
return most_matching_item;
}
*quicksearch_filename=0;
}
return -1;
}
// Translated from Highlight_file
void Locate_list_item(T_List_button * list, T_Fileselector * selector, short selected_item)
{
// Safety bounds
if (selected_item<0)
selected_item=0;
else if (selected_item>=list->Scroller->Nb_elements)
selected_item=list->Scroller->Nb_elements-1;
if ((list->Scroller->Nb_elements<=list->Scroller->Nb_visibles) || (selected_item<(list->Scroller->Nb_visibles/2)))
{
list->List_start=0;
list->Cursor_position=selected_item;
}
else
{
if (selected_item>=list->Scroller->Nb_elements-(list->Scroller->Nb_visibles/2))
{
list->List_start=list->Scroller->Nb_elements-list->Scroller->Nb_visibles;
list->Cursor_position=selected_item-list->List_start;
}
else
{
list->List_start=selected_item-(list->Scroller->Nb_visibles/2-1);
list->Cursor_position=(list->Scroller->Nb_visibles/2-1);
}
}
}
int Quicksearch_list(T_List_button * list, T_Fileselector * selector)
{
// Try Quicksearch
short selected_item=Quicksearch(selector);
if (selected_item>=0 && selected_item!=list->Cursor_position+list->List_start)
{
Locate_list_item(list, selector, selected_item);
Hide_cursor();
// Mise à jour du scroller
list->Scroller->Position=list->List_start;
Window_draw_slider(list->Scroller);
Window_redraw_list(list);
Display_cursor();
// Store the selected value as attribute2
Window_attribute2=list->List_start + list->Cursor_position;
// Return the control ID of the list.
return list->Number;
}
return 0;
}
byte Button_Load_or_Save(byte load, T_IO_Context *context)
@ -1048,17 +1289,20 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
T_Dropdown_button * formats_dropdown;
T_Dropdown_button * bookmark_dropdown[4];
short temp;
unsigned int format;
int dummy=0; // Sert à appeler SDL_GetKeyState
byte save_or_load_image=0;
byte has_clicked_ok=0;// Indique si on a clické sur Load ou Save ou sur
//un bouton enclenchant Load ou Save juste après.
byte initial_back_color; // | fout en l'air (c'te conne).
char previous_directory[MAX_PATH_CHARACTERS]; // Répertoire d'où l'on vient après un CHDIR
char quicksearch_filename[MAX_PATH_CHARACTERS]="";
char save_filename[MAX_PATH_CHARACTERS];
char initial_comment[COMMENT_SIZE+1];
char * most_matching_filename;
short window_shortcut;
Reset_quicksearch();
// if (Native_filesel(load) != 0); // TODO : handle this
if (context->Type == CONTEXT_MAIN_IMAGE)
window_shortcut = load?(0x100+BUTTON_LOAD):(0x100+BUTTON_SAVE);
@ -1099,7 +1343,7 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
}
// Affichage du commentaire
if (Get_fileformat(Main_format)->Comment)
Print_in_window(47,70,context->Comment,MC_Black,MC_Light);
Print_in_window(45,70,context->Comment,MC_Black,MC_Light);
}
Window_set_normal_button(253,180,51,14,"Cancel",0,1,KEY_ESC); // 2
@ -1124,11 +1368,11 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
Get_fileformat(Main_format)->Label,
1,0,1,RIGHT_SIDE|LEFT_SIDE,0); // 6
for (temp=0; temp < NB_KNOWN_FORMATS; temp++)
for (format=0; format < Nb_known_formats(); format++)
{
if ((load && (File_formats[temp].Identifier <= FORMAT_ALL_FILES || File_formats[temp].Load)) ||
(!load && File_formats[temp].Save))
Window_dropdown_add_item(formats_dropdown,File_formats[temp].Identifier,File_formats[temp].Label);
if ((load && (File_formats[format].Identifier <= FORMAT_ALL_FILES || File_formats[format].Load)) ||
(!load && File_formats[format].Save))
Window_dropdown_add_item(formats_dropdown,File_formats[format].Identifier,File_formats[format].Label);
}
Print_in_window(70,18,"Format",MC_Dark,MC_Light);
@ -1161,13 +1405,30 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
// On prend bien soin de passer dans le répertoire courant (le bon qui faut! Oui madame!)
if (load)
{
#if defined(__MINT__)
chdir(Main_current_directory);
static char path[1024]={0};
Dgetpath(path,0);
strcat(path,PATH_SEPARATOR);
strcpy(Main_current_directory,path);
#else
chdir(Main_current_directory);
getcwd(Main_current_directory,256);
#endif
}
else
{
#if defined(__MINT__)
chdir(context->File_directory);
static char path[1024]={0};
Dgetpath(path,0);
strcat(path,PATH_SEPARATOR);
strcpy(Main_current_directory,path);
#else
getcwd(Main_current_directory,256);
#endif
}
// Affichage des premiers fichiers visibles:
@ -1181,7 +1442,7 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
// On affiche le nouveau nom de fichier
Print_filename_in_fileselector();
Highlight_file(context->File_name);
Highlight_file(Find_file_in_fileselector(&Filelist, context->File_name));
Prepare_and_display_filelist(Main_fileselector_position,Main_fileselector_offset,file_scroller);
}
@ -1309,7 +1570,8 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
// On vient de changer de nom de fichier, donc on doit s'appreter
// a rafficher une preview
New_preview_is_needed=1;
*quicksearch_filename=0;
Reset_quicksearch();
}
else
{
@ -1322,7 +1584,7 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
has_clicked_ok=1;
New_preview_is_needed=1;
*quicksearch_filename=0;
Reset_quicksearch();
}
}
Display_cursor();
@ -1340,26 +1602,40 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
Display_file_list(&Filelist, Main_fileselector_position,Main_fileselector_offset);
Display_cursor();
New_preview_is_needed=1;
*quicksearch_filename=0;
Reset_quicksearch();
break;
case 6 : // Scroller des formats
Hide_cursor();
// On met à jour le format de browsing du fileselect:
Main_format=Window_attribute2;
// Comme on change de liste, on se place en début de liste:
Main_fileselector_position=0;
Main_fileselector_offset=0;
// Affichage des premiers fichiers visibles:
Reload_list_of_files(Main_format,file_scroller);
Display_cursor();
New_preview_is_needed=1;
*quicksearch_filename=0;
case 6 : // Scroller des formats
// On met à jour le format de browsing du fileselect:
if (Main_format != Window_attribute2) {
char* savename = (char *)strdup(Selector_filename);
int nameLength = strlen(savename);
DEBUG(Selector_filename, 42);
Main_format = Window_attribute2;
// Comme on change de liste, on se place en début de liste:
Main_fileselector_position = 0;
Main_fileselector_offset = 0;
// Affichage des premiers fichiers visibles:
Hide_cursor();
Reload_list_of_files(Main_format, file_scroller);
New_preview_is_needed = 1;
Reset_quicksearch();
strcpy(Selector_filename, savename);
if (Get_fileformat(Main_format)->Default_extension[0] != '\0' &&
Selector_filename[nameLength - 4] == '.')
{
strcpy(Selector_filename + nameLength - 3,
Get_fileformat(Main_format)->Default_extension);
}
free(savename);
Print_filename_in_fileselector();
Display_cursor();
}
break;
case 7 : // Saisie d'un commentaire pour la sauvegarde
if ( (!load) && (Get_fileformat(Main_format)->Comment) )
{
Readline(45,70,context->Comment,32,0);
Readline(45, 70, context->Comment, 32, INPUT_TYPE_STRING);
Display_cursor();
}
break;
@ -1368,7 +1644,7 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
// Save the filename
strcpy(save_filename, Selector_filename);
if (Readline(82,48,Selector_filename,27,2))
if (Readline(82,48,Selector_filename,27,INPUT_TYPE_FILENAME))
{
// On regarde s'il faut rajouter une extension. C'est-à-dire s'il
// n'y a pas de '.' dans le nom du fichier.
@ -1382,7 +1658,7 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
if(!Directory_exists(Selector_filename))
{
strcat(Selector_filename, ".");
strcat(Selector_filename,Get_fileformat(Main_format)->Default_extension);
strcat(Selector_filename, Get_fileformat(Main_format)->Default_extension);
}
}
else
@ -1438,7 +1714,7 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
Prepare_and_display_filelist(Main_fileselector_position,Main_fileselector_offset,file_scroller);
Display_cursor();
New_preview_is_needed=1;
*quicksearch_filename=0;
Reset_quicksearch();
break;
default:
if (clicked_button>=10 && clicked_button<10+NB_BOOKMARKS)
@ -1451,11 +1727,10 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
case -1: // bouton lui-même: aller au répertoire mémorisé
if (Config.Bookmark_directory[clicked_button-10])
{
*quicksearch_filename=0;
strcpy(Selector_filename,Config.Bookmark_directory[clicked_button-10]);
Selected_type=1;
has_clicked_ok=1;
*quicksearch_filename=0;
Reset_quicksearch();
}
break;
@ -1490,7 +1765,7 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
strcpy(bookmark_label, Config.Bookmark_label[clicked_button-10]);
if (bookmark_label[7]==ELLIPSIS_CHARACTER)
bookmark_label[7]='\0';
if (Readline_ex(bookmark_dropdown[clicked_button-10]->Pos_X+3+10,bookmark_dropdown[clicked_button-10]->Pos_Y+2,bookmark_label,8,8,0,0))
if (Readline_ex(bookmark_dropdown[clicked_button-10]->Pos_X+3+10,bookmark_dropdown[clicked_button-10]->Pos_Y+2,bookmark_label,8,8,INPUT_TYPE_STRING,0))
strcpy(Config.Bookmark_label[clicked_button-10],bookmark_label);
Display_bookmark(bookmark_dropdown[clicked_button-10],clicked_button-10);
Display_cursor();
@ -1515,63 +1790,63 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
{
case SDLK_UNKNOWN : break;
case SDLK_DOWN : // Bas
*quicksearch_filename=0;
Reset_quicksearch();
Hide_cursor();
Selector_scroll_down(&Main_fileselector_position,&Main_fileselector_offset);
Scroll_fileselector(file_scroller);
Key=0;
break;
case SDLK_UP : // Haut
*quicksearch_filename=0;
Reset_quicksearch();
Hide_cursor();
Selector_scroll_up(&Main_fileselector_position,&Main_fileselector_offset);
Scroll_fileselector(file_scroller);
Key=0;
break;
case SDLK_PAGEDOWN : // PageDown
*quicksearch_filename=0;
Reset_quicksearch();
Hide_cursor();
Selector_page_down(&Main_fileselector_position,&Main_fileselector_offset,9);
Scroll_fileselector(file_scroller);
Key=0;
break;
case SDLK_PAGEUP : // PageUp
*quicksearch_filename=0;
Reset_quicksearch();
Hide_cursor();
Selector_page_up(&Main_fileselector_position,&Main_fileselector_offset,9);
Scroll_fileselector(file_scroller);
Key=0;
break;
case SDLK_END : // End
*quicksearch_filename=0;
Reset_quicksearch();
Hide_cursor();
Selector_end(&Main_fileselector_position,&Main_fileselector_offset);
Scroll_fileselector(file_scroller);
Key=0;
break;
case SDLK_HOME : // Home
*quicksearch_filename=0;
Reset_quicksearch();
Hide_cursor();
Selector_home(&Main_fileselector_position,&Main_fileselector_offset);
Scroll_fileselector(file_scroller);
Key=0;
break;
case KEY_MOUSEWHEELDOWN :
*quicksearch_filename=0;
Reset_quicksearch();
Hide_cursor();
Selector_page_down(&Main_fileselector_position,&Main_fileselector_offset,3);
Scroll_fileselector(file_scroller);
Key=0;
break;
case KEY_MOUSEWHEELUP :
*quicksearch_filename=0;
Reset_quicksearch();
Hide_cursor();
Selector_page_up(&Main_fileselector_position,&Main_fileselector_offset,3);
Scroll_fileselector(file_scroller);
Key=0;
break;
case SDLK_BACKSPACE : // Backspace
*quicksearch_filename=0;
Reset_quicksearch();
// Si le choix ".." est bien en tête des propositions...
if (!strcmp(Filelist.First->Full_name,PARENT_DIR))
{
@ -1585,6 +1860,8 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
default:
if (clicked_button<=0)
{
short selected_item;
if (Is_shortcut(Key,0x100+BUTTON_HELP))
{
Window_help(load?BUTTON_LOAD:BUTTON_SAVE, NULL);
@ -1595,30 +1872,22 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
clicked_button=2;
break;
}
// Autre => On se place sur le nom de fichier qui correspond
temp=strlen(quicksearch_filename);
if (Key_ANSI>= ' ' && Key_ANSI < 255 && temp<50)
selected_item=Quicksearch(&Filelist);
if (selected_item>=0)
{
quicksearch_filename[temp]=Key_ANSI;
quicksearch_filename[temp+1]='\0';
most_matching_filename=Find_filename_match(&Filelist, quicksearch_filename);
if ( (most_matching_filename) )
{
temp=Main_fileselector_position+Main_fileselector_offset;
Hide_cursor();
Highlight_file(most_matching_filename);
Highlight_file(selected_item);
Prepare_and_display_filelist(Main_fileselector_position,Main_fileselector_offset,file_scroller);
Display_cursor();
if (temp!=Main_fileselector_position+Main_fileselector_offset)
New_preview_is_needed=1;
}
else
*quicksearch_filename=0;
Key=0;
}
// Key=0; ?
}
else
*quicksearch_filename=0;
Reset_quicksearch();
}
if (has_clicked_ok)
@ -1643,13 +1912,20 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
// On doit rentrer dans le répertoire:
if (!chdir(Selector_filename))
{
#if defined (__MINT__)
static char path[1024]={0};
char currentDrive='A';
currentDrive=currentDrive+Dgetdrv();
Dgetpath(path,0);
sprintf(Main_current_directory,"%c:\%s",currentDrive,path);
#else
getcwd(Main_current_directory,256);
#endif
// On lit le nouveau répertoire
Read_list_of_files(&Filelist, Main_format);
Sort_list_of_files(&Filelist);
// On place la barre de sélection sur le répertoire d'où l'on vient
Highlight_file(previous_directory);
Highlight_file(Find_file_in_fileselector(&Filelist, previous_directory));
}
else
Error(0);
@ -1659,7 +1935,7 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
New_preview_is_needed=1;
// On est dans un nouveau répertoire, donc on remet le quicksearch à 0
*quicksearch_filename=0;
Reset_quicksearch();
}
else // Sinon on essaye de charger ou sauver le fichier
{
@ -1681,7 +1957,7 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
// On efface le commentaire précédent
Window_rectangle(45,70,32*8,8,MC_Light);
// On nettoie la zone où va s'afficher la preview:
Window_rectangle(183,95,120,80,MC_Light);
Window_rectangle(183,95,PREVIEW_WIDTH,PREVIEW_HEIGHT,MC_Light);
// On efface les dimensions de l'image
Window_rectangle(143,59,72,8,MC_Light);
// On efface la taille du fichier
@ -1697,7 +1973,7 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
// Un update pour couvrir les 4 zones: 3 libellés plus le commentaire
Update_window_area(45,48,256,30);
// Zone de preview
Update_window_area(183,95,120,80);
Update_window_area(183,95,PREVIEW_WIDTH,PREVIEW_HEIGHT);
}
New_preview_is_needed=0;

View File

@ -31,12 +31,12 @@
byte Button_Load_or_Save(byte load, T_IO_Context *context);
void Add_element_to_list(T_Fileselector *list, const char * fname, int type);
void Add_element_to_list(T_Fileselector *list, const char * full_name, const char *short_name, int type, byte icon);
///
/// Formats a display name for a file, directory, or similar name (drive, volume).
/// The returned value is a pointer to a single static buffer of 19 characters
/// The returned value is a pointer to a single static buffer of maximum 40 characters
/// including the '\\0'.
char * Format_filename(const char * fname, int type);
char * Format_filename(const char * fname, word max_length, int type);
void Free_fileselector_list(T_Fileselector *list);
@ -48,4 +48,10 @@ T_Fileselector_item * Get_item_by_index(T_Fileselector *list, short index);
short Find_file_in_fileselector(T_Fileselector *list, const char * fname);
void Locate_list_item(T_List_button * list, T_Fileselector * selector, short selected_item);
int Quicksearch_list(T_List_button * list, T_Fileselector * selector);
void Reset_quicksearch(void);
#endif

View File

@ -73,6 +73,12 @@ GFX2_GLOBAL byte MC_Light; ///< Index of color to use as "light grey" in the GUI
GFX2_GLOBAL byte MC_White; ///< Index of color to use as "white" in the GUI menus.
GFX2_GLOBAL byte MC_Trans; ///< Index of color to use as "transparent" while loading the GUI file.
GFX2_GLOBAL byte MC_OnBlack; ///< Index of color immediately lighter than "black" in the GUI menus.
GFX2_GLOBAL byte MC_Window; ///< Index of color to use as window background in the GUI menus.
GFX2_GLOBAL byte MC_Lighter; ///< Index of color lighter than window in the GUI menus.
GFX2_GLOBAL byte MC_Darker; ///< Index of color darker than window in the GUI menus.
// Input state
GFX2_GLOBAL word Mouse_X; ///< Current mouse cursor position.
GFX2_GLOBAL word Mouse_Y; ///< Current mouse cursor position.
@ -294,10 +300,6 @@ GFX2_GLOBAL short Main_image_height;
GFX2_GLOBAL short Main_offset_X;
/// Y position (in image space) of the pixel to display in the top left corner of screen.
GFX2_GLOBAL short Main_offset_Y;
/// Backup of ::Main_offset_X, used to store it while the magnifier is open.
GFX2_GLOBAL short Old_main_offset_X;
/// Backup of ::Main_offset_Y, used to store it while the magnifier is open.
GFX2_GLOBAL short Old_main_offset_Y;
/// Name of the directory that holds the image currently edited.
GFX2_GLOBAL char Main_file_directory[1024];
/// Filename (without directory) of the image currently edited.
@ -364,10 +366,6 @@ GFX2_GLOBAL short Spare_image_height;
GFX2_GLOBAL short Spare_offset_X;
/// Y position (in image space) of the pixel to display in the top left corner of screen.
GFX2_GLOBAL short Spare_offset_Y;
/// Backup of ::Main_offset_X, used to store it while the magnifier is open.
GFX2_GLOBAL short Old_spare_offset_X;
/// Backup of ::Main_offset_Y, used to store it while the magnifier is open.
GFX2_GLOBAL short Old_spare_offset_Y;
/// Name of the directory that holds the image currently edited as spare page.
GFX2_GLOBAL char Spare_file_directory[MAX_PATH_CHARACTERS];
/// Filename (without directory) of the image currently edited as spare page.
@ -432,8 +430,16 @@ GFX2_GLOBAL T_List_of_pages * Spare_backups;
// -- Brush data
/// Pixel data of the current brush.
/// Pixel data of the current brush (remapped).
GFX2_GLOBAL byte * Brush;
/// Pixel data of the current brush (before remap).
GFX2_GLOBAL byte * Brush_original_pixels;
/// Palette of the brush, from when it was grabbed.
GFX2_GLOBAL T_Palette Brush_original_palette;
/// Back_color used when the brush was grabbed
GFX2_GLOBAL byte Brush_original_back_color;
/// Color mapping from ::Brush_original_pixels to ::Brush
GFX2_GLOBAL byte Brush_colormap[256];
/// X coordinate of the brush's "hot spot". It is < ::Brush_width
GFX2_GLOBAL word Brush_offset_X;
/// Y coordinate of the brush's "hot spot". It is < ::Brush_height
@ -492,9 +498,9 @@ GFX2_GLOBAL word Menu_palette_cell_width;
GFX2_GLOBAL T_Menu_Bar Menu_bars[MENUBAR_COUNT]
#ifdef GLOBAL_VARIABLES
=
{{MENU_WIDTH, 9, 1, 45, NULL, 20, BUTTON_HIDE }, // Status
{MENU_WIDTH, 10, 1, 35, NULL, 144, BUTTON_LAYER_SELECT }, // Layers
{MENU_WIDTH, 35, 1, 0, NULL, 254, BUTTON_CHOOSE_COL }} // Main
{{MENU_WIDTH, 9, 1, 45, {NULL,NULL,NULL}, 20, BUTTON_HIDE }, // Status
{MENU_WIDTH, 10, 1, 35, {NULL,NULL,NULL}, 144, BUTTON_LAYER_SELECT }, // Layers
{MENU_WIDTH, 35, 1, 0, {NULL,NULL,NULL}, 254, BUTTON_CHOOSE_COL }} // Main
#endif
;
@ -510,71 +516,59 @@ GFX2_GLOBAL word Menu_Y_before_window;
/// Backup of ::Paintbrush_hidden, used to store it while a window is open.
GFX2_GLOBAL byte Paintbrush_hidden_before_window;
GFX2_GLOBAL word Window_stack_pos_X[8];
/// The global stack of editor screens.
GFX2_GLOBAL T_Window Window_stack[8];
/// Position of the left border of the topmost window (in screen coordinates)
#define Window_pos_X Window_stack_pos_X[Windows_open-1]
#define Window_pos_X Window_stack[Windows_open-1].Pos_X
GFX2_GLOBAL word Window_stack_pos_Y[8];
/// Position of the top border of the topmost window (in screen coordinates)
#define Window_pos_Y Window_stack_pos_Y[Windows_open-1]
#define Window_pos_Y Window_stack[Windows_open-1].Pos_Y
GFX2_GLOBAL word Window_stack_width[8];
///
/// Width of the topmost window, in "window pixels"
/// (multiply by ::Menu_factor_X to get screen pixels)
#define Window_width Window_stack_width[Windows_open-1]
#define Window_width Window_stack[Windows_open-1].Width
GFX2_GLOBAL word Window_stack_height[8];
///
/// Height of the topmost window, in "window pixels"
/// (multiply by ::Menu_factor_Y to get screen pixels)
#define Window_height Window_stack_height[Windows_open-1]
#define Window_height Window_stack[Windows_open-1].Height
GFX2_GLOBAL word Window_stack_nb_buttons[8];
/// Total number of buttons/controls in the topmost window.
#define Window_nb_buttons Window_stack_nb_buttons[Windows_open-1]
#define Window_nb_buttons Window_stack[Windows_open-1].Nb_buttons
GFX2_GLOBAL T_Normal_button * Window_stack_normal_button_list[8];
/// List of normal buttons in the topmost window.
#define Window_normal_button_list Window_stack_normal_button_list[Windows_open-1]
#define Window_normal_button_list Window_stack[Windows_open-1].Normal_button_list
GFX2_GLOBAL T_Palette_button * Window_stack_palette_button_list[8];
/// List of "palette" buttons in the topmost window.
#define Window_palette_button_list Window_stack_palette_button_list[Windows_open-1]
#define Window_palette_button_list Window_stack[Windows_open-1].Palette_button_list
GFX2_GLOBAL T_Scroller_button * Window_stack_scroller_button_list[8];
/// List of sliders (scrollers) in the topmost window.
#define Window_scroller_button_list Window_stack_scroller_button_list[Windows_open-1]
#define Window_scroller_button_list Window_stack[Windows_open-1].Scroller_button_list
GFX2_GLOBAL T_Special_button * Window_stack_special_button_list[8];
/// List of special buttons in the topmost window.
#define Window_special_button_list Window_stack_special_button_list[Windows_open-1]
#define Window_special_button_list Window_stack[Windows_open-1].Special_button_list
GFX2_GLOBAL T_Dropdown_button * Window_stack_dropdown_button_list[8];
/// List of dropdown buttons in the topmost window.
#define Window_dropdown_button_list Window_stack_dropdown_button_list[Windows_open-1]
#define Window_dropdown_button_list Window_stack[Windows_open-1].Dropdown_button_list
GFX2_GLOBAL T_List_button * Window_stack_list_button_list[8];
/// List of list buttons in the topmost window.
#define Window_list_button_list Window_stack_list_button_list[Windows_open-1]
#define Window_list_button_list Window_stack[Windows_open-1].List_button_list
GFX2_GLOBAL int Window_stack_attribute1[8];
///
/// The function ::Window_clicked_button() set this to ::LEFT_SIDE or ::RIGHT_SIDE
/// after a button is activated through left or right mouse click.
#define Window_attribute1 Window_stack_attribute1[Windows_open-1]
#define Window_attribute1 Window_stack[Windows_open-1].Attribute1
GFX2_GLOBAL int Window_stack_attribute2[8];
///
/// The function ::Window_clicked_button() set this to return extra information:
/// - When a scroller was clicked: the scroller position (0-n)
/// - When a palette was clicked: the color index (0-255)
/// - When a dropdown was used: the selected item's number T_Dropdown_choice::Number
#define Window_attribute2 Window_stack_attribute2[Windows_open-1]
#define Window_attribute2 Window_stack[Windows_open-1].Attribute2
#define Window_draggable Window_stack[Windows_open-1].Draggable
/// Definition of the menu (toolbox)
@ -587,6 +581,7 @@ GFX2_GLOBAL struct
word Height; ///< Button's active heigth
byte Pressed; ///< Button is currently pressed
byte Shape; ///< Shape, listed in enum ::BUTTON_SHAPES
char Icon; ///< Which icon to display: Either the one from the toolbar (-1) or one of ::MENU_SPRITE
// Triggers on mouse/keyboard
Func_action Left_action; ///< Action triggered by a left mouseclick on the button
@ -765,6 +760,8 @@ GFX2_GLOBAL long Gradient_bounds_range;
GFX2_GLOBAL long Gradient_total_range;
/// Amount of randomness to use in gradient (1-256+)
GFX2_GLOBAL long Gradient_random_factor;
/// Gradient speed of cycling (0-64)
GFX2_GLOBAL byte Gradient_speed;
/// Pointer to a gradient function, depending on the selected method.
GFX2_GLOBAL Func_gradient Gradient_function;
///
@ -772,10 +769,10 @@ GFX2_GLOBAL Func_gradient Gradient_function;
/// either ::Pixel (if the gradient must be drawn on menus only)
/// or ::Display_pixel (if the gradient must be drawn on the image)
GFX2_GLOBAL Func_pixel Gradient_pixel;
/// Settings for all gradients
GFX2_GLOBAL T_Gradient_array Gradient_array[16];
/// Index in ::Gradient_array of the currently selected gradient.
GFX2_GLOBAL byte Current_gradient;
/// Boolean, true when the color cycling is active.
GFX2_GLOBAL byte Cycling_mode;
// -- Airbrush data
@ -823,6 +820,9 @@ GFX2_GLOBAL byte * Menu_font;
/// Pointer to the current active skin.
GFX2_GLOBAL T_Gui_skin * Gfx;
/// Pointer to the current active skin.
GFX2_GLOBAL T_Paintbrush Paintbrush[NB_PAINTBRUSH_SPRITES];
// -- Help data
/// Index of the ::Help_section shown by the Help screen.
@ -894,6 +894,7 @@ GFX2_GLOBAL T_Brush_template Brush_container[BRUSH_CONTAINER_COLUMNS*BRUSH_CONTA
CURSOR_SHAPE_XOR_TARGET , // Stretch brush
CURSOR_SHAPE_TARGET , // Distort brush
CURSOR_SHAPE_XOR_TARGET , // Gradient-filled rectangle
CURSOR_SHAPE_COLORPICKER , // Colorpick on right mouse button
};
#else
/// ::Cursor_shape to use for each operation.
@ -950,34 +951,83 @@ GFX2_GLOBAL SDL_Joystick* Joystick;
/// It was chosen to not conflict with any SDL key number.
#define KEY_JOYBUTTON (SDLK_LAST+4)
/// Button definitions for the gp2x
#define GP2X_BUTTON_UP (0)
#define GP2X_BUTTON_DOWN (4)
#define GP2X_BUTTON_LEFT (2)
#define GP2X_BUTTON_RIGHT (6)
#define GP2X_BUTTON_UPLEFT (1)
#define GP2X_BUTTON_UPRIGHT (7)
#define GP2X_BUTTON_DOWNLEFT (3)
#define GP2X_BUTTON_DOWNRIGHT (5)
#define GP2X_BUTTON_CLICK (18)
#define GP2X_BUTTON_A (12)
#define GP2X_BUTTON_B (13)
#define GP2X_BUTTON_Y (14)
#define GP2X_BUTTON_X (15)
#define GP2X_BUTTON_L (10)
#define GP2X_BUTTON_R (11)
#define GP2X_BUTTON_START (8)
#define GP2X_BUTTON_SELECT (9)
#define GP2X_BUTTON_VOLUP (16)
#define GP2X_BUTTON_VOLDOWN (17)
/// The joystick axis are {X,Y} - on all platforms so far.
/// If there is ever a platform where they are reversed, put
/// these lines in each platform "case" below.
#define JOYSTICK_AXIS_X (0)
#define JOYSTICK_AXIS_Y (1)
#ifdef __gp2x__
#define KEY_ESC (KEY_JOYBUTTON+GP2X_BUTTON_X)
#ifdef __GP2X__
#define JOYSTICK_THRESHOLD (4096)
/// Button definitions for the gp2x
#define JOY_BUTTON_UP (0)
#define JOY_BUTTON_DOWN (4)
#define JOY_BUTTON_LEFT (2)
#define JOY_BUTTON_RIGHT (6)
#define JOY_BUTTON_UPLEFT (1)
#define JOY_BUTTON_UPRIGHT (7)
#define JOY_BUTTON_DOWNLEFT (3)
#define JOY_BUTTON_DOWNRIGHT (5)
#define JOY_BUTTON_CLICK (18)
#define JOY_BUTTON_A (12)
#define JOY_BUTTON_B (13)
#define JOY_BUTTON_Y (14)
#define JOY_BUTTON_X (15)
#define JOY_BUTTON_L (10)
#define JOY_BUTTON_R (11)
#define JOY_BUTTON_START (8)
#define JOY_BUTTON_SELECT (9)
#define JOY_BUTTON_VOLUP (16)
#define JOY_BUTTON_VOLDOWN (17)
#define KEY_ESC (KEY_JOYBUTTON+JOY_BUTTON_X)
#elif defined(__WIZ__)
/// Button definitions for the Wiz
#define JOY_BUTTON_UP (0)
#define JOY_BUTTON_DOWN (4)
#define JOY_BUTTON_LEFT (2)
#define JOY_BUTTON_RIGHT (6)
#define JOY_BUTTON_UPLEFT (1)
#define JOY_BUTTON_UPRIGHT (7)
#define JOY_BUTTON_DOWNLEFT (3)
#define JOY_BUTTON_DOWNRIGHT (5)
#define JOY_BUTTON_L (10)
#define JOY_BUTTON_R (11)
#define JOY_BUTTON_A (12)
#define JOY_BUTTON_B (13)
#define JOY_BUTTON_X (14)
#define JOY_BUTTON_Y (15)
#define JOY_BUTTON_MENU (8)
#define JOY_BUTTON_SELECT (9)
#define JOY_BUTTON_VOLUP (16)
#define JOY_BUTTON_VOLDOWN (17)
#define KEY_ESC (KEY_JOYBUTTON+JOY_BUTTON_X)
#elif defined (__CAANOO__)
#define JOYSTICK_THRESHOLD (4096)
/// Button definitions for the Caanoo
#define JOY_BUTTON_A (0)
#define JOY_BUTTON_X (1)
#define JOY_BUTTON_B (2)
#define JOY_BUTTON_Y (3)
#define JOY_BUTTON_L (4)
#define JOY_BUTTON_R (5)
#define JOY_BUTTON_HOME (6)
#define JOY_BUTTON_HOLD (7)
#define JOY_BUTTON_I (8)
#define JOY_BUTTON_II (9)
#define JOY_BUTTON_JOY (10)
#define KEY_ESC (KEY_JOYBUTTON+JOY_BUTTON_HOME)
#else
///
/// This is the key identifier for ESC. When hard-coding keyboard shortcuts
/// for buttons, etc. we use this instead of SDLK_ESCAPE,
/// so the GP2X port can get a joybutton equivalent of it.
/// so the console ports can get a joybutton equivalent of it.
#define KEY_ESC SDLK_ESCAPE
#endif

View File

@ -48,12 +48,13 @@
#include "pxquad.h"
#include "windows.h"
#include "input.h"
#include "brush.h"
#ifdef __VBCC__
#define __attribute__(x)
#endif
#if defined(__VBCC__)||defined(__GP2X__)
#if defined(__VBCC__) || defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__)
#define M_PI 3.141592653589793238462643
#endif
@ -522,6 +523,8 @@ try_again:
Menu_factor_Y=1;
break;
default: // Stay below some reasonable size
if (factor>Max(Pixel_width,Pixel_height))
factor/=Max(Pixel_width,Pixel_height);
Menu_factor_X=Min(factor,abs(Config.Ratio));
Menu_factor_Y=Min(factor,abs(Config.Ratio));
}
@ -617,7 +620,8 @@ void Resize_image(word chosen_width,word chosen_height)
// |B| | C = Nouvelle image
// +-+-+
if (Backup_with_new_dimensions(1,Main_backups->Pages->Nb_layers,chosen_width,chosen_height))
Upload_infos_page_main(Main_backups->Pages);
if (Backup_with_new_dimensions(chosen_width,chosen_height))
{
// La nouvelle page a pu être allouée, elle est pour l'instant pleine de
// 0s. Elle fait Main_image_width de large.
@ -672,13 +676,16 @@ void Remap_spare(void)
// ne seront pas utilisées par Remap_general_lowlevel.
for (color=0;color<=255;color++)
if (used[color])
used[color]=Best_color(Spare_palette[color].R,Spare_palette[color].G,Spare_palette[color].B);
used[color]=Best_color_perceptual(Spare_palette[color].R,Spare_palette[color].G,Spare_palette[color].B);
// Maintenant qu'on a une super table de conversion qui n'a que le nom
// qui craint un peu, on peut faire l'échange dans la brosse de toutes les
// teintes.
for (layer=0; layer<Spare_backups->Pages->Nb_layers; layer++)
Remap_general_lowlevel(used,Spare_backups->Pages->Image[layer],Spare_image_width,Spare_image_height,Spare_image_width);
Remap_general_lowlevel(used,Spare_backups->Pages->Image[layer],Spare_backups->Pages->Image[layer],Spare_image_width,Spare_image_height,Spare_image_width);
// Change transparent color index
Spare_backups->Pages->Transparent_color=used[Spare_backups->Pages->Transparent_color];
}
@ -687,43 +694,89 @@ void Get_colors_from_brush(void)
{
short x_pos; // Variable de balayage de la brosse
short y_pos; // Variable de balayage de la brosse
byte used[256]; // Tableau de booléens "La couleur est utilisée"
byte brush_used[256]; // Tableau de booléens "La couleur est utilisée"
dword usage[256];
int color;
int image_color;
if (Confirmation_box("Modify current palette ?"))
//if (Confirmation_box("Modify current palette ?"))
// Backup with unchanged layers, only palette is modified
Backup_layers(0);
// Init array of new colors
for (color=0;color<=255;color++)
brush_used[color]=0;
// Tag used colors
for (y_pos=0;y_pos<Brush_height;y_pos++)
for (x_pos=0;x_pos<Brush_width;x_pos++)
brush_used[*(Brush_original_pixels + y_pos * Brush_width + x_pos)]=1;
// Check used colors in picture (to know which palette entries are free)
Count_used_colors(usage);
// First pass : omit colors that are already in palette
for (color=0; color<256; color++)
{
// Backup with unchanged layers, only palette is modified
Backup_layers(0);
// On commence par initialiser le tableau de booléen à faux
for (color=0;color<=255;color++)
used[color]=0;
// On calcule la table d'utilisation des couleurs
for (y_pos=0;y_pos<Brush_height;y_pos++)
for (x_pos=0;x_pos<Brush_width;x_pos++)
used[Read_pixel_from_brush(x_pos,y_pos)]=1;
// On recopie dans la palette principale les teintes des couleurs utilisées
// dans la palette du brouillon
for (color=0;color<=255;color++)
if (used[color])
// For each color used in brush (to add in palette)
if (brush_used[color])
{
// Try locate it in current palette
for (image_color=0; image_color<256; image_color++)
{
Main_palette[color].R=Spare_palette[color].R;
Main_palette[color].G=Spare_palette[color].G;
Main_palette[color].B=Spare_palette[color].B;
if (Brush_original_palette[color].R==Main_palette[image_color].R
&& Brush_original_palette[color].G==Main_palette[image_color].G
&& Brush_original_palette[color].B==Main_palette[image_color].B)
{
// Color already in main palette:
// Tag as used, so that no new color will overwrite it
usage[image_color]=1;
// Tag as non-new, to avoid it in pass 2
brush_used[color]=0;
break;
}
}
Set_palette(Main_palette);
Compute_optimal_menu_colors(Main_palette);
Hide_cursor();
Display_all_screen();
Display_menu();
Display_cursor();
End_of_modification();
Main_image_is_modified=1;
}
}
// Second pass : For each color to add, find an empty slot in
// main palette to add it
image_color=0;
for (color=0; color<256 && image_color<256; color++)
{
// For each color used in brush
if (brush_used[color])
{
for (; image_color<256; image_color++)
{
if (!usage[image_color])
{
// Copy from color to image_color
Main_palette[image_color].R=Brush_original_palette[color].R;
Main_palette[image_color].G=Brush_original_palette[color].G;
Main_palette[image_color].B=Brush_original_palette[color].B;
image_color++;
break;
}
}
}
}
Remap_brush();
Set_palette(Main_palette);
Compute_optimal_menu_colors(Main_palette);
Hide_cursor();
Display_all_screen();
Display_menu();
Display_cursor();
End_of_modification();
Main_image_is_modified=1;
}
@ -1082,6 +1135,7 @@ void Fill_general(byte fill_color)
if (! (Permanent_draw_count&7))
{
Uint32 now = SDL_GetTicks();
SDL_PumpEvents();
if (now>= Permanent_draw_next_refresh)
{
Permanent_draw_next_refresh = now+100;

View File

@ -2,6 +2,7 @@
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Peter Gordon
Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet
@ -31,6 +32,10 @@
#include <sys/mount.h>
#elif defined (__linux__)
#include <sys/vfs.h>
#elif defined (__MINT__)
#include <mint/sysbind.h>
#include <mint/osbind.h>
#include <mint/ostruct.h>
#endif
#include "const.h"
@ -92,7 +97,7 @@ void Redefine_control(word *shortcut, int x_pos, int y_pos)
Display_cursor();
while (1)
{
while(!Get_input())SDL_Delay(20);
Get_input(20);
if (Key==KEY_ESC)
return;
if (Key!=0)
@ -231,22 +236,102 @@ void Window_set_shortcut(int action_id)
Display_cursor();
}
// -- Menu d'aide -----------------------------------------------------------
void Display_help(void)
///
/// Print a line with the 'help' (6x8) font.
short Print_help(short x_pos, short y_pos, const char *line, char line_type, short link_position, short link_size)
{
short width; // Largeur physique d'une ligne de texte
short x; // Indices d'affichage d'un caractère
short y;
short x_position; // Parcours de remplissage du buffer de ligne
short line_index; // 0-15 (16 lignes de textes)
short char_index; // Parcours des caractères d'une ligne
short start_line=Help_position;
byte * char_pixel;
short repeat_menu_x_factor;
short repeat_menu_y_factor;
short real_x_pos;
short real_y_pos;
byte * char_pixel;
short width; // Largeur physique d'une ligne de texte
real_x_pos=ToWinX(x_pos);
real_y_pos=ToWinY(y_pos);
// Calcul de la taille
width=strlen(line);
// Les lignes de titres prennent plus de place
if (line_type == 'T' || line_type == '-')
width = width*2;
// Pour chaque ligne dans la fenêtre:
for (y=0;y<8;y++)
{
x_position=0;
// On crée une nouvelle ligne à splotcher
for (char_index=0;char_index<width;char_index++)
{
// Recherche du caractère dans les fontes de l'aide.
// Ligne titre : Si l'indice est impair on dessine le quart de caractère
// qui va a gauche, sinon celui qui va a droite.
if (line_type=='T')
{
if (line[char_index/2]>'_' || line[char_index/2]<' ')
char_pixel=&(Gfx->Help_font_norm['!'][0][0]); // Caractère pas géré
else if (char_index & 1)
char_pixel=&(Gfx->Help_font_t2[(unsigned char)(line[char_index/2])-' '][0][0]);
else
char_pixel=&(Gfx->Help_font_t1[(unsigned char)(line[char_index/2])-' '][0][0]);
}
else if (line_type=='-')
{
if (line[char_index/2]>'_' || line[char_index/2]<' ')
char_pixel=&(Gfx->Help_font_norm['!'][0][0]); // Caractère pas géré
else if (char_index & 1)
char_pixel=&(Gfx->Help_font_t4[(unsigned char)(line[char_index/2])-' '][0][0]);
else
char_pixel=&(Gfx->Help_font_t3[(unsigned char)(line[char_index/2])-' '][0][0]);
}
else if (line_type=='S')
char_pixel=&(Gfx->Bold_font[(unsigned char)(line[char_index])][0][0]);
else if (line_type=='N' || line_type=='K')
char_pixel=&(Gfx->Help_font_norm[(unsigned char)(line[char_index])][0][0]);
else
char_pixel=&(Gfx->Help_font_norm['!'][0][0]); // Un garde-fou en cas de probleme
for (x=0;x<6;x++)
for (repeat_menu_x_factor=0;repeat_menu_x_factor<Menu_factor_X;repeat_menu_x_factor++)
{
byte color = *(char_pixel+x+y*6);
byte repetition = Pixel_width-1;
// Surlignement pour liens
if (line_type=='K' && char_index>=link_position
&& char_index<(link_position+link_size))
{
if (color == MC_Light)
color=MC_White;
else if (color == MC_Dark)
color=MC_Light;
else if (y<7)
color=MC_Dark;
}
Horizontal_line_buffer[x_position++]=color;
while (repetition--)
Horizontal_line_buffer[x_position++]=color;
}
}
// On la splotche
for (repeat_menu_y_factor=0;repeat_menu_y_factor<Menu_factor_Y;repeat_menu_y_factor++)
Display_line_fast(real_x_pos,real_y_pos++,width*Menu_factor_X*6,Horizontal_line_buffer);
}
return width;
}
// -- Menu d'aide -----------------------------------------------------------
void Display_help(void)
{
short line_index; // 0-15 (16 lignes de textes)
short start_line=Help_position;
const short x_pos=13;
const short y_pos=19;
char line_type; // N: Normale, T: Titre, S: Sous-titre
// -: Ligne inférieur de sous-titre
const char * line;
@ -254,21 +339,19 @@ void Display_help(void)
// raccourcis clavier
short link_position=0; // Position du premier caractère "variable"
short link_size=0; // Taille de la partie variable
real_x_pos=Window_pos_X+(13*Menu_factor_X);
real_y_pos=Window_pos_Y+(19*Menu_factor_Y);
short width;
for (line_index=0;line_index<16;line_index++)
{
// Shortcut au cas ou la section fait moins de 16 lignes
if (line_index >= Help_section[Current_help_section].Length)
{
Block (real_x_pos,
real_y_pos,
44*6*Menu_factor_X,
Window_rectangle (x_pos,
y_pos + line_index*8,
44*6,
// 44 = Nb max de char (+1 pour éviter les plantages en mode X
// causés par une largeur = 0)
(Menu_factor_Y<<3) * (16 - line_index),
(16 - line_index)*8,
MC_Black);
break;
}
@ -307,83 +390,16 @@ void Display_help(void)
line = buffer;
}
// Calcul de la taille
width=strlen(line);
// Les lignes de titres prennent plus de place
if (line_type == 'T' || line_type == '-')
width = width*2;
// Pour chaque ligne dans la fenêtre:
for (y=0;y<8;y++)
{
x_position=0;
// On crée une nouvelle ligne à splotcher
for (char_index=0;char_index<width;char_index++)
{
// Recherche du caractère dans les fontes de l'aide.
// Ligne titre : Si l'indice est impair on dessine le quart de caractère
// qui va a gauche, sinon celui qui va a droite.
if (line_type=='T')
{
if (line[char_index/2]>'_' || line[char_index/2]<' ')
char_pixel=&(Gfx->Help_font_norm['!'][0][0]); // Caractère pas géré
else if (char_index & 1)
char_pixel=&(Gfx->Help_font_t2[(unsigned char)(line[char_index/2])-' '][0][0]);
else
char_pixel=&(Gfx->Help_font_t1[(unsigned char)(line[char_index/2])-' '][0][0]);
}
else if (line_type=='-')
{
if (line[char_index/2]>'_' || line[char_index/2]<' ')
char_pixel=&(Gfx->Help_font_norm['!'][0][0]); // Caractère pas géré
else if (char_index & 1)
char_pixel=&(Gfx->Help_font_t4[(unsigned char)(line[char_index/2])-' '][0][0]);
else
char_pixel=&(Gfx->Help_font_t3[(unsigned char)(line[char_index/2])-' '][0][0]);
}
else if (line_type=='S')
char_pixel=&(Gfx->Bold_font[(unsigned char)(line[char_index])][0][0]);
else if (line_type=='N' || line_type=='K')
char_pixel=&(Gfx->Help_font_norm[(unsigned char)(line[char_index])][0][0]);
else
char_pixel=&(Gfx->Help_font_norm['!'][0][0]); // Un garde-fou en cas de probleme
for (x=0;x<6;x++)
for (repeat_menu_x_factor=0;repeat_menu_x_factor<Menu_factor_X;repeat_menu_x_factor++)
{
byte color = *(char_pixel+x+y*6);
byte repetition = Pixel_width-1;
// Surlignement pour liens
if (line_type=='K' && char_index>=link_position
&& char_index<(link_position+link_size))
{
if (color == MC_Light)
color=MC_White;
else if (color == MC_Dark)
color=MC_Light;
else if (y<7)
color=MC_Dark;
}
Horizontal_line_buffer[x_position++]=color;
while (repetition--)
Horizontal_line_buffer[x_position++]=color;
}
}
// On la splotche
for (repeat_menu_y_factor=0;repeat_menu_y_factor<Menu_factor_Y;repeat_menu_y_factor++)
Display_line_fast(real_x_pos,real_y_pos++,width*Menu_factor_X*6,Horizontal_line_buffer);
}
width=Print_help(x_pos, y_pos+(line_index<<3), line, line_type, link_position, link_size);
// On efface la fin de la ligne:
Block (real_x_pos+width*Menu_factor_X*6,
real_y_pos-(8*Menu_factor_Y),
((44*6*Menu_factor_X)-width*Menu_factor_X*6)+1,
// 44 = Nb max de char (+1 pour éviter les plantages en mode X
// causés par une largeur = 0)
Menu_factor_Y<<3,
if (width<44)
Window_rectangle (x_pos+width*6,
y_pos+(line_index<<3),
(44-width)*6,
8,
MC_Black);
}
Update_rect(Window_pos_X+13*Menu_factor_X,Window_pos_Y+19*Menu_factor_Y,44*6*Menu_factor_X,16*8*Menu_factor_Y);
Update_window_area(x_pos,y_pos,44*6,16*8);
}
@ -391,7 +407,7 @@ void Scroll_help(T_Scroller_button * scroller)
{
Hide_cursor();
scroller->Position=Help_position;
Compute_slider_cursor_height(scroller);
Compute_slider_cursor_length(scroller);
Window_draw_slider(scroller);
Display_help();
Display_cursor();
@ -510,7 +526,7 @@ void Window_help(int section, const char *sub_section)
nb_lines=Help_section[Current_help_section].Length;
scroller->Position=0;
scroller->Nb_elements=nb_lines;
Compute_slider_cursor_height(scroller);
Compute_slider_cursor_length(scroller);
Window_draw_slider(scroller);
}
else
@ -627,7 +643,51 @@ void Button_Stats(void)
Print_in_window(10,35,"Build options:",STATS_TITLE_COLOR,MC_Black);
Print_in_window(146,35,TrueType_is_supported()?"TTF fonts":"no TTF fonts",STATS_DATA_COLOR,MC_Black);
#if defined (__MINT__)
// Affichage de la mémoire restante
Print_in_window(10,43,"Free memory: ",STATS_TITLE_COLOR,MC_Black);
freeRam=0;
char helpBuf[64];
unsigned long STRAM,TTRAM;
Atari_Memory_free(&STRAM,&TTRAM);
freeRam=STRAM+TTRAM;
buffer[0]='\0';
if(STRAM > (100*1024*1024))
sprintf(helpBuf,"ST:%u Mb ",(unsigned int)(STRAM/(1024*1024)));
else if(freeRam > 100*1024)
sprintf(helpBuf,"ST:%u Kb ",(unsigned int)(STRAM/1024));
else
sprintf(helpBuf,"ST:%u b ",(unsigned int)STRAM);
strncat(buffer,helpBuf,sizeof(char)*37);
if(TTRAM > (100ULL*1024*1024*1024))
sprintf(helpBuf,"TT:%u Gb",(unsigned int)(TTRAM/(1024*1024*1024)));
else if(TTRAM > (100*1024*1024))
sprintf(helpBuf,"TT:%u Mb",(unsigned int)(TTRAM/(1024*1024)));
else if(freeRam > 100*1024)
sprintf(helpBuf,"TT:%u Kb",(unsigned int)(TTRAM/1024));
else
sprintf(helpBuf,"TT:%u b",(unsigned int)TTRAM);
strncat(buffer,helpBuf,sizeof(char)*37);
if(freeRam > (100ULL*1024*1024*1024))
sprintf(helpBuf,"(%u Gb)",(unsigned int)(freeRam/(1024*1024*1024)));
else if(freeRam > (100*1024*1024))
sprintf(helpBuf,"(%u Mb)",(unsigned int)(freeRam/(1024*1024)));
else if(freeRam > 100*1024)
sprintf(helpBuf,"(%u Kb)",(unsigned int)(freeRam/1024));
else
sprintf(helpBuf,"(%u b)",(unsigned int)freeRam);
strncat(buffer,helpBuf,sizeof(char)*37);
Print_in_window(18,51,buffer,STATS_DATA_COLOR,MC_Black);
#else
// Affichage de la mémoire restante
Print_in_window(10,51,"Free memory: ",STATS_TITLE_COLOR,MC_Black);
@ -641,8 +701,12 @@ void Button_Stats(void)
sprintf(buffer,"%u Kilobytes",(unsigned int)(freeRam/1024));
else
sprintf(buffer,"%u bytes",(unsigned int)freeRam);
Print_in_window(114,51,buffer,STATS_DATA_COLOR,MC_Black);
#endif
// Used memory
Print_in_window(10,59,"Used memory pages: ",STATS_TITLE_COLOR,MC_Black);
if(Stats_pages_memory > (100LL*1024*1024*1024))
@ -670,6 +734,14 @@ void Button_Stats(void)
statfs(Main_current_directory,&disk_info);
mem_size=(qword) disk_info.f_bfree * (qword) disk_info.f_bsize;
}
#elif defined (__MINT__)
_DISKINFO drvInfo;
mem_size=0;
Dfree(&drvInfo,0);
//number of free clusters*sectors per cluster*bytes per sector;
// reports current drive
mem_size=drvInfo.b_free*drvInfo.b_clsiz*drvInfo.b_secsiz;
#else
// Free disk space is only for shows. Other platforms can display 0.
#warning "Missing code for your platform !!! Check and correct please :)"

View File

@ -46,5 +46,17 @@ void Button_Stats(void);
*/
void Window_help(int section, const char * sub_section);
/// Opens a window where you can change a shortcut key(s).
void Window_set_shortcut(int action_id);
///
/// Print a line with the 'help' (6x8) font.
short Print_help(short x_pos, short y_pos, const char *line, char line_type, short link_position, short link_size);
// Nom de la touche actuallement assignée à un raccourci d'après son numéro
// de type 0x100+BOUTON_* ou SPECIAL_*
const char * Keyboard_shortcut_value(word shortcut_number);
#endif

View File

@ -62,7 +62,11 @@ static const T_Help_table helptable_about[] =
HELP_BOLD (" \"Dragon's Layers\" Edition")
HELP_BOLD (" THE ULTIMATE MULTI-RESOLUTION GFX EDITOR")
HELP_TEXT (" http://grafx2.googlecode.com")
#if defined(__MINT__)
HELP_TEXT (" atari build ")
#else
HELP_TEXT ("")
#endif
HELP_TEXT ("Copyright 2007-2010, the Grafx2 project team")
HELP_TEXT (" Copyright 1996-2001, SUNSET DESIGN")
};
@ -156,6 +160,7 @@ static const T_Help_table helptable_help[] =
HELP_LINK ("Filled polyform: %s", 0x200+BUTTON_POLYFILL)
HELP_LINK ("Gradient rectangle: %s", 0x100+BUTTON_GRADRECT)
HELP_LINK ("Gradation menu: %s", 0x200+BUTTON_GRADRECT)
HELP_LINK ("Toggle color cycling:%s", SPECIAL_CYCLE_MODE)
HELP_LINK ("Spheres: %s", 0x100+BUTTON_SPHERES)
HELP_LINK ("Gradient ellipses: %s", 0x200+BUTTON_SPHERES)
HELP_LINK ("Adjust picture: %s", 0x100+BUTTON_ADJUST)
@ -204,6 +209,10 @@ static const T_Help_table helptable_help[] =
HELP_LINK ("Distort brush: %s", SPECIAL_DISTORT)
HELP_LINK ("Outline brush: %s", SPECIAL_OUTLINE)
HELP_LINK ("Nibble brush: %s", SPECIAL_NIBBLE)
HELP_LINK ("Double brush size: %s", SPECIAL_BRUSH_DOUBLE)
HELP_LINK ("Halve brush size: %s", SPECIAL_BRUSH_HALVE)
HELP_LINK ("Double brush width: %s", SPECIAL_BRUSH_DOUBLE_WIDTH)
HELP_LINK ("Double brush height: %s", SPECIAL_BRUSH_DOUBLE_HEIGHT)
HELP_LINK ("Get brush colors: %s", SPECIAL_GET_BRUSH_COLORS)
HELP_LINK ("Recolorize brush: %s", SPECIAL_RECOLORIZE_BRUSH)
HELP_LINK ("Rotate brush: %s", SPECIAL_ROTATE_ANY_ANGLE)
@ -228,6 +237,18 @@ static const T_Help_table helptable_help[] =
HELP_LINK (" 18:1 %s", SPECIAL_ZOOM_18)
HELP_LINK (" 20:1 %s", SPECIAL_ZOOM_20)
HELP_LINK ("Brush effects menu: %s", 0x100+BUTTON_BRUSH_EFFECTS)
HELP_LINK ("Brush factory: %s", 0x200+BUTTON_BRUSH_EFFECTS)
HELP_LINK ("Repeat last script: %s", SPECIAL_REPEAT_SCRIPT)
HELP_LINK ("Run script #1: %s", SPECIAL_RUN_SCRIPT_1)
HELP_LINK ("Run script #2: %s", SPECIAL_RUN_SCRIPT_2)
HELP_LINK ("Run script #3: %s", SPECIAL_RUN_SCRIPT_3)
HELP_LINK ("Run script #4: %s", SPECIAL_RUN_SCRIPT_4)
HELP_LINK ("Run script #5: %s", SPECIAL_RUN_SCRIPT_5)
HELP_LINK ("Run script #6: %s", SPECIAL_RUN_SCRIPT_6)
HELP_LINK ("Run script #7: %s", SPECIAL_RUN_SCRIPT_7)
HELP_LINK ("Run script #8: %s", SPECIAL_RUN_SCRIPT_8)
HELP_LINK ("Run script #9: %s", SPECIAL_RUN_SCRIPT_9)
HELP_LINK ("Run script #10: %s", SPECIAL_RUN_SCRIPT_10)
HELP_LINK ("Text: %s", 0x100+BUTTON_TEXT)
HELP_LINK ("Resolution menu: %s", 0x100+BUTTON_RESOL)
HELP_LINK ("Safety resolution: %s", 0x200+BUTTON_RESOL)
@ -424,6 +445,14 @@ static const T_Help_table helptable_credits[] =
HELP_TEXT ("")
HELP_TEXT (" Luc Schrijvers (Begasus)")
HELP_TEXT ("")
HELP_BOLD (" WIZ & CAANOO PORT")
HELP_TEXT ("")
HELP_TEXT (" Alexander Filyanov (PheeL)")
HELP_TEXT ("")
HELP_BOLD (" ATARI PORT")
HELP_TEXT ("")
HELP_TEXT (" Pawel Goralski (Saulot)")
HELP_TEXT ("")
HELP_TEXT ("")
HELP_TEXT (" ... made it work on your favourite toaster")
HELP_TEXT ("")
@ -432,17 +461,18 @@ static const T_Help_table helptable_credits[] =
//HELP_TEXT ("0----5----0----5----0----5----0----5----0--X")
HELP_TEXT (" anibiqme blumunkee BDCIron ")
HELP_TEXT (" Ced DawnBringer El Topo ")
HELP_TEXT (" falenblood fano fogbot121 ")
HELP_TEXT (" Frost Grimmy grknsngn ")
HELP_TEXT (" falenblood fanickbux fano ")
HELP_TEXT (" fogbot121 Frost Grimmy ")
HELP_TEXT (" Gürkan Sengün Hatch HoraK-FDF ")
HELP_TEXT (" iLKke Iw2evk Jamon ")
HELP_TEXT (" keito kusma Lord Graga ")
HELP_TEXT (" Lorenzo Gatti MagerValp maymunbeyin ")
HELP_TEXT (" mind MooZ Pasi Kallinen ")
HELP_TEXT (" the Peach petter richienyhus ")
HELP_TEXT (" tape.wyrm TeeEmCee tempest ")
HELP_TEXT (" the Peach petter PheeL ")
HELP_TEXT (" richienyhus sm4tik spratek ")
HELP_TEXT (" tape.yrm TeeEmCee tempest ")
HELP_TEXT (" Timo Kurrpa titus^Rab Tobé ")
HELP_TEXT (" yakumo9275 00ai99")
HELP_TEXT (" yakumo2975 00ai99")
HELP_TEXT ("")
HELP_TEXT (" ... posted the annoying bug reports.")
HELP_TEXT ("")
@ -631,9 +661,25 @@ static const T_Help_table helptable_paintbrush[] =
HELP_TEXT ("brush size by using the keys:")
HELP_LINK ("Reduce : %s", SPECIAL_SMALLER_PAINTBRUSH)
HELP_LINK ("Increase : %s", SPECIAL_BIGGER_PAINTBRUSH)
HELP_TEXT ("The last 3 paintbrushes in the menu belong")
HELP_TEXT ("to the \"miscellaneous\" family and their size")
HELP_TEXT ("cannot be modified.")
HELP_TEXT ("")
HELP_TEXT ("Other brushes are bitmaps, their size can't")
HELP_TEXT ("be adjusted.")
HELP_TEXT ("")
HELP_TEXT ("Click with left mouse button to choose a ")
HELP_TEXT ("paintbrush, and right mouse button to store")
HELP_TEXT ("your current brush in the slot. If your")
HELP_TEXT ("current brush is a grabbed brush, it will")
HELP_TEXT ("store a monochrome version of it, maximum")
HELP_TEXT ("15x15. (See below 'Brush container' to store")
HELP_TEXT ("backups of a big brush)")
HELP_TEXT ("The stored brushes are saved when you exit")
HELP_TEXT ("the program.")
HELP_TEXT ("")
HELP_TEXT ("The 'Preset' button allows you to pick a")
HELP_TEXT ("brush from any family. It's useful if you've")
HELP_TEXT ("overwritten all normal slots with brushes")
HELP_TEXT ("that you use more often.")
HELP_TEXT ("")
HELP_TEXT ("")
HELP_BOLD ("BRUSH CONTAINER")
HELP_TEXT ("")
@ -1123,6 +1169,27 @@ static const T_Help_table helptable_grad_rect[] =
HELP_TEXT ("- Index scroller: Defines the current")
HELP_TEXT ("gradation among a set of 16 that will be")
HELP_TEXT ("memorised.")
HELP_TEXT ("")
HELP_BOLD ("COLOR CYCLING")
HELP_TEXT ("")
HELP_TEXT ("These options allow you to use animation of")
HELP_TEXT ("colors: Grafx2 will shift palette entries")
HELP_TEXT ("at real-time. Note that only the LBM file")
HELP_TEXT ("format can record these settings, and very")
HELP_TEXT ("few image viewers will play it back.")
HELP_TEXT ("")
HELP_TEXT ("- Cycling: Activates or desactivates the")
HELP_TEXT ("cycling of colors when you're in the editor.")
HELP_LINK ("Key: %s", SPECIAL_CYCLE_MODE)
HELP_TEXT ("")
HELP_TEXT ("- Speed: Sets the speed for the cycling of")
HELP_TEXT ("this range. Zero means this range doesn't")
HELP_TEXT ("cycle. With 1, the range shifts 0.2856 times")
HELP_TEXT ("per second; at speed 64 it's 18.28 times")
HELP_TEXT ("per second. The program activates cycling")
HELP_TEXT ("while you hold the speed slider, so you can")
HELP_TEXT ("preview the speed.")
HELP_TEXT ("")
};
static const T_Help_table helptable_spheres[] =
{
@ -1253,15 +1320,17 @@ static const T_Help_table helptable_brush_fx[] =
HELP_TEXT ("point at coordinates inferior to the ones of")
HELP_TEXT ("the first point, the brush will be inverted.")
HELP_TEXT ("Meanwhile, you can press the following keys")
HELP_TEXT ("whose effects are: 'D' : double the")
HELP_TEXT ("brush in X and Y 'H' : reduce the")
HELP_TEXT ("brush by half in X and Y 'X' : double")
HELP_TEXT ("the brush in X 'Shift+X': reduce the brush")
HELP_TEXT ("by half in X 'Y' : double the brush")
HELP_TEXT ("in Y 'Shift+Y': reduce the brush by half")
HELP_TEXT ("in Y 'N' : restore the normal size of")
HELP_TEXT ("the brush (can be useful")
HELP_TEXT ("because it's the only way for cancelling)")
HELP_TEXT ("whose effects are:")
HELP_TEXT (" 'D' : Double the brush")
HELP_TEXT (" 'H' : Reduce the brush by half")
HELP_TEXT (" 'X' : Double the brush in X")
HELP_TEXT (" 'Shift+X': Reduce the brush by half in X")
HELP_TEXT (" 'Y' : Double the brush in Y")
HELP_TEXT (" 'Shift+Y': Reduce the brush by half in Y")
HELP_TEXT (" 'N' : Restore the normal size of the")
HELP_TEXT (" brush (can be useful because")
HELP_TEXT (" it's the only way for")
HELP_TEXT (" cancelling)")
HELP_TEXT ("")
HELP_LINK ("- Distort: (Key:%s)",SPECIAL_DISTORT)
HELP_TEXT ("Triggers an interactive operation")
@ -1312,6 +1381,8 @@ static const T_Help_table helptable_brush_fx[] =
HELP_TEXT ("")
HELP_TITLE("BRUSH FACTORY")
HELP_TEXT ("")
HELP_LINK ("(Key:%s)",0x200+BUTTON_BRUSH_EFFECTS)
HELP_TEXT ("")
HELP_TEXT ("This menu allows you to run scripts. Scripts")
HELP_TEXT ("are written in the Lua language, and allow")
HELP_TEXT ("you to modify the brush (hence the name")
@ -1331,6 +1402,8 @@ static const T_Help_table helptable_brush_fx[] =
HELP_TEXT ("time you open the window. Scripts are loaded")
HELP_TEXT ("from disk when you run them.")
HELP_TEXT ("")
HELP_LINK ("- Repeat last script: %s", SPECIAL_REPEAT_SCRIPT)
HELP_TEXT ("")
};
static const T_Help_table helptable_effects[] =
{
@ -2273,6 +2346,13 @@ static const T_Help_table helptable_settings_details[] =
HELP_TEXT ("variants of your original palette, resulting")
HELP_TEXT ("in a pretty grid !")
HELP_TEXT ("")
HELP_BOLD (" Sync views")
HELP_TEXT ("When this mode is active, scrolling the view")
HELP_TEXT ("(and the magnifier view) affects both the")
HELP_TEXT ("main image and the spare page - as long as")
HELP_TEXT ("they have the same dimensions.")
HELP_TEXT ("")
HELP_TEXT ("")
HELP_TEXT ("")
HELP_TITLE("INPUT")
HELP_TEXT ("")
@ -2323,6 +2403,14 @@ static const T_Help_table helptable_settings_details[] =
HELP_TEXT ("GrafX2 to recognize them as a combo.")
HELP_TEXT ("")
HELP_TEXT ("")
HELP_BOLD (" Swap buttons")
HELP_TEXT ("This setting determines which key inverts")
HELP_TEXT ("the mouse buttons when it's held : A left")
HELP_TEXT ("click is then interpreted as a right-click.")
HELP_TEXT ("It's especially useful for one-button")
HELP_TEXT ("controllers, such as touchscreens and")
HELP_TEXT ("tablets.")
HELP_TEXT ("")
HELP_TITLE("EDITING")
HELP_TEXT ("")
HELP_TEXT ("")
@ -2359,7 +2447,14 @@ static const T_Help_table helptable_settings_details[] =
HELP_TEXT ("window. (Set it to 'no' if you have a slow")
HELP_TEXT ("computer or if you edit huge pictures)")
HELP_TEXT ("")
HELP_TEXT ("")
HELP_BOLD (" Right click colorpick")
HELP_TEXT ("This enables a mode where the right mouse")
HELP_TEXT ("buttons acts as a color picker until")
HELP_TEXT ("it's released, and selects Foreground color.")
HELP_TEXT ("This mode prevents you from painting with")
HELP_TEXT ("Background color.")
HELP_TEXT ("This option is ignored when the Shade,")
HELP_TEXT ("Quick-shade, or Tiling mode is used.")
};
static const T_Help_table helptable_clear[] =
@ -2474,16 +2569,28 @@ static const T_Help_table helptable_palette[] =
HELP_TEXT ("- Gauges: Allow you to modify the")
HELP_TEXT ("current selection.")
HELP_TEXT ("")
HELP_TEXT ("- RGB or HSL above the gauges: Switches")
HELP_TEXT ("between RGB and HSL color spaces. In HSL")
HELP_TEXT ("mode, the three sliders allow you to set the")
HELP_TEXT ("Hue (tint), Saturation (from grayscale to")
HELP_TEXT ("pure color) and Lightness (from black to")
HELP_TEXT ("white).")
HELP_TEXT ("")
HELP_TEXT ("- numbers below the gauges: Allows you to")
HELP_TEXT ("type in a new color in hexadecimal RRGGBB")
HELP_TEXT ("or RGB: ie. to get blue, you can type either")
HELP_TEXT ("0000ff or 00f.")
HELP_TEXT ("")
HELP_TEXT ("- \"+\" and \"-\": Allow you to lighten or")
HELP_TEXT ("darken the current selection.")
HELP_TEXT ("")
HELP_TEXT ("- Default: Restores the predifined GrafX2")
HELP_TEXT ("- Preset: Restores the predefined GrafX2")
HELP_TEXT ("palette.")
HELP_TEXT ("")
HELP_TEXT ("- Gray: Transforms the current selection")
HELP_TEXT ("into its gray-scaled equivalent.")
HELP_TEXT ("")
HELP_TEXT ("- Negative: Transforms the current selection")
HELP_TEXT ("- Neg: Transforms the current selection")
HELP_TEXT ("into its reverse video equivalent.")
HELP_TEXT ("")
HELP_TEXT ("- Invert: Swaps the colors of the current")
@ -2520,18 +2627,12 @@ static const T_Help_table helptable_palette[] =
HELP_TEXT ("whole palette it will sort this range.")
HELP_TEXT ("")
HELP_TEXT ("- Used: Indicates the number of colors used")
HELP_TEXT ("in the picture.")
HELP_TEXT ("in the picture and opens a histogram screen.")
HELP_TEXT ("")
HELP_TEXT ("- Zap unused: Erases the unused colors with")
HELP_TEXT ("copies of the current selection. (The")
HELP_TEXT ("keyboard shortcut for this button is <Del>).")
HELP_TEXT ("")
HELP_TEXT ("- HSL: Switches between RGB and HSL color")
HELP_TEXT ("spaces. In HSL mode, the three sliders")
HELP_TEXT ("allow you to set the Hue (tint), Saturation")
HELP_TEXT ("(from grayscale to pure color) and")
HELP_TEXT ("Lightness (from black to white).")
HELP_TEXT ("")
HELP_TEXT ("- Reduce: Allows you to reduce the palette")
HELP_TEXT ("to the number of colors you want (and")
HELP_TEXT ("modifies the picture).")

View File

@ -884,7 +884,16 @@ T_Key_config ConfigKey[NB_SHORTCUTS] = {
"",
true,
SDLK_u, // U
0},
// Secondary shortcut is button I on the Caanoo, L on the Wiz, unset on others
#if defined (__CAANOO__)
(KEY_JOYBUTTON+JOY_BUTTON_I)
#elif defined (__WIZ__)
(KEY_JOYBUTTON+JOY_BUTTON_L)
#else
0
#endif
// --
},
{103,
"Redo",
"Redo the last undone action.",
@ -892,7 +901,16 @@ T_Key_config ConfigKey[NB_SHORTCUTS] = {
"",
true,
SDLK_u|MOD_SHIFT, // Shift + U
0},
// Secondary shortcut is button II on the Caanoo, R on the Wiz, unset on others
#if defined (__CAANOO__)
(KEY_JOYBUTTON+JOY_BUTTON_II)
#elif defined (__WIZ__)
(KEY_JOYBUTTON+JOY_BUTTON_R)
#else
0
#endif
// --
},
{133,
"Kill",
"Kills the current page. It actually",
@ -924,7 +942,17 @@ T_Key_config ConfigKey[NB_SHORTCUTS] = {
"confirmation is asked.",
false,
SDLK_q, // Q (A en AZERTY)
0},
// Secondary shortcut is button Home on the Caanoo, Menu on the Wiz, unset on others
#if defined (__CAANOO__)
(KEY_JOYBUTTON+JOY_BUTTON_HOME)
#elif defined (__WIZ__)
(KEY_JOYBUTTON+JOY_BUTTON_MENU)
#else
0
#endif
// --
},
{107,
"Palette menu",
"Opens a menu which allows you to",
@ -1478,13 +1506,149 @@ T_Key_config ConfigKey[NB_SHORTCUTS] = {
SDLK_HOME|MOD_ALT, // Alt + Home
0},
{181,
"Brush factory",
"Opens a window where you can run a",
"Lua script.",
"",
true,
0, // No shortcut
0},
{182,
"Repeat script",
"Re-run the last script selected",
"in the Brush factory window.",
"",
true,
0, // No shortcut
0},
{183,
"Double brush size",
"Resizes the current user brush",
"by doubling width and height.",
"",
true,
SDLK_h|MOD_SHIFT, // Shift+H
0},
{184,
"Double brush width",
"Resizes the current user brush",
"by doubling its width.",
"",
true,
SDLK_x|MOD_SHIFT, // Shift+X
0},
{185,
"Double brush height",
"Resizes the current user brush",
"by doubling its height.",
"",
true,
SDLK_y|MOD_SHIFT, // Shift+Y
0},
{186,
"Halve brush size",
"Resizes the current user brush",
"by halving its width and height",
"",
true,
SDLK_h, // H
0},
{187,
"Run script #1",
"Runs a recorded Lua script.",
"",
"",
true,
0, // No shortcut
0},
{188,
"Run script #2",
"Runs a recorded Lua script.",
"",
"",
true,
0, // No shortcut
0},
{189,
"Run script #3",
"Runs a recorded Lua script.",
"",
"",
true,
0, // No shortcut
0},
{190,
"Run script #4",
"Runs a recorded Lua script.",
"",
"",
true,
0, // No shortcut
0},
{191,
"Run script #5",
"Runs a recorded Lua script.",
"",
"",
true,
0, // No shortcut
0},
{192,
"Run script #6",
"Runs a recorded Lua script.",
"",
"",
true,
0, // No shortcut
0},
{193,
"Run script #7",
"Runs a recorded Lua script.",
"",
"",
true,
0, // No shortcut
0},
{194,
"Run script #8",
"Runs a recorded Lua script.",
"",
"",
true,
0, // No shortcut
0},
{195,
"Run script #9",
"Runs a recorded Lua script.",
"",
"",
true,
0, // No shortcut
0},
{196,
"Run script #10",
"Runs a recorded Lua script.",
"",
"",
true,
0, // No shortcut
0},
{197,
"Toggle color cycling",
"Activates or desactivates color",
"cycling, if the current image has",
"cycling colors. (See gradient menu)",
true,
SDLK_BACKQUOTE|MOD_CTRL, // Ctrl + `~
0},
{198,
"Format checker",
"Performs a format check on the",
"current image.",
"",
true,
0,
0},
0}
};
word Ordering[NB_SHORTCUTS]=
@ -1670,6 +1834,23 @@ word Ordering[NB_SHORTCUTS]=
0x100+BUTTON_LAYER_UP,
0x100+BUTTON_LAYER_DOWN,
0x100+BUTTON_LAYER_MENU,
0x200+BUTTON_BRUSH_EFFECTS,
SPECIAL_REPEAT_SCRIPT,
SPECIAL_BRUSH_DOUBLE,
SPECIAL_BRUSH_DOUBLE_WIDTH,
SPECIAL_BRUSH_DOUBLE_HEIGHT,
SPECIAL_BRUSH_HALVE,
SPECIAL_RUN_SCRIPT_1,
SPECIAL_RUN_SCRIPT_2,
SPECIAL_RUN_SCRIPT_3,
SPECIAL_RUN_SCRIPT_4,
SPECIAL_RUN_SCRIPT_5,
SPECIAL_RUN_SCRIPT_6,
SPECIAL_RUN_SCRIPT_7,
SPECIAL_RUN_SCRIPT_8,
SPECIAL_RUN_SCRIPT_9,
SPECIAL_RUN_SCRIPT_10,
SPECIAL_CYCLE_MODE,
SPECIAL_FORMAT_CHECKER,
SPECIAL_FORMAT_CHECKER_MENU,
};

View File

@ -33,6 +33,8 @@
#endif
#include <SDL.h>
#define NB_SHORTCUTS 199 ///< Number of actions that can have a key combination associated to it.
/*** Types definitions and structs ***/
typedef struct

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,7 @@
/// Initialization (and some de-initialization) functions.
//////////////////////////////////////////////////////////////////////////////
T_Gui_skin *Load_graphics(const char * skin_file);
T_Gui_skin *Load_graphics(const char * skin_file, T_Gradient_array *gradients);
void Set_current_skin(const char *skinfile, T_Gui_skin *gfx);
void Init_buttons(void);
void Init_operations(void);
@ -34,6 +34,10 @@ int Save_CFG(void);
void Set_all_video_modes(void);
void Set_config_defaults(void);
void Init_sighandler(void);
void Init_paintbrushes(void);
/// Set application icon(s)
void Define_icon(void);
extern char Gui_loading_error_message[512];

View File

@ -21,6 +21,12 @@
*/
#include <SDL.h>
#include <SDL_syswm.h>
#ifdef __WIN32__
#include <windows.h>
#include <ShellApi.h>
#endif
#include "global.h"
#include "keyboard.h"
@ -28,7 +34,9 @@
#include "windows.h"
#include "errors.h"
#include "misc.h"
#include "buttons.h"
#include "input.h"
#include "loadsave.h"
#ifdef __VBCC__
#define __attribute__(x)
@ -36,6 +44,7 @@
void Handle_window_resize(SDL_ResizeEvent event);
void Handle_window_exit(SDL_QuitEvent event);
int Color_cycling(__attribute__((unused)) void* useless);
// public Globals (available as extern)
@ -44,8 +53,11 @@ int Snap_axis = 0;
int Snap_axis_origin_X;
int Snap_axis_origin_Y;
char * Drop_file_name = NULL;
// --
// Digital joystick state
byte Directional_up;
byte Directional_up_right;
byte Directional_right;
@ -56,14 +68,22 @@ byte Directional_left;
byte Directional_up_left;
byte Directional_click;
long Directional_delay;
// Emulated directional controller.
// This has a distinct state from Directional_, because some joysticks send
// "I'm not moving" SDL events when idle, thus stopping the emulated one.
byte Directional_emulated_up;
byte Directional_emulated_right;
byte Directional_emulated_down;
byte Directional_emulated_left;
long Directional_first_move;
long Directional_last_move;
long Directional_step;
int Mouse_moved; ///< Boolean, Set to true if any cursor movement occurs.
word Input_new_mouse_X;
word Input_new_mouse_Y;
byte Input_new_mouse_K;
byte Button_inverter=0; // State of the key that swaps mouse buttons.
byte Mouse_mode = 0; ///< Mouse mode = 0:normal, 1:emulated with custom sensitivity.
short Mouse_virtual_x_position;
@ -71,21 +91,84 @@ short Mouse_virtual_y_position;
short Mouse_virtual_width;
short Mouse_virtual_height;
// TODO: move to config
#ifdef __GP2X__
short Joybutton_shift=GP2X_BUTTON_L; // Button number that serves as a "shift" modifier
short Joybutton_control=GP2X_BUTTON_R; // Button number that serves as a "ctrl" modifier
short Joybutton_alt=GP2X_BUTTON_CLICK; // Button number that serves as a "alt" modifier
short Joybutton_left_click=GP2X_BUTTON_B; // Button number that serves as left click
short Joybutton_right_click=GP2X_BUTTON_Y; // Button number that serves as right-click
#else
short Joybutton_shift=-1; // Button number that serves as a "shift" modifier
short Joybutton_control=-1; // Button number that serves as a "ctrl" modifier
short Joybutton_alt=-1; // Button number that serves as a "alt" modifier
short Joybutton_left_click=0; // Button number that serves as left click
short Joybutton_right_click=0; // Button number that serves as right-click
// Joystick/pad configurations for the various console ports.
// See the #else for the documentation of fields.
// TODO: Make these user-settable somehow.
#if defined(__GP2X__)
#define JOYSTICK_THRESHOLD (4096)
short Joybutton_shift= JOY_BUTTON_L;
short Joybutton_control= JOY_BUTTON_R;
short Joybutton_alt= JOY_BUTTON_CLICK;
short Joybutton_left_click= JOY_BUTTON_B;
short Joybutton_right_click=JOY_BUTTON_Y;
#elif defined(__WIZ__)
#define JOYSTICK_THRESHOLD (4096)
short Joybutton_shift= JOY_BUTTON_X;
short Joybutton_control= JOY_BUTTON_SELECT;
short Joybutton_alt= JOY_BUTTON_Y;
short Joybutton_left_click= JOY_BUTTON_A;
short Joybutton_right_click=JOY_BUTTON_B;
#elif defined(__CAANOO__)
#define JOYSTICK_THRESHOLD (4096)
short Joybutton_shift= JOY_BUTTON_L;
short Joybutton_control= JOY_BUTTON_R;
short Joybutton_alt= JOY_BUTTON_Y;
short Joybutton_left_click= JOY_BUTTON_A;
short Joybutton_right_click=JOY_BUTTON_B;
#else // Default : Any joystick on a computer platform
///
/// This is the sensitivity threshold for the directional
/// pad of a cheap digital joypad on the PC. It has been set through
/// trial and error : If value is too large then the movement is
/// randomly interrupted; if the value is too low the cursor will
/// move by itself, controlled by parasits.
/// YR 04/11/2010: I just observed a -8700 when joystick is idle.
#define JOYSTICK_THRESHOLD (10000)
/// A button that is marked as "modifier" will
short Joybutton_shift=-1; ///< Button number that serves as a "shift" modifier; -1 for none
short Joybutton_control=-1; ///< Button number that serves as a "ctrl" modifier; -1 for none
short Joybutton_alt=-1; ///< Button number that serves as a "alt" modifier; -1 for none
short Joybutton_left_click=0; ///< Button number that serves as left click; -1 for none
short Joybutton_right_click=1; ///< Button number that serves as right-click; -1 for none
#endif
int Has_shortcut(word function)
{
if (function == 0xFFFF)
return 0;
if (function & 0x100)
{
if (Buttons_Pool[function&0xFF].Left_shortcut[0]!=KEY_NONE)
return 1;
if (Buttons_Pool[function&0xFF].Left_shortcut[1]!=KEY_NONE)
return 1;
return 0;
}
if (function & 0x200)
{
if (Buttons_Pool[function&0xFF].Right_shortcut[0]!=KEY_NONE)
return 1;
if (Buttons_Pool[function&0xFF].Right_shortcut[1]!=KEY_NONE)
return 1;
return 0;
}
if(Config_Key[function][0]!=KEY_NONE)
return 1;
if(Config_Key[function][1]!=KEY_NONE)
return 1;
return 0;
}
int Is_shortcut(word key, word function)
{
if (key == 0 || function == 0xFFFF)
@ -177,16 +260,18 @@ int Move_cursor_with_constraints()
feedback=1;
if (Input_new_mouse_K == 0)
{
Input_sticky_control = 0;
}
}
// Hide cursor, because even just a click change needs it
if (!Mouse_moved)
{
Mouse_moved++;
// Hide cursor (erasing icon and brush on screen
// before changing the coordinates.
Hide_cursor();
}
Mouse_moved++;
if (Input_new_mouse_X != Mouse_X || Input_new_mouse_Y != Mouse_Y)
{
Mouse_X=Input_new_mouse_X;
@ -194,8 +279,8 @@ int Move_cursor_with_constraints()
}
Mouse_K=Input_new_mouse_K;
if (Mouse_moved > Config.Mouse_merge_movement)
if (! Operation[Current_operation][Mouse_K_unique]
if (Mouse_moved > Config.Mouse_merge_movement
&& !Operation[Current_operation][Mouse_K_unique]
[Operation_stack_size].Fast_mouse)
feedback=1;
}
@ -254,11 +339,19 @@ int Handle_mouse_click(SDL_MouseButtonEvent event)
switch(event.button)
{
case SDL_BUTTON_LEFT:
Input_new_mouse_K |= 1;
if (Button_inverter)
Input_new_mouse_K |= 2;
else
Input_new_mouse_K |= 1;
break;
break;
case SDL_BUTTON_RIGHT:
Input_new_mouse_K |= 2;
if (Button_inverter)
Input_new_mouse_K |= 1;
else
Input_new_mouse_K |= 2;
break;
break;
case SDL_BUTTON_MIDDLE:
@ -284,11 +377,17 @@ int Handle_mouse_release(SDL_MouseButtonEvent event)
switch(event.button)
{
case SDL_BUTTON_LEFT:
Input_new_mouse_K &= ~1;
if (Button_inverter)
Input_new_mouse_K &= ~2;
else
Input_new_mouse_K &= ~1;
break;
case SDL_BUTTON_RIGHT:
Input_new_mouse_K &= ~2;
if (Button_inverter)
Input_new_mouse_K &= ~1;
else
Input_new_mouse_K &= ~2;
break;
}
@ -300,27 +399,64 @@ int Handle_mouse_release(SDL_MouseButtonEvent event)
int Handle_key_press(SDL_KeyboardEvent event)
{
//Appui sur une touche du clavier
int modifier;
Key = Keysym_to_keycode(event.keysym);
Key_ANSI = Keysym_to_ANSI(event.keysym);
switch(event.keysym.sym)
{
case SDLK_RSHIFT:
case SDLK_LSHIFT:
modifier=MOD_SHIFT;
break;
case SDLK_RCTRL:
case SDLK_LCTRL:
modifier=MOD_CTRL;
break;
case SDLK_RALT:
case SDLK_LALT:
case SDLK_MODE:
modifier=MOD_ALT;
break;
case SDLK_RMETA:
case SDLK_LMETA:
modifier=MOD_META;
break;
default:
modifier=0;
}
if (Config.Swap_buttons && modifier == Config.Swap_buttons && Button_inverter==0)
{
Button_inverter=1;
if (Input_new_mouse_K)
{
Input_new_mouse_K ^= 3; // Flip bits 0 and 1
return Move_cursor_with_constraints();
}
}
if(Is_shortcut(Key,SPECIAL_MOUSE_UP))
{
Directional_up=1;
Directional_emulated_up=1;
return 0;
}
else if(Is_shortcut(Key,SPECIAL_MOUSE_DOWN))
{
Directional_down=1;
Directional_emulated_down=1;
return 0;
}
else if(Is_shortcut(Key,SPECIAL_MOUSE_LEFT))
{
Directional_left=1;
Directional_emulated_left=1;
return 0;
}
else if(Is_shortcut(Key,SPECIAL_MOUSE_RIGHT))
{
Directional_right=1;
Directional_emulated_right=1;
return 0;
}
else if(Is_shortcut(Key,SPECIAL_CLICK_LEFT) && Keyboard_click_allowed > 0)
@ -349,26 +485,35 @@ int Release_control(int key_code, int modifier)
Snap_axis = 0;
need_feedback = 1;
}
if (Config.Swap_buttons && modifier == Config.Swap_buttons && Button_inverter==1)
{
Button_inverter=0;
if (Input_new_mouse_K)
{
Input_new_mouse_K ^= 3; // Flip bits 0 and 1
return Move_cursor_with_constraints();
}
}
if((key_code && key_code == (Config_Key[SPECIAL_MOUSE_UP][0]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_UP][0]&modifier) ||
(key_code && key_code == (Config_Key[SPECIAL_MOUSE_UP][1]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_UP][1]&modifier))
{
Directional_up=0;
Directional_emulated_up=0;
}
if((key_code && key_code == (Config_Key[SPECIAL_MOUSE_DOWN][0]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_DOWN][0]&modifier) ||
(key_code && key_code == (Config_Key[SPECIAL_MOUSE_DOWN][1]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_DOWN][1]&modifier))
{
Directional_down=0;
Directional_emulated_down=0;
}
if((key_code && key_code == (Config_Key[SPECIAL_MOUSE_LEFT][0]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_LEFT][0]&modifier) ||
(key_code && key_code == (Config_Key[SPECIAL_MOUSE_LEFT][1]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_LEFT][1]&modifier))
{
Directional_left=0;
Directional_emulated_left=0;
}
if((key_code && key_code == (Config_Key[SPECIAL_MOUSE_RIGHT][0]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_RIGHT][0]&modifier) ||
(key_code && key_code == (Config_Key[SPECIAL_MOUSE_RIGHT][1]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_RIGHT][1]&modifier))
{
Directional_right=0;
Directional_emulated_right=0;
}
if((key_code && key_code == (Config_Key[SPECIAL_CLICK_LEFT][0]&0x0FFF)) || (Config_Key[SPECIAL_CLICK_LEFT][0]&modifier) ||
(key_code && key_code == (Config_Key[SPECIAL_CLICK_LEFT][1]&0x0FFF)) || (Config_Key[SPECIAL_CLICK_LEFT][1]&modifier))
@ -445,54 +590,88 @@ int Handle_joystick_press(SDL_JoyButtonEvent event)
if (event.button == Joybutton_control)
{
SDL_SetModState(SDL_GetModState() | KMOD_CTRL);
if (Config.Swap_buttons == MOD_CTRL && Button_inverter==0)
{
Button_inverter=1;
if (Input_new_mouse_K)
{
Input_new_mouse_K ^= 3; // Flip bits 0 and 1
return Move_cursor_with_constraints();
}
}
return 0;
}
if (event.button == Joybutton_alt)
{
SDL_SetModState(SDL_GetModState() | (KMOD_ALT|KMOD_META));
if (Config.Swap_buttons == MOD_ALT && Button_inverter==0)
{
Button_inverter=1;
if (Input_new_mouse_K)
{
Input_new_mouse_K ^= 3; // Flip bits 0 and 1
return Move_cursor_with_constraints();
}
}
return 0;
}
if (event.button == Joybutton_left_click)
{
Input_new_mouse_K=1;
Input_new_mouse_K = Button_inverter ? 2 : 1;
return Move_cursor_with_constraints();
}
if (event.button == Joybutton_right_click)
{
Input_new_mouse_K=2;
Input_new_mouse_K = Button_inverter ? 1 : 2;
return Move_cursor_with_constraints();
}
#ifdef __GP2X__
switch(event.button)
{
case GP2X_BUTTON_UP:
#ifdef JOY_BUTTON_UP
case JOY_BUTTON_UP:
Directional_up=1;
break;
case GP2X_BUTTON_UPRIGHT:
#endif
#ifdef JOY_BUTTON_UPRIGHT
case JOY_BUTTON_UPRIGHT:
Directional_up_right=1;
break;
case GP2X_BUTTON_RIGHT:
#endif
#ifdef JOY_BUTTON_RIGHT
case JOY_BUTTON_RIGHT:
Directional_right=1;
break;
case GP2X_BUTTON_DOWNRIGHT:
#endif
#ifdef JOY_BUTTON_DOWNRIGHT
case JOY_BUTTON_DOWNRIGHT:
Directional_down_right=1;
break;
case GP2X_BUTTON_DOWN:
#endif
#ifdef JOY_BUTTON_DOWN
case JOY_BUTTON_DOWN:
Directional_down=1;
break;
case GP2X_BUTTON_DOWNLEFT:
#endif
#ifdef JOY_BUTTON_DOWNLEFT
case JOY_BUTTON_DOWNLEFT:
Directional_down_left=1;
break;
case GP2X_BUTTON_LEFT:
#endif
#ifdef JOY_BUTTON_LEFT
case JOY_BUTTON_LEFT:
Directional_left=1;
break;
case GP2X_BUTTON_UPLEFT:
#endif
#ifdef JOY_BUTTON_UPLEFT
case JOY_BUTTON_UPLEFT:
Directional_up_left=1;
break;
#endif
default:
break;
}
#endif
Key = (KEY_JOYBUTTON+event.button)|Key_modifiers(SDL_GetModState());
// TODO: systeme de répétition
@ -527,58 +706,75 @@ int Handle_joystick_release(SDL_JoyButtonEvent event)
return Move_cursor_with_constraints();
}
#ifdef __GP2X__
switch(event.button)
{
case GP2X_BUTTON_UP:
Directional_up=0;
#ifdef JOY_BUTTON_UP
case JOY_BUTTON_UP:
Directional_up=1;
break;
case GP2X_BUTTON_UPRIGHT:
Directional_up_right=0;
#endif
#ifdef JOY_BUTTON_UPRIGHT
case JOY_BUTTON_UPRIGHT:
Directional_up_right=1;
break;
case GP2X_BUTTON_RIGHT:
Directional_right=0;
#endif
#ifdef JOY_BUTTON_RIGHT
case JOY_BUTTON_RIGHT:
Directional_right=1;
break;
case GP2X_BUTTON_DOWNRIGHT:
Directional_down_right=0;
#endif
#ifdef JOY_BUTTON_DOWNRIGHT
case JOY_BUTTON_DOWNRIGHT:
Directional_down_right=1;
break;
case GP2X_BUTTON_DOWN:
Directional_down=0;
#endif
#ifdef JOY_BUTTON_DOWN
case JOY_BUTTON_DOWN:
Directional_down=1;
break;
case GP2X_BUTTON_DOWNLEFT:
Directional_down_left=0;
#endif
#ifdef JOY_BUTTON_DOWNLEFT
case JOY_BUTTON_DOWNLEFT:
Directional_down_left=1;
break;
case GP2X_BUTTON_LEFT:
Directional_left=0;
#endif
#ifdef JOY_BUTTON_LEFT
case JOY_BUTTON_LEFT:
Directional_left=1;
break;
case GP2X_BUTTON_UPLEFT:
Directional_up_left=0;
#endif
#ifdef JOY_BUTTON_UPLEFT
case JOY_BUTTON_UPLEFT:
Directional_up_left=1;
break;
#endif
default:
break;
}
#endif
return Move_cursor_with_constraints();
}
void Handle_joystick_movement(SDL_JoyAxisEvent event)
{
if (event.axis==0) // X
if (event.axis==JOYSTICK_AXIS_X)
{
Directional_right=Directional_left=0;
if (event.value<-1000)
if (event.value<-JOYSTICK_THRESHOLD)
{
Directional_left=1;
}
else if (event.value>1000)
else if (event.value>JOYSTICK_THRESHOLD)
Directional_right=1;
}
else if (event.axis==1) // Y
else if (event.axis==JOYSTICK_AXIS_Y)
{
Directional_up=Directional_down=0;
if (event.value<-1000)
if (event.value<-JOYSTICK_THRESHOLD)
{
Directional_up=1;
}
else if (event.value>1000)
else if (event.value>JOYSTICK_THRESHOLD)
Directional_down=1;
}
}
@ -616,138 +812,222 @@ int Cursor_displace(short delta_x, short delta_y)
return Move_cursor_with_constraints();
}
// This function is the acceleration profile for directional (digital) cursor
// controllers.
int Directional_acceleration(int msec)
{
const int initial_delay = 250;
const int linear_factor = 200;
const int accel_factor = 10000;
// At beginning there is 1 pixel move, then nothing for N milliseconds
if (msec<initial_delay)
return 1;
// After that, position over time is generally y = ax²+bx+c
// a = 1/accel_factor
// b = 1/linear_factor
// c = 1
return 1+(msec-initial_delay+linear_factor)/linear_factor+(msec-initial_delay)*(msec-initial_delay)/accel_factor;
}
// Main input handling function
int Get_input(void)
int Get_input(int sleep_time)
{
SDL_Event event;
int user_feedback_required = 0; // Flag qui indique si on doit arrêter de traiter les évènements ou si on peut enchainer
// Commit any pending screen update.
// This is done in this function because it's called after reading
// some user input.
Flush_update();
Color_cycling(NULL);
Key_ANSI = 0;
Key = 0;
Mouse_moved=0;
Input_new_mouse_X = Mouse_X;
Input_new_mouse_Y = Mouse_Y;
Input_new_mouse_K = Mouse_K;
// Not using SDL_PollEvent() because every call polls the input
// device. In some cases such as high-sensitivity mouse or cheap
// digital joypad, every call will see something subtly different in
// the state of the device, and thus it will enqueue a new event.
// The result is that the queue will never empty !!!
// Get new events from input devices.
SDL_PumpEvents();
// Process as much events as possible without redrawing the screen.
// This mostly allows us to merge mouse events for people with an high
// resolution mouse
while( (!user_feedback_required) && SDL_PollEvent(&event)) // Try to cumulate for a full VBL except if there is a required feedback
while(!user_feedback_required && SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_ALLEVENTS)==1)
{
switch(event.type)
{
case SDL_VIDEORESIZE:
Handle_window_resize(event.resize);
user_feedback_required = 1;
break;
switch(event.type)
{
case SDL_VIDEORESIZE:
Handle_window_resize(event.resize);
user_feedback_required = 1;
break;
case SDL_QUIT:
Handle_window_exit(event.quit);
user_feedback_required = 1;
break;
case SDL_QUIT:
Handle_window_exit(event.quit);
user_feedback_required = 1;
break;
case SDL_MOUSEMOTION:
user_feedback_required = Handle_mouse_move(event.motion);
break;
case SDL_MOUSEMOTION:
user_feedback_required = Handle_mouse_move(event.motion);
break;
case SDL_MOUSEBUTTONDOWN:
Handle_mouse_click(event.button);
user_feedback_required = 1;
break;
case SDL_MOUSEBUTTONDOWN:
Handle_mouse_click(event.button);
user_feedback_required = 1;
break;
case SDL_MOUSEBUTTONUP:
Handle_mouse_release(event.button);
user_feedback_required = 1;
break;
case SDL_MOUSEBUTTONUP:
Handle_mouse_release(event.button);
user_feedback_required = 1;
break;
case SDL_KEYDOWN:
Handle_key_press(event.key);
user_feedback_required = 1;
break;
case SDL_KEYDOWN:
Handle_key_press(event.key);
user_feedback_required = 1;
break;
case SDL_KEYUP:
Handle_key_release(event.key);
break;
case SDL_KEYUP:
Handle_key_release(event.key);
break;
// Start of Joystik handling
#ifdef USE_JOYSTICK
// Start of Joystik handling
#ifdef USE_JOYSTICK
case SDL_JOYBUTTONUP:
Handle_joystick_release(event.jbutton);
user_feedback_required = 1;
break;
case SDL_JOYBUTTONUP:
Handle_joystick_release(event.jbutton);
user_feedback_required = 1;
break;
case SDL_JOYBUTTONDOWN:
Handle_joystick_press(event.jbutton);
user_feedback_required = 1;
break;
case SDL_JOYBUTTONDOWN:
Handle_joystick_press(event.jbutton);
user_feedback_required = 1;
break;
case SDL_JOYAXISMOTION:
Handle_joystick_movement(event.jaxis);
break;
case SDL_JOYAXISMOTION:
Handle_joystick_movement(event.jaxis);
break;
#endif
// End of Joystick handling
default:
// DEBUG("Unhandled SDL event number : ",event.type);
break;
}
#endif
// End of Joystick handling
case SDL_SYSWMEVENT:
#ifdef __WIN32__
if(event.syswm.msg->msg == WM_DROPFILES)
{
int file_count;
HDROP hdrop = (HDROP)(event.syswm.msg->wParam);
if((file_count = DragQueryFile(hdrop,(UINT)-1,(LPTSTR) NULL ,(UINT) 0)) > 0)
{
long len;
// Query filename length
len = DragQueryFile(hdrop,0 ,NULL ,0);
if (len)
{
Drop_file_name=calloc(len+1,1);
if (Drop_file_name)
{
if (DragQueryFile(hdrop,0 ,(LPTSTR) Drop_file_name ,(UINT) MAX_PATH))
{
// Success
}
else
{
free(Drop_file_name);
// Don't report name copy error
}
}
else
{
// Don't report alloc error (for a file name? :/ )
}
}
else
{
// Don't report weird Windows error
}
}
else
{
// Drop of zero files. Thanks for the information, Bill.
}
}
#endif
break;
default:
//DEBUG("Unhandled SDL event number : ",event.type);
break;
}
}
// Directional controller
if (!(Directional_up||Directional_up_right||Directional_right||
Directional_down_right||Directional_down||Directional_down_left||
Directional_left||Directional_up_left))
Directional_down_right||Directional_down||Directional_down_left||
Directional_left||Directional_up_left||Directional_emulated_up||
Directional_emulated_right||Directional_emulated_down||
Directional_emulated_left))
{
Directional_delay=-1;
Directional_last_move=SDL_GetTicks();
Directional_first_move=0;
}
else
{
long time_now;
int step=0;
time_now=SDL_GetTicks();
if (time_now>Directional_last_move+Directional_delay)
if (Directional_first_move==0)
{
Directional_first_move=time_now;
step=1;
}
else
{
// Compute how much the cursor has moved since last call.
// This tries to make smooth cursor movement
// no matter the frequency of calls to Get_input()
step =
Directional_acceleration(time_now - Directional_first_move) -
Directional_acceleration(Directional_last_move - Directional_first_move);
// Clip speed at 3 pixel per visible frame.
if (step > 3)
step=3;
}
Directional_last_move = time_now;
if (step)
{
// Speed parameters, acceleration etc. are here
if (Directional_delay==-1)
{
Directional_delay=150;
Directional_step=16;
}
else if (Directional_delay==150)
Directional_delay=40;
else if (Directional_delay!=0)
Directional_delay=Directional_delay*8/10;
else if (Directional_step<16*4)
Directional_step++;
Directional_last_move = time_now;
// Directional controller UP
if ((Directional_up||Directional_up_left||Directional_up_right) &&
!(Directional_down_right||Directional_down||Directional_down_left))
if ((Directional_up||Directional_emulated_up||Directional_up_left||Directional_up_right) &&
!(Directional_down_right||Directional_down||Directional_emulated_down||Directional_down_left))
{
Cursor_displace(0, -Directional_step/16);
Cursor_displace(0, -step);
}
// Directional controller RIGHT
if ((Directional_up_right||Directional_right||Directional_down_right) &&
!(Directional_down_left||Directional_left||Directional_up_left))
if ((Directional_up_right||Directional_right||Directional_emulated_right||Directional_down_right) &&
!(Directional_down_left||Directional_left||Directional_emulated_left||Directional_up_left))
{
Cursor_displace(Directional_step/16,0);
Cursor_displace(step,0);
}
// Directional controller DOWN
if ((Directional_down_right||Directional_down||Directional_down_left) &&
!(Directional_up_left||Directional_up||Directional_up_right))
if ((Directional_down_right||Directional_down||Directional_emulated_down||Directional_down_left) &&
!(Directional_up_left||Directional_up||Directional_emulated_up||Directional_up_right))
{
Cursor_displace(0, Directional_step/16);
Cursor_displace(0, step);
}
// Directional controller LEFT
if ((Directional_down_left||Directional_left||Directional_up_left) &&
!(Directional_up_right||Directional_right||Directional_down_right))
if ((Directional_down_left||Directional_left||Directional_emulated_left||Directional_up_left) &&
!(Directional_up_right||Directional_right||Directional_emulated_right||Directional_down_right))
{
Cursor_displace(-Directional_step/16,0);
Cursor_displace(-step,0);
}
}
}
@ -757,14 +1037,15 @@ int Get_input(void)
{
Compute_paintbrush_coordinates();
Display_cursor();
return 1;
}
// Commit any pending screen update.
// This is done in this function because it's called after reading
// some user input.
Flush_update();
if (user_feedback_required)
return 1;
return (Mouse_moved!=0) || user_feedback_required;
// Nothing significant happened
if (sleep_time)
SDL_Delay(sleep_time);
return 0;
}
void Adjust_mouse_sensitivity(word fullscreen)
@ -796,3 +1077,74 @@ void Set_mouse_position(void)
Mouse_virtual_y_position = 12*Mouse_Y*Pixel_height;
}
}
int Color_cycling(__attribute__((unused)) void* useless)
{
static byte offset[16];
int i, color;
static SDL_Color PaletteSDL[256];
int changed; // boolean : true if the palette needs a change in this tick.
long now;
static long start=0;
if (start==0)
{
// First run
start = SDL_GetTicks();
return 1;
}
if (!Allow_colorcycling || !Cycling_mode)
return 1;
now = SDL_GetTicks();
changed=0;
// Check all cycles for a change at this tick
for (i=0; i<16; i++)
{
int len;
len=Main_backups->Pages->Gradients->Range[i].End-Main_backups->Pages->Gradients->Range[i].Start+1;
if (len>1 && Main_backups->Pages->Gradients->Range[i].Speed)
{
int new_offset;
new_offset=(now-start)/(int)(1000.0/(Main_backups->Pages->Gradients->Range[i].Speed*0.2856)) % len;
if (!Main_backups->Pages->Gradients->Range[i].Inverse)
new_offset=len - new_offset;
if (new_offset!=offset[i])
changed=1;
offset[i]=new_offset;
}
}
if (changed)
{
// Initialize the palette
for(color=0;color<256;color++)
{
PaletteSDL[color].r=Main_palette[color].R;
PaletteSDL[color].g=Main_palette[color].G;
PaletteSDL[color].b=Main_palette[color].B;
}
for (i=0; i<16; i++)
{
int len;
len=Main_backups->Pages->Gradients->Range[i].End-Main_backups->Pages->Gradients->Range[i].Start+1;
if (len>1 && Main_backups->Pages->Gradients->Range[i].Speed)
{
for(color=Main_backups->Pages->Gradients->Range[i].Start;color<=Main_backups->Pages->Gradients->Range[i].End;color++)
{
PaletteSDL[color].r=Main_palette[Main_backups->Pages->Gradients->Range[i].Start+((color-Main_backups->Pages->Gradients->Range[i].Start+offset[i])%len)].R;
PaletteSDL[color].g=Main_palette[Main_backups->Pages->Gradients->Range[i].Start+((color-Main_backups->Pages->Gradients->Range[i].Start+offset[i])%len)].G;
PaletteSDL[color].b=Main_palette[Main_backups->Pages->Gradients->Range[i].Start+((color-Main_backups->Pages->Gradients->Range[i].Start+offset[i])%len)].B;
}
}
}
SDL_SetPalette(Screen_SDL, SDL_PHYSPAL | SDL_LOGPAL, PaletteSDL,0,256);
}
return 0;
}

View File

@ -33,11 +33,14 @@
/// The latest input variables are held in ::Key, ::Key_ANSI, ::Mouse_X, ::Mouse_Y, ::Mouse_K.
/// Note that ::Key and ::Key_ANSI are not persistent, they will be reset to 0
/// on subsequent calls to ::Get_input().
int Get_input(void);
int Get_input(int sleep_time);
/// Returns true if the keycode has been set as a keyboard shortcut for the function.
int Is_shortcut(word key, word function);
/// Returns true if the function has any shortcut key.
int Has_shortcut(word function);
/// Adjust mouse sensitivity (and actual mouse input mode)
void Adjust_mouse_sensitivity(word fullscreen);
@ -56,3 +59,8 @@ extern int Snap_axis;
extern int Snap_axis_origin_X;
/// For the :Snap_axis mode, sets the origin's point (in image coordinates)
extern int Snap_axis_origin_Y;
///
/// This malloced string is set when a drag-and-drop event
/// brings a file to Grafx2's window.
extern char * Drop_file_name;

View File

@ -2,6 +2,7 @@
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Yves Rizoud
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
@ -32,14 +33,24 @@
#include <fcntl.h>
#include <unistd.h>
#if defined(__amigaos4__)
#if defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__)
#include <proto/dos.h>
#include <sys/types.h>
#include <dirent.h>
#define isHidden(x) (0)
#elif defined(__WIN32__)
#include <dirent.h>
#include <windows.h>
//#include <commdlg.h>
#define isHidden(x) (GetFileAttributesA((x)->d_name)&FILE_ATTRIBUTE_HIDDEN)
#elif defined(__MINT__)
#include <mint/osbind.h>
#include <mint/sysbind.h>
#include <dirent.h>
#define isHidden(x) (0)
#else
#include <dirent.h>
#define isHidden(x) ((x)->d_name[0]=='.')
#endif
#include "struct.h"
@ -276,6 +287,38 @@ void For_each_file(const char * directory_name, void Callback(const char *))
closedir(current_directory);
}
/// Scans a directory, calls Callback for each file or directory in it,
void For_each_directory_entry(const char * directory_name, void Callback(const char *, byte is_file, byte is_directory, byte is_hidden))
{
// Pour scan de répertoire
DIR* current_directory; //Répertoire courant
struct dirent* entry; // Structure de lecture des éléments
char full_filename[MAX_PATH_CHARACTERS];
int filename_position;
strcpy(full_filename, directory_name);
current_directory=opendir(directory_name);
if(current_directory == NULL) return; // Répertoire invalide ...
filename_position = strlen(full_filename);
if (filename_position==0 || strcmp(full_filename+filename_position-1,PATH_SEPARATOR))
{
strcat(full_filename, PATH_SEPARATOR);
filename_position = strlen(full_filename);
}
while ((entry=readdir(current_directory)))
{
struct stat Infos_enreg;
strcpy(&full_filename[filename_position], entry->d_name);
stat(full_filename,&Infos_enreg);
Callback(
full_filename,
S_ISREG(Infos_enreg.st_mode),
S_ISDIR(Infos_enreg.st_mode),
isHidden(entry)?1:0);
}
closedir(current_directory);
}
void Get_full_filename(char * output_name, char * file_name, char * directory_name)
{
strcpy(output_name,directory_name);
@ -299,7 +342,7 @@ int Lock_file_handle = -1;
byte Create_lock_file(const char *file_directory)
{
#ifdef __amigaos__
#if defined (__amigaos__)||(__AROS__)
#warning "Missing code for your platform, please check and correct!"
#else
char lock_filename[MAX_PATH_CHARACTERS];
@ -336,7 +379,7 @@ byte Create_lock_file(const char *file_directory)
return -1;
}
#endif
#endif // __amigaos__
#endif // __amigaos__ or __AROS__
return 0;
}

View File

@ -2,6 +2,7 @@
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Yves Rizoud
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
@ -71,6 +72,8 @@ char * Find_last_slash(const char * str);
#if defined(__WIN32__)
#define PATH_SEPARATOR "\\"
#elif defined(__MINT__)
#define PATH_SEPARATOR "\\"
#else
#define PATH_SEPARATOR "/"
#endif
@ -90,6 +93,10 @@ int Directory_exists(char * directory);
/// Scans a directory, calls Callback for each file in it,
void For_each_file(const char * directory_name, void Callback(const char *));
/// Scans a directory, calls Callback for each file or directory in it,
void For_each_directory_entry(const char * directory_name, void Callback(const char *, byte is_file, byte is_directory, byte is_hidden));
///
/// Creates a fully qualified name from a directory and filename.
/// The point is simply to insert a PATH_SEPARATOR when needed.

View File

@ -2,6 +2,7 @@
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2010 Alexander Filyanov
Copyright 2009 Franck Charlet
Copyright 2008 Yves Rizoud
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
@ -465,38 +466,93 @@ const char * Key_name(word key)
key=key & ~(MOD_CTRL|MOD_ALT|MOD_SHIFT);
if (key>=KEY_JOYBUTTON && key<=KEY_JOYBUTTON+18)
// 99 is only a sanity check
if (key>=KEY_JOYBUTTON && key<=KEY_JOYBUTTON+99)
{
#ifdef __GP2X__
char *button_name;
switch(key-KEY_JOYBUTTON)
{
case GP2X_BUTTON_UP: button_name="[UP]"; break;
case GP2X_BUTTON_DOWN: button_name="[DOWN]"; break;
case GP2X_BUTTON_LEFT: button_name="[LEFT]"; break;
case GP2X_BUTTON_RIGHT: button_name="[RIGHT]"; break;
case GP2X_BUTTON_UPLEFT: button_name="[UP-LEFT]"; break;
case GP2X_BUTTON_UPRIGHT: button_name="[UP-RIGHT]"; break;
case GP2X_BUTTON_DOWNLEFT: button_name="[DOWN-LEFT]"; break;
case GP2X_BUTTON_DOWNRIGHT: button_name="[DOWN-RIGHT]"; break;
case GP2X_BUTTON_CLICK: button_name="[CLICK]"; break;
case GP2X_BUTTON_A: button_name="[A]"; break;
case GP2X_BUTTON_B: button_name="[B]"; break;
case GP2X_BUTTON_X: button_name="[X]"; break;
case GP2X_BUTTON_Y: button_name="[Y]"; break;
case GP2X_BUTTON_L: button_name="[L]"; break;
case GP2X_BUTTON_R: button_name="[R]"; break;
case GP2X_BUTTON_START: button_name="[START]"; break;
case GP2X_BUTTON_SELECT: button_name="[SELECT]"; break;
case GP2X_BUTTON_VOLUP: button_name="[VOL UP]"; break;
case GP2X_BUTTON_VOLDOWN: button_name="[VOL DOWN]"; break;
default: sprintf(buffer+strlen(buffer), "[B%d]", key);return buffer;
{
#ifdef JOY_BUTTON_UP
case JOY_BUTTON_UP: button_name="[UP]"; break;
#endif
#ifdef JOY_BUTTON_DOWN
case JOY_BUTTON_DOWN: button_name="[DOWN]"; break;
#endif
#ifdef JOY_BUTTON_LEFT
case JOY_BUTTON_LEFT: button_name="[LEFT]"; break;
#endif
#ifdef JOY_BUTTON_RIGHT
case JOY_BUTTON_RIGHT: button_name="[RIGHT]"; break;
#endif
#ifdef JOY_BUTTON_UPLEFT
case JOY_BUTTON_UPLEFT: button_name="[UP-LEFT]"; break;
#endif
#ifdef JOY_BUTTON_UPRIGHT
case JOY_BUTTON_UPRIGHT: button_name="[UP-RIGHT]"; break;
#endif
#ifdef JOY_BUTTON_DOWNLEFT
case JOY_BUTTON_DOWNLEFT: button_name="[DOWN-LEFT]"; break;
#endif
#ifdef JOY_BUTTON_DOWNRIGHT
case JOY_BUTTON_DOWNRIGHT: button_name="[DOWN-RIGHT]"; break;
#endif
#ifdef JOY_BUTTON_CLICK
case JOY_BUTTON_CLICK: button_name="[CLICK]"; break;
#endif
#ifdef JOY_BUTTON_A
case JOY_BUTTON_A: button_name="[A]"; break;
#endif
#ifdef JOY_BUTTON_B
case JOY_BUTTON_B: button_name="[B]"; break;
#endif
#ifdef JOY_BUTTON_X
case JOY_BUTTON_X: button_name="[X]"; break;
#endif
#ifdef JOY_BUTTON_Y
case JOY_BUTTON_Y: button_name="[Y]"; break;
#endif
#ifdef JOY_BUTTON_L
case JOY_BUTTON_L: button_name="[L]"; break;
#endif
#ifdef JOY_BUTTON_R
case JOY_BUTTON_R: button_name="[R]"; break;
#endif
#ifdef JOY_BUTTON_START
case JOY_BUTTON_START: button_name="[START]"; break;
#endif
#ifdef JOY_BUTTON_SELECT
case JOY_BUTTON_SELECT: button_name="[SELECT]"; break;
#endif
#ifdef JOY_BUTTON_VOLUP
case JOY_BUTTON_VOLUP: button_name="[VOL UP]"; break;
#endif
#ifdef JOY_BUTTON_VOLDOWN
case JOY_BUTTON_VOLDOWN: button_name="[VOL DOWN]"; break;
#endif
#ifdef JOY_BUTTON_MENU
case JOY_BUTTON_MENU: button_name="[MENU]"; break;
#endif
#ifdef JOY_BUTTON_HOME
case JOY_BUTTON_HOME: button_name="[HOME]"; break;
#endif
#ifdef JOY_BUTTON_HOLD
case JOY_BUTTON_HOLD: button_name="[HOLD]"; break;
#endif
#ifdef JOY_BUTTON_I
case JOY_BUTTON_I: button_name="[BUTTON I]"; break;
#endif
#ifdef JOY_BUTTON_II
case JOY_BUTTON_II: button_name="[BUTTON II]"; break;
#endif
#ifdef JOY_BUTTON_JOY
case JOY_BUTTON_JOY: button_name="[THUMB JOY]"; break;
#endif
default: sprintf(buffer+strlen(buffer), "[B%d]", key-KEY_JOYBUTTON);return buffer;
}
strcat(buffer,button_name);
#else
sprintf(buffer+strlen(buffer), "[B%d]", key-KEY_JOYBUTTON);
#endif
return buffer;
}

View File

@ -2,6 +2,8 @@
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2010 Alexander Filyanov
Copyright 2009 Petter Lindquist
Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet
@ -47,6 +49,8 @@
#include "struct.h"
#include "windows.h"
#include "engine.h"
#include "brush.h"
#include "setup.h"
// -- PKM -------------------------------------------------------------------
void Test_PKM(T_IO_Context *);
@ -121,6 +125,10 @@ void Save_C64(T_IO_Context *);
// -- SCR (Amstrad CPC)
void Save_SCR(T_IO_Context *);
// -- XPM (X PixMap)
// Loading is done through SDL_Image
void Save_XPM(T_IO_Context*);
// -- PNG -------------------------------------------------------------------
#ifndef __no_pnglib__
void Test_PNG(T_IO_Context *);
@ -133,7 +141,7 @@ void Save_PNG(T_IO_Context *);
void Load_SDL_Image(T_IO_Context *);
// ENUM Name TestFunc LoadFunc SaveFunc PalOnly Comment Layers Ext Exts
T_Format File_formats[NB_KNOWN_FORMATS] = {
T_Format File_formats[] = {
{FORMAT_ALL_IMAGES, "(all)", NULL, NULL, NULL, 0, 0, 0, "", "gif;png;bmp;pcx;pkm;lbm;iff;img;sci;scq;scf;scn;sco;pi1;pc1;cel;neo;kcf;pal;c64;koa;koala;fli;bml;cdu;prg;tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico"},
{FORMAT_ALL_FILES, "(*.*)", NULL, NULL, NULL, 0, 0, 0, "", "*"},
{FORMAT_GIF, " gif", Test_GIF, Load_GIF, Save_GIF, 0, 1, 1, "gif", "gif"},
@ -143,7 +151,7 @@ T_Format File_formats[NB_KNOWN_FORMATS] = {
{FORMAT_BMP, " bmp", Test_BMP, Load_BMP, Save_BMP, 0, 0, 0, "bmp", "bmp"},
{FORMAT_PCX, " pcx", Test_PCX, Load_PCX, Save_PCX, 0, 0, 0, "pcx", "pcx"},
{FORMAT_PKM, " pkm", Test_PKM, Load_PKM, Save_PKM, 0, 1, 0, "pkm", "pkm"},
{FORMAT_LBM, " lbm", Test_LBM, Load_LBM, Save_LBM, 0, 0, 0, "lbm", "lbm;iff"},
{FORMAT_LBM, " lbm", Test_LBM, Load_LBM, Save_LBM, 0, 0, 0, "lbm", "lbm;iff;ilbm"},
{FORMAT_IMG, " img", Test_IMG, Load_IMG, Save_IMG, 0, 0, 0, "img", "img"},
{FORMAT_SCx, " sc?", Test_SCx, Load_SCx, Save_SCx, 0, 0, 0, "sc?", "sci;scq;scf;scn;sco"},
{FORMAT_PI1, " pi1", Test_PI1, Load_PI1, Save_PI1, 0, 0, 0, "pi1", "pi1"},
@ -154,9 +162,16 @@ T_Format File_formats[NB_KNOWN_FORMATS] = {
{FORMAT_PAL, " pal", Test_PAL, Load_PAL, Save_PAL, 1, 0, 0, "pal", "pal"},
{FORMAT_C64, " c64", Test_C64, Load_C64, Save_C64, 0, 1, 0, "c64", "c64;koa;koala;fli;bml;cdu;prg"},
{FORMAT_SCR, " cpc", NULL, NULL, Save_SCR, 0, 0, 0, "cpc", "cpc;scr"},
{FORMAT_XPM, " xpm", NULL, NULL, Save_XPM, 0, 0, 0, "xpm", "xpm"},
{FORMAT_MISC,"misc.",NULL, NULL, NULL, 0, 0, 0, "", "tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico"},
};
/// Total number of known file formats
unsigned int Nb_known_formats(void)
{
return sizeof(File_formats)/sizeof(File_formats[0]);
}
/// Set the color of a pixel (on load)
void Set_pixel(T_IO_Context *context, short x_pos, short y_pos, byte color)
{
@ -180,38 +195,32 @@ void Set_pixel(T_IO_Context *context, short x_pos, short y_pos, byte color)
// Chargement des pixels dans la preview
case CONTEXT_PREVIEW:
// Skip pixels of transparent index if :
// - It's the first layer, and image has transparent background.
// - or it's a layer above the first one
if (color == context->Transparent_color && (context->Current_layer > 0 || context->Background_transparent))
// it's a layer above the first one
if (color == context->Transparent_color && context->Current_layer > 0)
break;
if (((x_pos % context->Preview_factor_X)==0) && ((y_pos % context->Preview_factor_Y)==0))
{
// Tag the color as 'used'
context->Preview_usage[color]=1;
// Store pixel
if (context->Ratio == PIXEL_WIDE &&
Pixel_ratio != PIXEL_WIDE &&
Pixel_ratio != PIXEL_WIDE2)
{
Pixel(context->Preview_pos_X+(x_pos/context->Preview_factor_X*2),
context->Preview_pos_Y+(y_pos/context->Preview_factor_Y),
color);
Pixel(context->Preview_pos_X+(x_pos/context->Preview_factor_X*2)+1,
context->Preview_pos_Y+(y_pos/context->Preview_factor_Y),
color);
context->Preview_bitmap[x_pos/context->Preview_factor_X*2 + (y_pos/context->Preview_factor_Y)*PREVIEW_WIDTH*Menu_factor_X]=color;
context->Preview_bitmap[x_pos/context->Preview_factor_X*2+1 + (y_pos/context->Preview_factor_Y)*PREVIEW_WIDTH*Menu_factor_X]=color;
}
else if (context->Ratio == PIXEL_TALL &&
Pixel_ratio != PIXEL_TALL &&
Pixel_ratio != PIXEL_TALL2)
{
Pixel(context->Preview_pos_X+(x_pos/context->Preview_factor_X),
context->Preview_pos_Y+(y_pos/context->Preview_factor_Y*2),
color);
Pixel(context->Preview_pos_X+(x_pos/context->Preview_factor_X),
context->Preview_pos_Y+(y_pos/context->Preview_factor_Y*2)+1,
color);
context->Preview_bitmap[x_pos/context->Preview_factor_X + (y_pos/context->Preview_factor_Y*2)*PREVIEW_WIDTH*Menu_factor_X]=color;
context->Preview_bitmap[x_pos/context->Preview_factor_X + (y_pos/context->Preview_factor_Y*2+1)*PREVIEW_WIDTH*Menu_factor_X]=color;
}
else
Pixel(context->Preview_pos_X+(x_pos/context->Preview_factor_X),
context->Preview_pos_Y+(y_pos/context->Preview_factor_Y),
color);
context->Preview_bitmap[x_pos/context->Preview_factor_X + (y_pos/context->Preview_factor_Y)*PREVIEW_WIDTH*Menu_factor_X]=color;
}
break;
@ -234,8 +243,6 @@ void Palette_loaded(T_IO_Context *context)
{
case CONTEXT_MAIN_IMAGE:
case CONTEXT_PREVIEW:
Set_palette(context->Palette);
break;
case CONTEXT_BRUSH:
case CONTEXT_SURFACE:
break;
@ -243,67 +250,7 @@ void Palette_loaded(T_IO_Context *context)
switch (context->Type)
{
case CONTEXT_PREVIEW:
Compute_optimal_menu_colors(context->Palette);
/*
if(
(
context->Palette[MC_Black].R==context->Palette[MC_Dark].R &&
context->Palette[MC_Black].G==context->Palette[MC_Dark].G &&
context->Palette[MC_Black].B==context->Palette[MC_Dark].B
) ||
(
context->Palette[MC_Light].R==context->Palette[MC_Dark].R &&
context->Palette[MC_Light].G==context->Palette[MC_Dark].G &&
context->Palette[MC_Light].B==context->Palette[MC_Dark].B
) ||
(
context->Palette[MC_White].R==context->Palette[MC_Light].R &&
context->Palette[MC_White].G==context->Palette[MC_Light].G &&
context->Palette[MC_White].B==context->Palette[MC_Light].B
)
)
{
// Si on charge une image monochrome, le fileselect ne sera plus visible. Dans ce cas on force quelques couleurs à des valeurs sures
int black =
Main_palette[MC_Black].R +
Main_palette[MC_Black].G +
Main_palette[MC_Black].B;
int white =
Main_palette[MC_White].R +
Main_palette[MC_White].G +
Main_palette[MC_White].B;
//Set_color(MC_Light,(2*white+black)/9,(2*white+black)/9,(2*white+black)/9);
//Set_color(MC_Dark,(2*black+white)/9,(2*black+white)/9,(2*black+white)/9);
Main_palette[MC_Dark].R=(2*black+white)/9;
Main_palette[MC_Dark].G=(2*black+white)/9;
Main_palette[MC_Dark].B=(2*black+white)/9;
Main_palette[MC_Light].R=(2*white+black)/9;
Main_palette[MC_Light].G=(2*white+black)/9;
Main_palette[MC_Light].B=(2*white+black)/9;
Set_palette(Main_palette);
}
*/
Remap_screen_after_menu_colors_change();
// Preview palette
if (Get_fileformat(context->Format)->Palette_only)
{
short index;
if (context->Type == CONTEXT_PREVIEW)
for (index=0; index<256; index++)
Window_rectangle(183+(index/16)*7,95+(index&15)*5,5,5,index);
Update_window_area(183,95,120,80);
}
break;
case CONTEXT_PREVIEW:
case CONTEXT_MAIN_IMAGE:
case CONTEXT_BRUSH:
case CONTEXT_SURFACE:
@ -336,17 +283,17 @@ void Set_pixel_24b(T_IO_Context *context, short x_pos, short y_pos, byte r, byte
break;
case CONTEXT_PREVIEW:
{
if (((x_pos % context->Preview_factor_X)==0) && ((y_pos % context->Preview_factor_Y)==0))
{
color=((r >> 5) << 5) |
((g >> 5) << 2) |
((b >> 6));
Pixel(context->Preview_pos_X+(x_pos/context->Preview_factor_X),
context->Preview_pos_Y+(y_pos/context->Preview_factor_Y),
color);
}
if (((x_pos % context->Preview_factor_X)==0) && ((y_pos % context->Preview_factor_Y)==0))
{
color=((r >> 5) << 5) |
((g >> 5) << 2) |
((b >> 6));
// Tag the color as 'used'
context->Preview_usage[color]=1;
context->Preview_bitmap[x_pos/context->Preview_factor_X + (y_pos/context->Preview_factor_Y)*PREVIEW_WIDTH*Menu_factor_X]=color;
}
break;
}
@ -388,6 +335,11 @@ void Pre_load(T_IO_Context *context, short width, short height, long file_size,
// Preview
case CONTEXT_PREVIEW:
// Préparation du chargement d'une preview:
context->Preview_bitmap=malloc(PREVIEW_WIDTH*PREVIEW_HEIGHT*Menu_factor_X*Menu_factor_Y);
if (!context->Preview_bitmap)
File_error=1;
// Affichage des données "Image size:"
if ((width<10000) && (height<10000))
{
@ -426,11 +378,12 @@ void Pre_load(T_IO_Context *context, short width, short height, long file_size,
{
Print_in_window( 59,59,Get_fileformat(format)->Label,MC_Black,MC_Light);
}
// On efface le commentaire précédent
Window_rectangle(45,70,32*8,8,MC_Light);
// Affichage du commentaire
Print_in_window(45,70,context->Comment,MC_Black,MC_Light);
if (Get_fileformat(format)->Comment)
Print_in_window(45,70,Main_comment,MC_Black,MC_Light);
// Calcul des données nécessaires à l'affichage de la preview:
if (ratio == PIXEL_WIDE &&
@ -442,8 +395,8 @@ void Pre_load(T_IO_Context *context, short width, short height, long file_size,
Pixel_ratio != PIXEL_TALL2)
height*=2;
context->Preview_factor_X=Round_div_max(width,122*Menu_factor_X);
context->Preview_factor_Y=Round_div_max(height, 82*Menu_factor_Y);
context->Preview_factor_X=Round_div_max(width,120*Menu_factor_X);
context->Preview_factor_Y=Round_div_max(height, 80*Menu_factor_Y);
if ( (!Config.Maximize_preview) && (context->Preview_factor_X!=context->Preview_factor_Y) )
{
@ -457,17 +410,17 @@ void Pre_load(T_IO_Context *context, short width, short height, long file_size,
context->Preview_pos_Y=Window_pos_Y+ 95*Menu_factor_Y;
// On nettoie la zone où va s'afficher la preview:
Window_rectangle(183,95,120,80,MC_Light);
Window_rectangle(183,95,PREVIEW_WIDTH,PREVIEW_HEIGHT,MC_Light);
// Un update pour couvrir les 4 zones: 3 libellés plus le commentaire
Update_window_area(45,48,256,30);
// Zone de preview
Update_window_area(183,95,120,80);
Update_window_area(183,95,PREVIEW_WIDTH,PREVIEW_HEIGHT);
break;
// Other loading
case CONTEXT_MAIN_IMAGE:
if (Backup_with_new_dimensions(0,1,width,height))
if (Backup_new_image(1,width,height))
{
// La nouvelle page a pu être allouée, elle est pour l'instant pleine
// de 0s. Elle fait Main_image_width de large.
@ -605,7 +558,10 @@ void Load_image(T_IO_Context *context)
{
unsigned int index; // index de balayage des formats
T_Format *format = &(File_formats[2]); // Format du fichier à charger
int i;
// Not sure it's the best place...
context->Color_cycles=0;
// On place par défaut File_error à vrai au cas où on ne sache pas
// charger le format du fichier:
@ -622,7 +578,7 @@ void Load_image(T_IO_Context *context)
{
// Sinon, on va devoir scanner les différents formats qu'on connait pour
// savoir à quel format est le fichier:
for (index=0; index < NB_KNOWN_FORMATS; index++)
for (index=0; index < Nb_known_formats(); index++)
{
format = Get_fileformat(index);
// Loadable format
@ -714,7 +670,7 @@ void Load_image(T_IO_Context *context)
case CONTEXT_SURFACE:
if (Convert_24b_bitmap_to_256(context->Surface->pixels,context->Buffer_image_24b,context->Width,context->Height,context->Palette))
File_error=1;
File_error=1;
break;
}
@ -722,11 +678,34 @@ void Load_image(T_IO_Context *context)
free(context->Buffer_image_24b);
context->Buffer_image_24b = NULL;
}
else if (context->Type == CONTEXT_MAIN_IMAGE)
{
// Non-24b main image: Add menu colors
if (Config.Safety_colors)
{
dword color_usage[256];
memset(color_usage,0,sizeof(color_usage));
if (Count_used_colors(color_usage)<252)
{
int gui_index=0;
int c;
for (c=255; c>=0 && gui_index<4; c--)
{
if (color_usage[c]==0)
{
context->Palette[c]=*Favorite_GUI_color(gui_index);
gui_index++;
}
}
}
}
}
if (context->Type == CONTEXT_MAIN_IMAGE)
{
if ( File_error!=1)
{
Set_palette(context->Palette);
if (format->Palette_only)
{
// Make a backup step
@ -773,6 +752,21 @@ void Load_image(T_IO_Context *context)
Main_image_width=1;
if (Main_image_height<1)
Main_image_height=1;
// Color cyling ranges:
for (i=0; i<16; i++)
Main_backups->Pages->Gradients->Range[i].Speed=0;
for (i=0; i<context->Color_cycles; i++)
{
Main_backups->Pages->Gradients->Range[i].Start=context->Cycle_range[i].Start;
Main_backups->Pages->Gradients->Range[i].End=context->Cycle_range[i].End;
Main_backups->Pages->Gradients->Range[i].Inverse=context->Cycle_range[i].Inverse;
Main_backups->Pages->Gradients->Range[i].Speed=context->Cycle_range[i].Speed;
}
// Comment
strcpy(Main_comment, context->Comment);
}
}
else if (File_error!=1)
@ -791,19 +785,16 @@ void Load_image(T_IO_Context *context)
}
else if (context->Type == CONTEXT_BRUSH && File_error==0)
{
free(Brush);
Brush=context->Buffer_image;
context->Buffer_image = NULL;
Brush_width=context->Width;
Brush_height=context->Height;
free(Smear_brush);
Smear_brush_width=(Brush_width>MAX_PAINTBRUSH_SIZE)?Brush_width:MAX_PAINTBRUSH_SIZE;
Smear_brush_height=(Brush_height>MAX_PAINTBRUSH_SIZE)?Brush_height:MAX_PAINTBRUSH_SIZE;
Smear_brush=(byte *)malloc(Smear_brush_width*Smear_brush_height);
if (!Smear_brush)
if (Realloc_brush(context->Width, context->Height, context->Buffer_image, NULL))
{
File_error=3;
free(context->Buffer_image);
}
memcpy(Brush_original_palette, context->Palette, sizeof(T_Palette));
Remap_brush();
context->Buffer_image = NULL;
}
else if (context->Type == CONTEXT_SURFACE)
{
@ -822,6 +813,91 @@ void Load_image(T_IO_Context *context)
SDL_SetColors(context->Surface, colors, 0, 256);
}
}
else if (context->Type == CONTEXT_PREVIEW
/*&& !context->Buffer_image_24b*/
/*&& !Get_fileformat(context->Format)->Palette_only*/)
{
// Try to adapt the palette to accomodate the GUI.
int c;
int count_unused;
byte unused_color[4];
count_unused=0;
// Try find 4 unused colors and insert good colors there
for (c=255; c>=0 && count_unused<4; c--)
{
if (!context->Preview_usage[c])
{
unused_color[count_unused]=c;
count_unused++;
}
}
// Found! replace them with some favorites
if (count_unused==4)
{
int gui_index;
for (gui_index=0; gui_index<4; gui_index++)
{
context->Palette[unused_color[gui_index]]=*Favorite_GUI_color(gui_index);
}
}
// All preview display is here
// Update palette and screen first
Compute_optimal_menu_colors(context->Palette);
Remap_screen_after_menu_colors_change();
Set_palette(context->Palette);
// Display palette preview
if (Get_fileformat(context->Format)->Palette_only)
{
short index;
if (context->Type == CONTEXT_PREVIEW)
for (index=0; index<256; index++)
Window_rectangle(183+(index/16)*7,95+(index&15)*5,5,5,index);
}
// Display normal image
else if (context->Preview_bitmap)
{
int x_pos,y_pos;
int width,height;
width=context->Width/context->Preview_factor_X;
height=context->Height/context->Preview_factor_Y;
if (context->Ratio == PIXEL_WIDE &&
Pixel_ratio != PIXEL_WIDE &&
Pixel_ratio != PIXEL_WIDE2)
width*=2;
else if (context->Ratio == PIXEL_TALL &&
Pixel_ratio != PIXEL_TALL &&
Pixel_ratio != PIXEL_TALL2)
height*=2;
for (y_pos=0; y_pos<height;y_pos++)
for (x_pos=0; x_pos<width;x_pos++)
{
byte color=context->Preview_bitmap[x_pos+y_pos*PREVIEW_WIDTH*Menu_factor_X];
// Skip transparent if image has transparent background.
if (color == context->Transparent_color && context->Background_transparent)
color=MC_Window;
Pixel(context->Preview_pos_X+x_pos,
context->Preview_pos_Y+y_pos,
color);
}
}
// Refresh modified part
Update_window_area(183,95,PREVIEW_WIDTH,PREVIEW_HEIGHT);
// Preview comment
Print_in_window(45,70,context->Comment,MC_Black,MC_Light);
//Update_window_area(45,70,32*8,8);
}
}
@ -916,8 +992,10 @@ void Load_SDL_Image(T_IO_Context *context)
}
else
{
// Hi/Trucolor
Pre_load(context, surface->w, surface->h, file_size ,FORMAT_ALL_IMAGES, PIXEL_SIMPLE, 1);
{
// Hi/Trucolor
Pre_load(context, surface->w, surface->h, file_size ,FORMAT_ALL_IMAGES, PIXEL_SIMPLE, 1);
}
for (y_pos=0; y_pos<context->Height; y_pos++)
{
@ -938,8 +1016,10 @@ void Load_SDL_Image(T_IO_Context *context)
SDL_FreeSurface(surface);
}
///
/// Load an arbitrary SDL_Surface.
SDL_Surface * Load_surface(char *full_name)
/// @param gradients Pass the address of a target T_Gradient_array if you want the gradients, NULL otherwise
SDL_Surface * Load_surface(char *full_name, T_Gradient_array *gradients)
{
SDL_Surface * bmp=NULL;
T_IO_Context context;
@ -948,8 +1028,23 @@ SDL_Surface * Load_surface(char *full_name)
Load_image(&context);
if (context.Surface)
{
bmp=context.Surface;
// Caller wants the gradients:
if (gradients != NULL)
{
int i;
memset(gradients, 0, sizeof(T_Gradient_array));
for (i=0; i<context.Color_cycles; i++)
{
gradients->Range[i].Start=context.Cycle_range[i].Start;
gradients->Range[i].End=context.Cycle_range[i].End;
gradients->Range[i].Inverse=context.Cycle_range[i].Inverse;
gradients->Range[i].Speed=context.Cycle_range[i].Speed;
}
}
}
Destroy_context(&context);
return bmp;
@ -1011,10 +1106,12 @@ void Emergency_backup(const char *fname, byte *source, int width, int height, T_
void Image_emergency_backup()
{
#ifndef NOLAYERS
if (Main_backups && Main_backups->Pages && Main_backups->Pages->Nb_layers == 1)
Emergency_backup("a999999.bkp",Main_screen, Main_image_width, Main_image_height, &Main_palette);
Emergency_backup(SAFETYBACKUP_PREFIX_A "999999" BACKUP_FILE_EXTENSION,Main_screen, Main_image_width, Main_image_height, &Main_palette);
if (Spare_backups && Spare_backups->Pages && Spare_backups->Pages->Nb_layers == 1)
Emergency_backup("b999999.bkp",Spare_visible_image.Image, Spare_image_width, Spare_image_height, &Spare_palette);
Emergency_backup(SAFETYBACKUP_PREFIX_B "999999" BACKUP_FILE_EXTENSION,Spare_visible_image.Image, Spare_image_width, Spare_image_height, &Spare_palette);
#endif
}
T_Format * Get_fileformat(byte format)
@ -1022,7 +1119,7 @@ T_Format * Get_fileformat(byte format)
unsigned int i;
T_Format * safe_default = File_formats;
for (i=0; i < NB_KNOWN_FORMATS; i++)
for (i=0; i < Nb_known_formats(); i++)
{
if (File_formats[i].Identifier == format)
return &(File_formats[i]);
@ -1041,11 +1138,12 @@ byte Get_pixel(T_IO_Context *context, short x, short y)
return *(context->Target_address + y*context->Pitch + x);
}
/// Cleans up resources (currently: the 24bit buffer)
/// Cleans up resources
void Destroy_context(T_IO_Context *context)
{
free(context->Buffer_image_24b);
free(context->Buffer_image);
free(context->Preview_bitmap);
memset(context, 0, sizeof(T_IO_Context));
}
@ -1069,6 +1167,8 @@ void Init_context_backup_image(T_IO_Context * context, char *file_name, char *fi
/// Setup for loading/saving the current main image
void Init_context_layered_image(T_IO_Context * context, char *file_name, char *file_directory)
{
int i;
memset(context, 0, sizeof(T_IO_Context));
context->Type = CONTEXT_MAIN_IMAGE;
@ -1091,6 +1191,18 @@ void Init_context_layered_image(T_IO_Context * context, char *file_name, char *f
context->Target_address=Main_backups->Pages->Image[0];
context->Pitch=Main_image_width;
// Color cyling ranges:
for (i=0; i<16; i++)
{
if (Main_backups->Pages->Gradients->Range[i].Start!=Main_backups->Pages->Gradients->Range[i].End)
{
context->Cycle_range[context->Color_cycles].Start=Main_backups->Pages->Gradients->Range[i].Start;
context->Cycle_range[context->Color_cycles].End=Main_backups->Pages->Gradients->Range[i].End;
context->Cycle_range[context->Color_cycles].Inverse=Main_backups->Pages->Gradients->Range[i].Inverse;
context->Cycle_range[context->Color_cycles].Speed=Main_backups->Pages->Gradients->Range[i].Speed;
context->Color_cycles++;
}
}
}
/// Setup for loading/saving the flattened version of current main image
@ -1332,8 +1444,13 @@ int Check_recovery(void)
int restored_main;
// First check if can write backups
if (Create_lock_file(Config_directory))
#if defined (__MINT__)
//TODO: enable file lock under Freemint only
return 0;
#else
if (Create_lock_file(Config_directory))
return -1;
#endif
Safety_backup_active=1;
@ -1389,7 +1506,7 @@ void Rotate_safety_backups(void)
{
// Clear a previous save (rotating saves)
sprintf(deleted_file, "%s%c%6.6d.bkp",
sprintf(deleted_file, "%s%c%6.6d" BACKUP_FILE_EXTENSION,
Config_directory,
Main_safety_backup_prefix,
(Uint32)(Main_safety_number + 1000000l - Rotation_safety_backup) % (Uint32)1000000l);
@ -1400,7 +1517,7 @@ void Rotate_safety_backups(void)
Main_time_of_safety_backup=now;
// Create a new file name and save
sprintf(file_name, "%c%6.6d.bkp",
sprintf(file_name, "%c%6.6d" BACKUP_FILE_EXTENSION,
Main_safety_backup_prefix,
(Uint32)Main_safety_number);
Init_context_backup_image(&context, file_name, Config_directory);
@ -1442,6 +1559,10 @@ void Delete_safety_backups(void)
}
// Release lock file
#if defined (__MINT__)
//TODO: release file lock under Freemint only
#else
Release_lock_file(Config_directory);
#endif
}

View File

@ -37,6 +37,14 @@ enum CONTEXT_TYPE {
CONTEXT_SURFACE,
};
/// Data for a cycling color series. Heavily cloned from T_Gradient_array.
typedef struct
{
byte Start; ///< First color
byte End; ///< Last color
byte Inverse; ///< Boolean, true if the gradient goes in descending order
byte Speed; ///< Frequency of cycling, from 1 (slow) to 64 (fast)
} T_Color_cycle;
typedef struct
{
@ -71,6 +79,9 @@ typedef struct
/// Original file directory, stored in GIF file
char * Original_file_directory;
byte Color_cycles;
T_Color_cycle Cycle_range[16];
/// Internal: during load, marks which layer is being loaded.
short Current_layer;
@ -87,12 +98,17 @@ typedef struct
short Preview_factor_Y;
short Preview_pos_X;
short Preview_pos_Y;
byte *Preview_bitmap;
byte Preview_usage[256];
// Internal: returned surface for SDL_Surface case
SDL_Surface * Surface;
} T_IO_Context;
#define PREVIEW_WIDTH 120
#define PREVIEW_HEIGHT 80
/// Type of a function that can be called for a T_IO_Context. Kind of a method.
typedef void (* Func_IO) (T_IO_Context *);
@ -165,8 +181,10 @@ extern T_Format File_formats[];
/// is too high.
void Image_emergency_backup(void);
///
/// Load an arbitrary SDL_Surface.
SDL_Surface * Load_surface(char *full_name);
/// @param gradients Pass the address of a target T_Gradient_array if you want the gradients, NULL otherwise
SDL_Surface * Load_surface(char *full_name, T_Gradient_array *gradients);
/*
@ -178,12 +196,8 @@ T_Format * Get_fileformat(byte format);
// -- File formats
#ifndef __no_pnglib__
#define NB_KNOWN_FORMATS 19 ///< Total number of known file formats.
#else
// Without pnglib
#define NB_KNOWN_FORMATS 18 ///< Total number of known file formats.
#endif
/// Total number of known file formats
unsigned int Nb_known_formats(void);
// Internal use
@ -210,7 +224,6 @@ void Set_layer(T_IO_Context *context, byte layer);
// =================================================================
// This is here and not in fileformats.c because the emergency save uses it...
#pragma pack(1)
typedef struct
{
byte Filler1[6];
@ -219,7 +232,6 @@ typedef struct
byte Filler2[118];
T_Palette Palette;
} T_IMG_Header;
#pragma pack()
// Data for 24bit loading

View File

@ -2,6 +2,7 @@
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2009 Pasi Kallinen
Copyright 2008 Peter Gordon
Copyright 2008 Franck Charlet
@ -40,7 +41,7 @@
// There is no WM on the GP2X...
#ifndef __GP2X__
#if !defined(__GP2X__) && !defined(__WIZ__) && !defined(__CAANOO__)
#include <SDL_syswm.h>
#endif
@ -65,11 +66,14 @@
#include "brush.h"
#include "palette.h"
#include "realpath.h"
#include "input.h"
#if defined(__WIN32__)
#include <windows.h>
#include <shlwapi.h>
#define chdir(dir) SetCurrentDirectory(dir)
#elif defined (__MINT__)
#include <mint/osbind.h>
#elif defined(__macosx__)
#import <corefoundation/corefoundation.h>
#import <sys/param.h>
@ -85,6 +89,8 @@
extern DECLSPEC int SDLCALL SDL_putenv(const char *variable);
#endif
extern char Program_version[]; // generated in pversion.c
//--- Affichage de la syntaxe, et de la liste des modes vidéos disponibles ---
void Display_syntax(void)
{
@ -139,7 +145,7 @@ void Error_function(int error_code, const char *filename, int line_number, const
for (index=0;index<=255;index++)
temp_palette[index].R=255;
Set_palette(temp_palette);
SDL_Delay(500);
Delay_with_active_mouse(50); // Half a second of red flash
Set_palette(Main_palette);
}
else
@ -400,22 +406,39 @@ int Analyze_command_line(int argc, char * argv[], char *main_filename, char *mai
return file_in_command_line;
}
// Compile-time assertions:
#define CT_ASSERT(e) extern char (*ct_assert(void)) [sizeof(char[1 - 2*!(e)])]
// This line will raise an error at compile time
// when sizeof(T_Components) is not 3.
CT_ASSERT(sizeof(T_Components)==3);
// This line will raise an error at compile time
// when sizeof(T_Palette) is not 768.
CT_ASSERT(sizeof(T_Palette)==768);
// ------------------------ Initialiser le programme -------------------------
// Returns 0 on fail
int Init_program(int argc,char * argv[])
{
{
int temp;
int starting_videomode;
static char program_directory[MAX_PATH_CHARACTERS];
T_Gui_skin *gfx;
int file_in_command_line;
T_Gradient_array initial_gradients;
static char main_filename [MAX_PATH_CHARACTERS];
static char main_directory[MAX_PATH_CHARACTERS];
static char spare_filename [MAX_PATH_CHARACTERS];
static char spare_directory[MAX_PATH_CHARACTERS];
#if defined(__MINT__)
printf("===============================\n");
printf(" /|\\ GrafX2 %.19s\n", Program_version);
printf(" compilation date: %.16s\n", __DATE__);
printf("===============================\n");
#endif
// On crée dès maintenant les descripteurs des listes de pages pour la page
// principale et la page de brouillon afin que leurs champs ne soient pas
// invalide lors des appels aux multiples fonctions manipulées à
@ -431,9 +454,12 @@ int Init_program(int argc,char * argv[])
Set_data_directory(program_directory,Data_directory);
// Choose directory for settings (read/write)
Set_config_directory(program_directory,Config_directory);
// On détermine le répertoire courant:
#if defined(__MINT__)
strcpy(Main_current_directory,program_directory);
#else
// On détermine le répertoire courant:
getcwd(Main_current_directory,256);
#endif
// On en profite pour le mémoriser dans le répertoire principal:
strcpy(Initial_directory,Main_current_directory);
@ -473,8 +499,6 @@ int Init_program(int argc,char * argv[])
// On initialise d'ot' trucs
Main_offset_X=0;
Main_offset_Y=0;
Old_main_offset_X=0;
Old_main_offset_Y=0;
Main_separator_position=0;
Main_X_zoom=0;
Main_separator_proportion=INITIAL_SEPARATOR_PROPORTION;
@ -486,8 +510,6 @@ int Init_program(int argc,char * argv[])
Main_magnifier_offset_Y=0;
Spare_offset_X=0;
Spare_offset_Y=0;
Old_spare_offset_X=0;
Old_spare_offset_Y=0;
Spare_separator_position=0;
Spare_X_zoom=0;
Spare_separator_proportion=INITIAL_SEPARATOR_PROPORTION;
@ -497,62 +519,27 @@ int Init_program(int argc,char * argv[])
Spare_magnifier_width=0;
Spare_magnifier_offset_X=0;
Spare_magnifier_offset_Y=0;
Keyboard_click_allowed = 0;
Keyboard_click_allowed = 1;
Main_safety_backup_prefix = 'a';
Spare_safety_backup_prefix = 'b';
Main_safety_backup_prefix = SAFETYBACKUP_PREFIX_A[0];
Spare_safety_backup_prefix = SAFETYBACKUP_PREFIX_B[0];
Main_time_of_safety_backup = 0;
Spare_time_of_safety_backup = 0;
// SDL
if(SDL_Init(SDL_INIT_TIMER|SDL_INIT_VIDEO|SDL_INIT_JOYSTICK) < 0)
if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_JOYSTICK) < 0)
{
// The program can't continue without that anyway
printf("Couldn't initialize SDL.\n");
return(0);
}
Joystick = SDL_JoystickOpen(0);
SDL_EnableKeyRepeat(250, 32);
SDL_EnableUNICODE(SDL_ENABLE);
SDL_WM_SetCaption("GrafX2","GrafX2");
{
// Routine pour définir l'icone.
char icon_path[MAX_PATH_CHARACTERS];
SDL_Surface * icon;
sprintf(icon_path, "%s%s", Data_directory, "gfx2.gif");
icon = IMG_Load(icon_path);
if (icon && icon->w == 32 && icon->h == 32)
{
Uint32 pink;
pink = SDL_MapRGB(icon->format, 255, 0, 255);
if (icon->format->BitsPerPixel == 8)
{
SDL_SetColorKey(icon, SDL_SRCCOLORKEY, pink);
SDL_WM_SetIcon(icon,NULL);
}
else
{
byte *icon_mask;
int x,y;
icon_mask=malloc(128);
memset(icon_mask,0,128);
for (y=0;y<32;y++)
for (x=0;x<32;x++)
if (Get_SDL_pixel_hicolor(icon, x, y) != pink)
icon_mask[(y*32+x)/8] |=0x80>>(x&7);
SDL_WM_SetIcon(icon,icon_mask);
free(icon_mask);
icon_mask = NULL;
}
SDL_FreeSurface(icon);
}
}
Define_icon();
// Texte
Init_text();
@ -574,7 +561,6 @@ int Init_program(int argc,char * argv[])
// Données sur le pinceau:
Paintbrush_X=0;
Paintbrush_Y=0;
Paintbrush_shape=PAINTBRUSH_SHAPE_ROUND;
Paintbrush_hidden=0;
// On initialise tout ce qui concerne les opérations et les effets
@ -634,6 +620,25 @@ int Init_program(int argc,char * argv[])
Windows_open=0;
// Paintbrush
if (!(Paintbrush_sprite=(byte *)malloc(MAX_PAINTBRUSH_SIZE*MAX_PAINTBRUSH_SIZE))) Error(ERROR_MEMORY);
// Load preset paintbrushes (uses Paintbrush_ variables)
Init_paintbrushes();
// Set a valid paintbrush afterwards
*Paintbrush_sprite=1;
Paintbrush_width=1;
Paintbrush_height=1;
Paintbrush_offset_X=0;
Paintbrush_offset_Y=0;
Paintbrush_shape=PAINTBRUSH_SHAPE_ROUND;
#if defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__)
// Prefer cycling active by default
Cycling_mode=1;
#endif
// Charger la configuration des touches
Set_config_defaults();
@ -662,10 +667,10 @@ int Init_program(int argc,char * argv[])
Help_position=0;
// Load sprites, palette etc.
gfx = Load_graphics(Config.Skin_file);
gfx = Load_graphics(Config.Skin_file, &initial_gradients);
if (gfx == NULL)
{
gfx = Load_graphics("skin_DPaint.png");
gfx = Load_graphics(DEFAULT_SKIN_FILENAME, &initial_gradients);
if (gfx == NULL)
{
printf("%s", Gui_loading_error_message);
@ -678,7 +683,10 @@ int Init_program(int argc,char * argv[])
// Gfx->Default_palette[MC_Dark] =Config.Fav_menu_colors[1];
// Gfx->Default_palette[MC_Light]=Config.Fav_menu_colors[2];
// Gfx->Default_palette[MC_White]=Config.Fav_menu_colors[3];
// Compute_optimal_menu_colors(Gfx->Default_palette);
// Even when using the skin's palette, if RGB range is small
// the colors will be unusable.
Compute_optimal_menu_colors(Gfx->Default_palette);
// Infos sur les trames (Sieve)
Sieve_mode=0;
@ -686,9 +694,9 @@ int Init_program(int argc,char * argv[])
// Font
if (!(Menu_font=Load_font(Config.Font_file)))
if (!(Menu_font=Load_font("font_DPaint.png")))
if (!(Menu_font=Load_font(DEFAULT_FONT_FILENAME)))
{
printf("Unable to open the default font file: %s\n", "font_Classic.png");
printf("Unable to open the default font file: %s\n", DEFAULT_FONT_FILENAME);
Error(ERROR_GUI_MISSING);
}
@ -701,11 +709,6 @@ int Init_program(int argc,char * argv[])
if (!(Brush =(byte *)malloc( 1* 1))) Error(ERROR_MEMORY);
if (!(Smear_brush =(byte *)malloc(MAX_PAINTBRUSH_SIZE*MAX_PAINTBRUSH_SIZE))) Error(ERROR_MEMORY);
// Pinceau
if (!(Paintbrush_sprite=(byte *)malloc(MAX_PAINTBRUSH_SIZE*MAX_PAINTBRUSH_SIZE))) Error(ERROR_MEMORY);
*Paintbrush_sprite=1;
Paintbrush_width=1;
Paintbrush_height=1;
starting_videomode=Current_resolution;
Horizontal_line_buffer=NULL;
@ -731,6 +734,9 @@ int Init_program(int argc,char * argv[])
SetWindowPos(pInfo.window, 0, Config.Window_pos_x, Config.Window_pos_y, 0, 0, SWP_NOSIZE);
}
}
// Open a console for debugging...
//ActivateConsole();
#endif
Main_image_width=Screen_width/Pixel_width;
@ -745,15 +751,29 @@ int Init_program(int argc,char * argv[])
// Nettoyage de l'écran virtuel (les autres recevront celui-ci par copie)
memset(Main_screen,0,Main_image_width*Main_image_height);
// Now that the backup system is there, we can store the gradients.
memcpy(Main_backups->Pages->Gradients->Range, initial_gradients.Range, sizeof(initial_gradients.Range));
memcpy(Spare_backups->Pages->Gradients->Range, initial_gradients.Range, sizeof(initial_gradients.Range));
Gradient_function=Gradient_basic;
Gradient_lower_bound=0;
Gradient_upper_bound=0;
Gradient_random_factor=1;
Gradient_bounds_range=1;
Current_gradient=0;
// Initialisation de diverses variables par calcul:
Compute_magnifier_data();
Compute_limits();
Compute_paintbrush_coordinates();
// On affiche le menu:
Display_menu();
Display_paintbrush_in_menu();
Display_sprite_in_menu(BUTTON_PAL_LEFT,18+(Config.Palette_vertical!=0));
Display_sprite_in_menu(BUTTON_PAL_LEFT,Config.Palette_vertical?MENU_SPRITE_VERTICAL_PALETTE_SCROLL:-1);
Display_menu();
Draw_menu_button(BUTTON_PAL_LEFT,BUTTON_RELEASED);
Draw_menu_button(BUTTON_PAL_RIGHT,BUTTON_RELEASED);
// On affiche le curseur pour débutter correctement l'état du programme:
Display_cursor();
@ -770,8 +790,11 @@ int Init_program(int argc,char * argv[])
// On initialise la brosse initiale à 1 pixel blanc:
Brush_width=1;
Brush_height=1;
for (temp=0;temp<256;temp++)
Brush_colormap[temp]=temp;
Capture_brush(0,0,0,0,0);
*Brush=MC_White;
*Brush_original_pixels=MC_White;
// Test de recuperation de fichiers sauvés
switch (Check_recovery())
@ -843,6 +866,9 @@ int Init_program(int argc,char * argv[])
break;
}
}
Allow_drag_and_drop(1);
return(1);
}
@ -908,6 +934,12 @@ void Program_shutdown(void)
Error(ERROR_MISSING_DIRECTORY);
SDL_Quit();
#if defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__)
chdir("/usr/gp2x");
execl("/usr/gp2x/gp2xmenu", "/usr/gp2x/gp2xmenu", NULL);
#endif
}

View File

@ -2,6 +2,7 @@
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet
Copyright 2007 Adrien Destugues
@ -177,7 +178,8 @@ void Wait_end_of_click(void)
{
// On désactive tous les raccourcis clavier
while(Mouse_K) if(!Get_input()) SDL_Delay(20);
while(Mouse_K)
Get_input(20);
}
void Clear_current_image_with_stencil(byte color, byte * stencil)
@ -339,7 +341,7 @@ void Rotate_270_deg_lowlevel(byte * source, byte * dest, short width, short heig
// Replace une couleur par une autre dans un buffer
void Remap_general_lowlevel(byte * conversion_table,byte * buffer,short width,short height,short buffer_width)
void Remap_general_lowlevel(byte * conversion_table,byte * in_buffer, byte *out_buffer,short width,short height,short buffer_width)
{
int dx,cx;
@ -349,17 +351,19 @@ void Remap_general_lowlevel(byte * conversion_table,byte * buffer,short width,sh
// Pour chaque pixel
for(cx=width;cx>0;cx--)
{
*buffer = conversion_table[*buffer];
buffer++;
*out_buffer = conversion_table[*in_buffer];
in_buffer++;
out_buffer++;
}
buffer += buffer_width-width;
in_buffer += buffer_width-width;
out_buffer += buffer_width-width;
}
}
void Copy_image_to_brush(short start_x,short start_y,short Brush_width,short Brush_height,word image_width)
{
byte* src=start_y*image_width+start_x+Main_backups->Pages->Image[Main_current_layer]; //Adr départ image (ESI)
byte* dest=Brush; //Adr dest brosse (EDI)
byte* dest=Brush_original_pixels; //Adr dest brosse (EDI)
int dx;
for (dx=Brush_height;dx!=0;dx--)
@ -499,6 +503,22 @@ byte Effect_substractive_colorize(word x,word y,byte color)
blue<blue_under?blue:blue_under);
}
byte Effect_alpha_colorize (word x,word y,byte color)
{
byte color_under = Read_pixel_from_feedback_screen(x,y);
byte blue_under=Main_palette[color_under].B;
byte green_under=Main_palette[color_under].G;
byte red_under=Main_palette[color_under].R;
int factor=(Main_palette[color].R*76 +
Main_palette[color].G*151 +
Main_palette[color].B*28)/255;
return Best_color(
(Main_palette[Fore_color].R*factor + red_under*(255-factor))/255,
(Main_palette[Fore_color].G*factor + green_under*(255-factor))/255,
(Main_palette[Fore_color].B*factor + blue_under*(255-factor))/255);
}
void Check_timer(void)
{
if((SDL_GetTicks()/55)-Timer_delay>Timer_start) Timer_state=1;
@ -659,17 +679,6 @@ void Rescale(byte *src_buffer, short src_width, short src_height, byte *dst_buff
}
}
void Slider_timer(byte speed)
//Boucle d'attente pour faire bouger les scrollbars à une vitesse correcte
{
Uint32 end;
byte original_mouse_k = Mouse_K;
end = SDL_GetTicks() + speed*10;
do
{
if (!Get_input()) SDL_Delay(20);
} while (Mouse_K == original_mouse_k && SDL_GetTicks()<end);
}
void Scroll_picture(byte * main_src, byte * main_dest, short x_offset,short y_offset)
{
@ -732,13 +741,26 @@ void Zoom_a_line(byte* original_line, byte* zoomed_line,
// sysinfo not implemented
#elif defined(__AROS__) || defined(__amigaos4__) || defined(__MORPHOS__) || defined(__amigaos__)
#include <proto/exec.h>
#elif defined(__MINT__)
#include <mint/osbind.h>
#include <mint/sysbind.h>
#elif defined(__SKYOS__)
#include <skyos/sysinfo.h>
#else
#include <sys/sysinfo.h> // sysinfo() for free RAM
#endif
#if defined (__MINT__)
// atari have two kinds of memory
// standard and fast ram
void Atari_Memory_free(unsigned long *stRam,unsigned long *ttRam){
//TODO: return STRAM/TT-RAM
unsigned long mem=0;
*stRam=Mxalloc(-1L,0);
*ttRam = Mxalloc(-1L,1);
}
#else
// Indique quelle est la mémoire disponible
unsigned long Memory_free(void)
{
@ -778,6 +800,8 @@ unsigned long Memory_free(void)
return info.freeram*info.mem_unit;
#endif
}
#endif
// Arrondir un nombre réel à la valeur entière la plus proche

View File

@ -33,7 +33,7 @@
#define SWAP_PBYTES(a,b) { byte * c=a; a=b; b=c;}
void Copy_image_to_brush(short start_x,short start_y,short Brush_width,short Brush_height,word image_width);
void Remap_general_lowlevel(byte * conversion_table,byte * buffer,short width,short height,short buffer_width);
void Remap_general_lowlevel(byte * conversion_table,byte * in_buffer, byte *out_buffer,short width,short height,short buffer_width);
void Scroll_picture(byte * main_src, byte * main_dest, short x_offset,short y_offset);
void Wait_end_of_click(void);
void Set_color(byte color, byte red, byte green, byte blue);
@ -42,7 +42,6 @@ void Palette_256_to_64(T_Palette palette);
void Palette_64_to_256(T_Palette palette);
void Clear_current_image(byte color);
void Clear_current_image_with_stencil(byte color, byte * stencil);
void Slider_timer(byte speed);
dword Round_div(dword numerator,dword divisor);
word Count_used_colors(dword * usage);
word Count_used_colors_area(dword* usage, word start_x, word start_y, word width, word height);
@ -86,6 +85,7 @@ void Replace_colors_within_limits(byte * replace_table);
byte Effect_interpolated_colorize (word x,word y,byte color);
byte Effect_additive_colorize (word x,word y,byte color);
byte Effect_substractive_colorize(word x,word y,byte color);
byte Effect_alpha_colorize(word x,word y,byte color);
byte Effect_sieve(word x,word y);
///

View File

@ -2,6 +2,7 @@
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2009 Petter Lindquist
Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet
@ -368,7 +369,8 @@ void Load_PKM(T_IO_Context * context)
Compteur_de_donnees_packees=0;
Compteur_de_pixels=0;
Taille_pack=(file_size)-sizeof(T_PKM_Header)-header.Jump;
// Header size is 780
Taille_pack=(file_size)-780-header.Jump;
// Boucle de décompression:
while ( (Compteur_de_pixels<image_size) && (Compteur_de_donnees_packees<Taille_pack) && (!File_error) )
@ -637,7 +639,6 @@ void Save_PKM(T_IO_Context * context)
//////////////////////////////////// CEL ////////////////////////////////////
#pragma pack(1)
typedef struct
{
word Width; // width de l'image
@ -656,7 +657,6 @@ typedef struct
word Y_offset; // Offset en Y de l'image
byte Filler2[16]; // ???
} T_CEL_Header2;
#pragma pack()
// -- Tester si un fichier est au format CEL --------------------------------
@ -689,7 +689,7 @@ void Test_CEL(T_IO_Context * context)
// Vu que ce header n'a pas de signature, il va falloir tester la
// cohérence de la dimension de l'image avec celle du fichier.
size=file_size-sizeof(T_CEL_Header1);
size=file_size-4;
if ( (!size) || ( (((header1.Width+1)>>1)*header1.Height)!=size ) )
{
// Tentative de reconnaissance de la signature des nouveaux fichiers
@ -735,7 +735,7 @@ void Load_CEL(T_IO_Context * context)
short y_pos;
byte last_byte=0;
long file_size;
const long int header_size = (long int)(sizeof(header1.Width)+sizeof(header1.Height));
const long int header_size = 4;
File_error=0;
Get_full_filename(filename, context->File_name, context->File_directory);
@ -775,7 +775,7 @@ void Load_CEL(T_IO_Context * context)
// On réessaye avec le nouveau format
fseek(file,0,SEEK_SET);
if (Read_bytes(file,header2.Signature,sizeof(header2.Signature))
if (Read_bytes(file,header2.Signature,4)
&& Read_byte(file,&(header2.Kind))
&& Read_byte(file,&(header2.Nb_bits))
&& Read_word_le(file,&(header2.Filler1))
@ -783,7 +783,7 @@ void Load_CEL(T_IO_Context * context)
&& Read_word_le(file,&(header2.Height))
&& Read_word_le(file,&(header2.X_offset))
&& Read_word_le(file,&(header2.Y_offset))
&& Read_bytes(file,header2.Filler2,sizeof(header2.Filler2))
&& Read_bytes(file,header2.Filler2,16)
)
{
// Chargement d'un fichier CEL avec signature (nouveaux fichiers)
@ -942,7 +942,7 @@ void Save_CEL(T_IO_Context * context)
for (x_pos=0;x_pos<16;x_pos++) // Initialisation du filler 2 (?)
header2.Filler2[x_pos]=0;
if (Write_bytes(file,header2.Signature,sizeof(header2.Signature))
if (Write_bytes(file,header2.Signature,4)
&& Write_byte(file,header2.Kind)
&& Write_byte(file,header2.Nb_bits)
&& Write_word_le(file,header2.Filler1)
@ -950,7 +950,7 @@ void Save_CEL(T_IO_Context * context)
&& Write_word_le(file,header2.Height)
&& Write_word_le(file,header2.X_offset)
&& Write_word_le(file,header2.Y_offset)
&& Write_bytes(file,header2.Filler2,sizeof(header2.Filler2))
&& Write_bytes(file,header2.Filler2,14)
)
{
// Sauvegarde de l'image
@ -974,7 +974,6 @@ void Save_CEL(T_IO_Context * context)
//////////////////////////////////// KCF ////////////////////////////////////
#pragma pack(1)
typedef struct
{
struct
@ -986,7 +985,6 @@ typedef struct
} color[16];
} Palette[10];
} T_KCF_Header;
#pragma pack()
// -- Tester si un fichier est au format KCF --------------------------------
@ -994,7 +992,7 @@ void Test_KCF(T_IO_Context * context)
{
char filename[MAX_PATH_CHARACTERS];
FILE *file;
T_KCF_Header buffer;
T_KCF_Header header1;
T_CEL_Header2 header2;
int pal_index;
int color_index;
@ -1003,18 +1001,22 @@ void Test_KCF(T_IO_Context * context)
Get_full_filename(filename, context->File_name, context->File_directory);
if ((file=fopen(filename, "rb")))
{
if (File_length_file(file)==sizeof(T_KCF_Header))
if (File_length_file(file)==320)
{
Read_bytes(file,&buffer,sizeof(T_KCF_Header));
for (pal_index=0;pal_index<10 && !File_error;pal_index++)
for (color_index=0;color_index<16 && !File_error;color_index++)
if (!Read_byte(file,&header1.Palette[pal_index].color[color_index].Byte1) ||
!Read_byte(file,&header1.Palette[pal_index].color[color_index].Byte2))
File_error=1;
// On vérifie une propriété de la structure de palette:
for (pal_index=0;pal_index<10;pal_index++)
for (color_index=0;color_index<16;color_index++)
if ((buffer.Palette[pal_index].color[color_index].Byte2>>4)!=0)
if ((header1.Palette[pal_index].color[color_index].Byte2>>4)!=0)
File_error=1;
}
else
{
if (Read_bytes(file,header2.Signature,sizeof(header2.Signature))
if (Read_bytes(file,header2.Signature,4)
&& Read_byte(file,&(header2.Kind))
&& Read_byte(file,&(header2.Nb_bits))
&& Read_word_le(file,&(header2.Filler1))
@ -1022,7 +1024,7 @@ void Test_KCF(T_IO_Context * context)
&& Read_word_le(file,&(header2.Height))
&& Read_word_le(file,&(header2.X_offset))
&& Read_word_le(file,&(header2.Y_offset))
&& Read_bytes(file,header2.Filler2,sizeof(header2.Filler2))
&& Read_bytes(file,header2.Filler2,14)
)
{
if (memcmp(header2.Signature,"KiSS",4)==0)
@ -1049,7 +1051,7 @@ void Load_KCF(T_IO_Context * context)
{
char filename[MAX_PATH_CHARACTERS];
FILE *file;
T_KCF_Header buffer;
T_KCF_Header header1;
T_CEL_Header2 header2;
byte bytes[3];
int pal_index;
@ -1063,11 +1065,16 @@ void Load_KCF(T_IO_Context * context)
if ((file=fopen(filename, "rb")))
{
file_size=File_length_file(file);
if (file_size==sizeof(T_KCF_Header))
if (file_size==320)
{
// Fichier KCF à l'ancien format
for (pal_index=0;pal_index<10 && !File_error;pal_index++)
for (color_index=0;color_index<16 && !File_error;color_index++)
if (!Read_byte(file,&header1.Palette[pal_index].color[color_index].Byte1) ||
!Read_byte(file,&header1.Palette[pal_index].color[color_index].Byte2))
File_error=1;
if (Read_bytes(file,&buffer,sizeof(T_KCF_Header)))
if (!File_error)
{
// Pre_load(context, ?); // Pas possible... pas d'image...
@ -1079,9 +1086,9 @@ void Load_KCF(T_IO_Context * context)
for (color_index=0;color_index<16;color_index++)
{
index=16+(pal_index*16)+color_index;
context->Palette[index].R=((buffer.Palette[pal_index].color[color_index].Byte1 >> 4) << 4);
context->Palette[index].B=((buffer.Palette[pal_index].color[color_index].Byte1 & 15) << 4);
context->Palette[index].G=((buffer.Palette[pal_index].color[color_index].Byte2 & 15) << 4);
context->Palette[index].R=((header1.Palette[pal_index].color[color_index].Byte1 >> 4) << 4);
context->Palette[index].B=((header1.Palette[pal_index].color[color_index].Byte1 & 15) << 4);
context->Palette[index].G=((header1.Palette[pal_index].color[color_index].Byte2 & 15) << 4);
}
for (index=0;index<16;index++)
@ -1100,7 +1107,7 @@ void Load_KCF(T_IO_Context * context)
{
// Fichier KCF au nouveau format
if (Read_bytes(file,header2.Signature,sizeof(header2.Signature))
if (Read_bytes(file,header2.Signature,4)
&& Read_byte(file,&(header2.Kind))
&& Read_byte(file,&(header2.Nb_bits))
&& Read_word_le(file,&(header2.Filler1))
@ -1108,7 +1115,7 @@ void Load_KCF(T_IO_Context * context)
&& Read_word_le(file,&(header2.Height))
&& Read_word_le(file,&(header2.X_offset))
&& Read_word_le(file,&(header2.Y_offset))
&& Read_bytes(file,header2.Filler2,sizeof(header2.Filler2))
&& Read_bytes(file,header2.Filler2,14)
)
{
// Pre_load(context, ?); // Pas possible... pas d'image...
@ -1168,7 +1175,7 @@ void Save_KCF(T_IO_Context * context)
{
char filename[MAX_PATH_CHARACTERS];
FILE *file;
T_KCF_Header buffer;
T_KCF_Header header1;
T_CEL_Header2 header2;
byte bytes[3];
int pal_index;
@ -1196,12 +1203,16 @@ void Save_KCF(T_IO_Context * context)
for (color_index=0;color_index<16;color_index++)
{
index=16+(pal_index*16)+color_index;
buffer.Palette[pal_index].color[color_index].Byte1=((context->Palette[index].R>>4)<<4) | (context->Palette[index].B>>4);
buffer.Palette[pal_index].color[color_index].Byte2=context->Palette[index].G>>4;
header1.Palette[pal_index].color[color_index].Byte1=((context->Palette[index].R>>4)<<4) | (context->Palette[index].B>>4);
header1.Palette[pal_index].color[color_index].Byte2=context->Palette[index].G>>4;
}
if (! Write_bytes(file,&buffer,sizeof(T_KCF_Header)))
File_error=1;
// Write all
for (pal_index=0;pal_index<10 && !File_error;pal_index++)
for (color_index=0;color_index<16 && !File_error;color_index++)
if (!Write_byte(file,header1.Palette[pal_index].color[color_index].Byte1) ||
!Write_byte(file,header1.Palette[pal_index].color[color_index].Byte2))
File_error=1;
}
else
{
@ -1218,7 +1229,7 @@ void Save_KCF(T_IO_Context * context)
for (index=0;index<16;index++) // Initialisation du filler 2 (?)
header2.Filler2[index]=0;
if (!Write_bytes(file,header2.Signature,sizeof(header2.Signature))
if (!Write_bytes(file,header2.Signature,4)
|| !Write_byte(file,header2.Kind)
|| !Write_byte(file,header2.Nb_bits)
|| !Write_word_le(file,header2.Filler1)
@ -1226,7 +1237,7 @@ void Save_KCF(T_IO_Context * context)
|| !Write_word_le(file,header2.Height)
|| !Write_word_le(file,header2.X_offset)
|| !Write_word_le(file,header2.Y_offset)
|| !Write_bytes(file,header2.Filler2,sizeof(header2.Filler2))
|| !Write_bytes(file,header2.Filler2,14)
)
File_error=1;
@ -1322,17 +1333,29 @@ void PI1_decode_palette(byte * src,byte * palette)
// Low High
// VVVV RRRR | 0000 BBBB
// 0321 0321 | 0321
ip=0;
for (i=0;i<16;i++)
{
w=((word)src[(i*2)+1]<<8) | src[(i*2)+0];
// Traitement des couleurs rouge, verte et bleue:
palette[ip++]=(((w & 0x0007) << 1) | ((w & 0x0008) >> 3)) << 4;
palette[ip++]=(((w & 0x7000) >> 11) | ((w & 0x8000) >> 15)) << 4;
palette[ip++]=(((w & 0x0700) >> 7) | ((w & 0x0800) >> 11)) << 4;
}
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
w=(((word)src[(i*2)+1]<<8) | (src[(i*2)+0]));
// Traitement des couleurs rouge, verte et bleue:
palette[ip++]=(((w & 0x0007) << 1) | ((w & 0x0008) >> 3)) << 4;
palette[ip++]=(((w & 0x7000) >> 11) | ((w & 0x8000) >> 15)) << 4;
palette[ip++]=(((w & 0x0700) >> 7) | ((w & 0x0800) >> 11)) << 4;
#else
w=(((word)src[(i*2+1)])|(((word)src[(i*2)])<<8));
palette[ip++] = (((w & 0x0700)>>7) | ((w & 0x0800) >> 7))<<4 ;
palette[ip++]=(((w & 0x0070)>>3) | ((w & 0x0080) >> 3))<<4 ;
palette[ip++] = (((w & 0x0007)<<1) | ((w & 0x0008)))<<4 ;
#endif
}
}
//// CODAGE de la PALETTE ////
@ -1345,20 +1368,31 @@ void PI1_code_palette(byte * palette,byte * dest)
// Schéma d'un word =
//
// Low High
// Low High
// VVVV RRRR | 0000 BBBB
// 0321 0321 | 0321
ip=0;
for (i=0;i<16;i++)
{
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
// Traitement des couleurs rouge, verte et bleue:
w =(((word)(palette[ip]>>2) & 0x38) >> 3) | (((word)(palette[ip]>>2) & 0x04) << 1); ip++;
w|=(((word)(palette[ip]>>2) & 0x38) << 9) | (((word)(palette[ip]>>2) & 0x04) << 13); ip++;
w|=(((word)(palette[ip]>>2) & 0x38) << 5) | (((word)(palette[ip]>>2) & 0x04) << 9); ip++;
dest[(i*2)+0]=w & 0x00FF;
dest[(i*2)+1]=(w>>8);
#else
w=(((word)(palette[ip]<<3))&0x0700);ip++;
w|=(((word)(palette[ip]>>1))&0x0070);ip++;
w|=(((word)(palette[ip]>>5))&0x0007);ip++;
dest[(i*2)+1]=w & 0x00FF;
dest[(i*2)+0]=(w>>8);
#endif
}
}
@ -2472,13 +2506,13 @@ int Save_C64_window(byte *saveWhat, byte *loadAddr)
Print_in_window(13,18,"Data:",MC_Dark,MC_Light);
what=Window_set_dropdown_button(10,28,90,15,70,what_label[*saveWhat],1, 0, 1, LEFT_SIDE,0); // 3
Window_dropdown_clear_items(what);
for (i=0; i<sizeof(what_label)/sizeof(char *); i++)
for (i=0; i<sizeof(what_label)/sizeof(what_label[0]); i++)
Window_dropdown_add_item(what,i,what_label[i]);
Print_in_window(113,18,"Address:",MC_Dark,MC_Light);
addr=Window_set_dropdown_button(110,28,70,15,70,address_label[*loadAddr/32],1, 0, 1, LEFT_SIDE,0); // 4
Window_dropdown_clear_items(addr);
for (i=0; i<sizeof(address_label)/sizeof(char *); i++)
for (i=0; i<sizeof(address_label)/sizeof(address_label[0]); i++)
Window_dropdown_add_item(addr,i,address_label[i]);
Update_window_area(0,0,Window_width,Window_height);

View File

@ -336,12 +336,12 @@ fstype_to_string (int t)
#define BROKEN
#endif
#if defined MOUNTED_GETMNTENT1 || defined MOUNTED_GETMNTENT2
/* Return the device number from MOUNT_OPTIONS, if possible.
Otherwise return (dev_t) -1. */
static dev_t
dev_from_mount_options (BROKEN char const *mount_options)
{

View File

@ -2,6 +2,7 @@
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2010 Alexander Filyanov
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
@ -30,6 +31,8 @@
#include "op_c.h"
#include "errors.h"
int Convert_24b_bitmap_to_256_fast(T_Bitmap256 dest,T_Bitmap24B source,int width,int height,T_Components * palette);
/// Convert RGB to HSL.
/// Both input and output are in the 0..255 range to use in the palette screen
void RGB_to_HSL(int r,int g,int b,byte * hr,byte * sr,byte* lr)
@ -165,6 +168,16 @@ void HSL_to_RGB(byte h,byte s,byte l, byte* r, byte* g, byte* b)
*b = bf * (255);
}
///
/// Returns a value that is high when color is near white,
/// and low when it's darker. Used for sorting.
long Perceptual_lightness(T_Components *color)
{
return 26*color->R*26*color->R +
55*color->G*55*color->G +
19*color->B*19*color->B;
}
// Conversion table handlers
// The conversion table is built after a run of the median cut algorithm and is
// used to find the best color index for a given (RGB) color. GIMP avoids
@ -1342,6 +1355,10 @@ static const byte precision_24b[]=
// Give this one a 24b source, get back the 256c bitmap and its palette
int Convert_24b_bitmap_to_256(T_Bitmap256 dest,T_Bitmap24B source,int width,int height,T_Components * palette)
{
#if defined(__GP2X__) || defined(__gp2x__) || defined(__WIZ__) || defined(__CAANOO__)
return Convert_24b_bitmap_to_256_fast(dest, source, width, height, palette);
#else
T_Conversion_table * table; // table de conversion
int ip; // index de précision pour la conversion
@ -1363,7 +1380,36 @@ int Convert_24b_bitmap_to_256(T_Bitmap256 dest,T_Bitmap24B source,int width,int
}
else
return 1;
#endif
}
//Really small, fast and ugly converter(just for handhelds)
#include "global.h"
#include "limits.h"
#include "engine.h"
#include "windows.h"
extern void Set_palette_fake_24b(T_Palette palette);
/// Really small, fast and dirty convertor(just for handhelds)
int Convert_24b_bitmap_to_256_fast(T_Bitmap256 dest,T_Bitmap24B source,int width,int height,T_Components * palette)
{
int size;
Set_palette_fake_24b(palette);
size = width*height;
while(size--)
{
//Set palette color index to destination bitmap
*dest = ((source->R >> 5) << 5) |
((source->G >> 5) << 2) |
((source->B >> 6));
source++;
dest++;
}
return 0;
}

View File

@ -160,6 +160,7 @@ void CT_set(T_Conversion_table * t,int r,int g,int b,byte i);
void RGB_to_HSL(int r, int g,int b, byte* h, byte*s, byte* l);
void HSL_to_RGB(byte h, byte s, byte l, byte* r, byte* g, byte* b);
long Perceptual_lightness(T_Components *color);
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////// Méthodes de gestion des tables d'occurence //

View File

@ -36,6 +36,7 @@
#include "sdlscreen.h"
#include "brush.h"
#include "windows.h"
#include "input.h"
// PI is NOT part of math.h according to C standards...
#if defined(__GP2X__) || defined(__VBCC__)
@ -53,11 +54,12 @@ void Start_operation_stack(word new_operation)
// On mémorise l'opération précédente si on démarre une interruption
switch(new_operation)
{
case OPERATION_MAGNIFY :
case OPERATION_COLORPICK :
case OPERATION_GRAB_BRUSH :
case OPERATION_POLYBRUSH :
case OPERATION_STRETCH_BRUSH :
case OPERATION_MAGNIFY:
case OPERATION_COLORPICK:
case OPERATION_RMB_COLORPICK:
case OPERATION_GRAB_BRUSH:
case OPERATION_POLYBRUSH:
case OPERATION_STRETCH_BRUSH:
case OPERATION_ROTATE_BRUSH:
Operation_before_interrupt=Current_operation;
// On passe à l'operation demandée
@ -226,6 +228,9 @@ void Freehand_mode1_2_0(void)
//
// Souris effacée: Oui
{
if (Rightclick_colorpick(0))
return;
Init_start_operation();
Backup();
Shade_table=Shade_table_right;
@ -322,6 +327,9 @@ void Freehand_mode2_2_0(void)
//
// Souris effacée: Oui
{
if (Rightclick_colorpick(0))
return;
Init_start_operation();
Backup();
Shade_table=Shade_table_right;
@ -390,6 +398,9 @@ void Freehand_Mode3_2_0(void)
//
// Souris effacée: Oui
{
if (Rightclick_colorpick(0))
return;
Init_start_operation();
Backup();
Shade_table=Shade_table_right;
@ -422,6 +433,9 @@ void Line_12_0(void)
// Début du tracé d'une ligne (premier clic)
{
if (Rightclick_colorpick(0))
return;
Init_start_operation();
Backup();
Paintbrush_shape_before_operation=Paintbrush_shape;
@ -480,9 +494,7 @@ void Line_12_5(void)
// On corrige les coordonnées de la ligne si la touche shift est appuyée...
if(SDL_GetModState() & KMOD_SHIFT)
{
Clamp_coordinates_regular_angle(start_x,start_y,&cursor_x,&cursor_y);
}
// On vient de bouger
if ((cursor_x!=end_x) || (cursor_y!=end_y))
@ -557,11 +569,11 @@ void Line_0_5(void)
}
/////////////////////////////////////////////////////////// OPERATION_K_LIGNE
/////////////////////////////////////////////////////////// OPERATION_K_LINE
void K_line_12_0(void)
// Opération : OPERATION_K_LIGNE
// Opération : OPERATION_K_LINE
// Click Souris: 1 ou 2
// Taille_Pile : 0
//
@ -569,6 +581,9 @@ void K_line_12_0(void)
{
byte color;
if (Rightclick_colorpick(0))
return;
Init_start_operation();
Backup();
Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right;
@ -594,7 +609,7 @@ void K_line_12_0(void)
void K_line_12_6(void)
// Opération : OPERATION_K_LIGNE
// Opération : OPERATION_K_LINE
// Click Souris: 1 ou 2 | 0
// Taille_Pile : 6 | 7
//
@ -634,7 +649,7 @@ void K_line_12_6(void)
void K_line_0_6(void)
// Opération : OPERATION_K_LIGNE
// Opération : OPERATION_K_LINE
// Click Souris: 0
// Taille_Pile : 6
//
@ -684,7 +699,7 @@ void K_line_0_6(void)
void K_line_12_7(void)
// Opération : OPERATION_K_LIGNE
// Opération : OPERATION_K_LINE
// Click Souris: 1 ou 2
// Taille_Pile : 7
//
@ -745,6 +760,9 @@ void Rectangle_12_0(void)
//
// Souris effacée: Oui
{
if (Rightclick_colorpick(0))
return;
Init_start_operation();
if ((Config.Coords_rel) && (Menu_is_visible))
@ -916,6 +934,9 @@ void Circle_12_0(void)
//
// Souris effacée: Oui
{
if (Rightclick_colorpick(0))
return;
Init_start_operation();
Backup();
@ -1090,6 +1111,9 @@ void Ellipse_12_0(void)
//
// Souris effacée: Oui
{
if (Rightclick_colorpick(0))
return;
Init_start_operation();
Backup();
@ -1284,9 +1308,12 @@ void Fill_2_0(void)
// Click Souris: 2
// Taille_Pile : 0
//
// Souris effacée: Oui
// Souris effacée: Non
//
{
if (Rightclick_colorpick(1))
return;
Hide_cursor();
// Pas besoin d'initialiser le début d'opération car le Smear n'affecte pas
// le Fill, et on se fout de savoir si on est dans la partie gauche ou
@ -1309,7 +1336,7 @@ void Replace_1_0(void)
// Click Souris: 1
// Taille_Pile : 0
//
// Souris effacée: Oui
// Souris effacée: Non
//
{
Hide_cursor();
@ -1331,9 +1358,12 @@ void Replace_2_0(void)
// Click Souris: 2
// Taille_Pile : 0
//
// Souris effacée: Oui
// Souris effacée: Non
//
{
if (Rightclick_colorpick(1))
return;
Hide_cursor();
// Pas besoin d'initialiser le début d'opération car le Smear n'affecte pas
// le Replace, et on se fout de savoir si on est dans la partie gauche ou
@ -1433,6 +1463,9 @@ void Curve_34_points_2_0(void)
// Souris effacée: Oui
//
{
if (Rightclick_colorpick(0))
return;
Init_start_operation();
Backup();
Shade_table=Shade_table_right;
@ -1711,17 +1744,17 @@ void Compute_3_point_curve(short x1, short y1, short x4, short y4,
float cx,cy; // Centre de (x1,y1) et (x4,y4)
float bx,by; // Intersect. des dtes ((x1,y1),(x2,y2)) et ((x3,y3),(x4,y4))
cx=(float)(x1+x4)/2.0; // P1*--_ Légende:
cy=(float)(y1+y4)/2.0; // · \·· P2 -_\|/ : courbe
// · \ ·*· * : point important
bx=cx+((8.0/3.0)*(Paintbrush_X-cx));// · | ·· · : pointillÚ
cx=(float)(x1+x4)/2.0; // P1*--_ Legend:
cy=(float)(y1+y4)/2.0; // · \·· P2 -_\|/ : curve
// · \ ·*· * : important point
bx=cx+((8.0/3.0)*(Paintbrush_X-cx));// · | ·· · : dotted line
by=cy+((8.0/3.0)*(Paintbrush_Y-cy));// · |P ·· B
// C *·····*·········* P=Pos. du pinceau
*x2=Round((bx+x1)/2.0); // · | ·· C=milieu de [P1,P4]
*y2=Round((by+y1)/2.0); // · | ·· B=point tel que
// · / ·*· C->B=(8/3) * C->P
*x3=Round((bx+x4)/2.0); // · _/·· P3 P2=milieu de [P1,B]
*y3=Round((by+y4)/2.0); // P4*-- P3=milieu de [P4,B]
// C *·····*·········* P=Pencil position
*x2=Round((bx+x1)/2.0); // · | ·· C=middle of [P1,P4]
*y2=Round((by+y1)/2.0); // · | ·· B=point computed as
// · / ·*· C->B=(8/3) * C->P
*x3=Round((bx+x4)/2.0); // · _/·· P3 P2=middle of [P1,B]
*y3=Round((by+y4)/2.0); // P4*-- P3=middle of [P4,B]
}
@ -1745,8 +1778,11 @@ void Curve_3_points_0_5(void)
Compute_3_point_curve(x1,y1,x4,y4,&x2,&y2,&x3,&y3);
Hide_line_preview(x1,y1,x4,y4);
Draw_curve_preview(x1,y1,x2,y2,x3,y3,x4,y4,color);
if (!Config.Stylus_mode)
{
Hide_line_preview(x1,y1,x4,y4);
Draw_curve_preview(x1,y1,x2,y2,x3,y3,x4,y4,color);
}
if ( (Config.Coords_rel) && (Menu_is_visible) )
{
@ -1765,17 +1801,19 @@ void Curve_3_points_0_5(void)
Operation_push(y4);
Operation_push(Paintbrush_X);
Operation_push(Paintbrush_Y);
if (Config.Stylus_mode)
{
Display_cursor();
while(!Mouse_K)
Get_input(20);
Hide_cursor();
Hide_line_preview(x1,y1,x4,y4);
}
}
void Curve_3_points_0_11(void)
//
// Opération : OPERATION_3_POINTS_CURVE
// Click Souris: 0
// Taille_Pile : 11
//
// Souris effacée: Non
//
void Curve_drag(void)
{
short x1,y1,x2,y2,x3,y3,x4,y4;
short old_x,old_y;
@ -1817,16 +1855,7 @@ void Curve_3_points_0_11(void)
Operation_push(Paintbrush_X);
Operation_push(Paintbrush_Y);
}
void Curve_3_points_12_11(void)
//
// Opération : OPERATION_3_POINTS_CURVE
// Click Souris: 1 ou 2
// Taille_Pile : 11
//
// Souris effacée: Oui
//
void Curve_finalize(void)
{
short x1,y1,x2,y2,x3,y3,x4,y4;
short old_x,old_y;
@ -1857,6 +1886,37 @@ void Curve_3_points_12_11(void)
Wait_end_of_click();
}
void Curve_3_points_0_11(void)
//
// Opération : OPERATION_3_POINTS_CURVE
// Click Souris: 0
// Taille_Pile : 11
//
// Souris effacée: Non
//
{
if (!Config.Stylus_mode)
Curve_drag();
else
Curve_finalize();
}
void Curve_3_points_12_11(void)
//
// Opération : OPERATION_3_POINTS_CURVE
// Click Souris: 1 ou 2
// Taille_Pile : 11
//
// Souris effacée: Oui
//
{
if (!Config.Stylus_mode)
Curve_finalize();
else
Curve_drag();
}
///////////////////////////////////////////////////////////// OPERATION_AIRBRUSH
@ -1873,8 +1933,11 @@ void Airbrush_1_0(void)
Backup();
Shade_table=Shade_table_left;
Airbrush_next_time = SDL_GetTicks()+Airbrush_delay*10;
Airbrush(LEFT_SIDE);
if (SDL_GetTicks()>Airbrush_next_time)
{
Airbrush(LEFT_SIDE);
Airbrush_next_time = SDL_GetTicks()+Airbrush_delay*10;
}
Operation_push(Paintbrush_X);
Operation_push(Paintbrush_Y);
@ -1889,11 +1952,17 @@ void Airbrush_2_0(void)
// Souris effacée: Non
//
{
if (Rightclick_colorpick(1))
return;
Init_start_operation();
Backup();
Shade_table=Shade_table_right;
Airbrush_next_time = SDL_GetTicks()+Airbrush_delay*10;
Airbrush(RIGHT_SIDE);
if (SDL_GetTicks()>Airbrush_next_time)
{
Airbrush(RIGHT_SIDE);
Airbrush_next_time = SDL_GetTicks()+Airbrush_delay*10;
}
Operation_push(Paintbrush_X);
Operation_push(Paintbrush_Y);
@ -1909,6 +1978,7 @@ void Airbrush_12_2(void)
//
{
short old_x,old_y;
Uint32 now;
Operation_pop(&old_y);
Operation_pop(&old_x);
@ -1920,9 +1990,13 @@ void Airbrush_12_2(void)
Display_cursor();
}
if (SDL_GetTicks()>Airbrush_next_time)
now=SDL_GetTicks();
if (now>Airbrush_next_time)
{
Airbrush_next_time+=Airbrush_delay*10;
//Airbrush_next_time+=Airbrush_delay*10;
// Time is now reset, because the += was death spiral
// if drawing took more time than the frequency.
Airbrush_next_time=now+Airbrush_delay*10;
Airbrush(Mouse_K_unique);
}
@ -1956,6 +2030,9 @@ void Polygon_12_0(void)
{
byte color;
if (Rightclick_colorpick(0))
return;
Init_start_operation();
Backup();
Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right;
@ -2057,6 +2134,9 @@ void Polyfill_12_0(void)
{
byte color;
if (Rightclick_colorpick(0))
return;
Init_start_operation();
Backup();
Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right;
@ -2255,6 +2335,9 @@ void Polyform_12_0(void)
{
short color;
if (Rightclick_colorpick(0))
return;
Init_start_operation();
Backup();
Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right;
@ -2413,6 +2496,9 @@ void Filled_polyform_12_0(void)
{
short color;
if (Rightclick_colorpick(0))
return;
Init_start_operation();
// Cette opération étant également utilisée pour le lasso, on ne fait pas de
@ -2825,6 +2911,7 @@ void Grad_circle_12_0(void)
Init_start_operation();
Backup();
Load_gradient_data(Current_gradient);
Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right;
color=(Mouse_K==LEFT_SIDE)?Fore_color:Back_color;
@ -3082,6 +3169,8 @@ void Grad_ellipse_12_0(void)
Init_start_operation();
Backup();
Load_gradient_data(Current_gradient);
Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right;
color=(Mouse_K==LEFT_SIDE)?Fore_color:Back_color;
@ -3306,6 +3395,7 @@ void Grad_rectangle_12_0(void)
{
Init_start_operation();
Backup();
Load_gradient_data(Current_gradient);
if ((Config.Coords_rel) && (Menu_is_visible))
Print_in_menu("\035: 1 \022: 1",0);
@ -3712,6 +3802,9 @@ void Centered_lines_12_0(void)
//
// Souris effacée: Oui
{
if (Rightclick_colorpick(0))
return;
Init_start_operation();
Backup();
Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right;

View File

@ -225,3 +225,8 @@ void Centered_lines_0_3(void);
void Centered_lines_12_7(void);
void Centered_lines_0_7(void);
/////////////////////////////////////////////////// OPERATION_RMB_COLORPICK
byte Rightclick_colorpick(byte cursor_visible);
void Rightclick_colorpick_2_1(void);
void Rightclick_colorpick_0_1(void);

View File

@ -75,6 +75,7 @@ T_Page * New_page(byte nb_layers)
page->Filename[0]='\0';
page->File_format=DEFAULT_FILEFORMAT;
page->Nb_layers=nb_layers;
page->Gradients=NULL;
page->Transparent_color=0; // Default transparent color
page->Background_transparent=0;
page->Next = page->Prev = NULL;
@ -141,6 +142,24 @@ byte * Dup_layer(byte * layer)
// ==============================================================
/// Adds a shared reference to the gradient data of another page. Pass NULL for new.
T_Gradient_array *Dup_gradient(T_Page * page)
{
// new
if (page==NULL || page->Gradients==NULL)
{
T_Gradient_array *array;
array=(T_Gradient_array *)calloc(1, sizeof(T_Gradient_array));
if (!array)
return NULL;
array->Used=1;
return array;
}
// shared
page->Gradients->Used++;
return page->Gradients;
}
void Download_infos_page_main(T_Page * page)
// Affiche la page à l'écran
{
@ -418,6 +437,16 @@ void Clear_page(T_Page * page)
Free_layer(page, i);
page->Image[i]=NULL;
}
// Free_gradient() : This data is reference-counted
if (page->Gradients)
{
page->Gradients->Used--;
if (page->Gradients->Used==0)
free(page->Gradients);
page->Gradients=NULL;
}
page->Width=0;
page->Height=0;
// On ne se préoccupe pas de ce que deviens le reste des infos de l'image.
@ -426,6 +455,7 @@ void Clear_page(T_Page * page)
void Copy_S_page(T_Page * dest,T_Page * source)
{
*dest=*source;
dest->Gradients=NULL;
}
@ -460,6 +490,10 @@ int Allocate_list_of_pages(T_List_of_pages * list)
list->List_size=1;
page->Gradients=Dup_gradient(NULL);
if (!page->Gradients)
return 0;
return 1; // Succès
}
@ -799,19 +833,10 @@ void Set_number_of_backups(int nb_backups)
// (nb_backups = Nombre de backups, sans compter les pages courantes)
}
int Backup_with_new_dimensions(int upload,byte layers,int width,int height)
int Backup_new_image(byte layers,int width,int height)
{
// Retourne 1 si une nouvelle page est disponible (alors pleine de 0) et
// 0 sinon.
T_Page * new_page;
int return_code=0;
int i;
if (upload)
// On remet à jour l'état des infos de la page courante (pour pouvoir les
// retrouver plus tard)
Upload_infos_page_main(Main_backups->Pages);
// Retourne 1 si une nouvelle page est disponible et 0 sinon
T_Page * new_page;
// On crée un descripteur pour la nouvelle page courante
new_page=New_page(layers);
@ -820,36 +845,161 @@ int Backup_with_new_dimensions(int upload,byte layers,int width,int height)
Error(0);
return 0;
}
Upload_infos_page_main(new_page);
new_page->Width=width;
new_page->Height=height;
strcpy(new_page->Filename, Main_backups->Pages->Filename);
strcpy(new_page->File_directory, Main_backups->Pages->File_directory);
if (Create_new_page(new_page,Main_backups,0xFFFFFFFF))
new_page->Transparent_color=0;
new_page->Gradients=Dup_gradient(NULL);
if (!Create_new_page(new_page,Main_backups,0xFFFFFFFF))
{
for (i=0; i<layers;i++)
{
memset(Main_backups->Pages->Image[i], Main_backups->Pages->Transparent_color, width*height);
}
Update_buffers(width, height);
Download_infos_page_main(Main_backups->Pages);
// Same code as in End_of_modification():
#ifndef NOLAYERS
memcpy(Main_visible_image_backup.Image,
Main_visible_image.Image,
Main_image_width*Main_image_height);
#else
Update_screen_targets();
#endif
Update_FX_feedback(Config.FX_Feedback);
// --
return_code=1;
Error(0);
return 0;
}
return return_code;
Update_buffers(width, height);
Download_infos_page_main(Main_backups->Pages);
return 1;
}
int Backup_with_new_dimensions(int width,int height)
{
// Retourne 1 si une nouvelle page est disponible (alors pleine de 0) et
// 0 sinon.
T_Page * new_page;
int i;
// On crée un descripteur pour la nouvelle page courante
new_page=New_page(Main_backups->Pages->Nb_layers);
if (!new_page)
{
Error(0);
return 0;
}
new_page->Width=width;
new_page->Height=height;
new_page->Transparent_color=0;
if (!Create_new_page(new_page,Main_backups,0xFFFFFFFF))
{
Error(0);
return 0;
}
// Copy data from previous history step
memcpy(Main_backups->Pages->Palette,Main_backups->Pages->Next->Palette,sizeof(T_Palette));
strcpy(Main_backups->Pages->Comment,Main_backups->Pages->Next->Comment);
Main_backups->Pages->File_format=Main_backups->Pages->Next->File_format;
strcpy(Main_backups->Pages->Filename, Main_backups->Pages->Next->Filename);
strcpy(Main_backups->Pages->File_directory, Main_backups->Pages->Next->File_directory);
Main_backups->Pages->Gradients=Dup_gradient(Main_backups->Pages->Next);
Main_backups->Pages->Background_transparent=Main_backups->Pages->Next->Background_transparent;
Main_backups->Pages->Transparent_color=Main_backups->Pages->Next->Transparent_color;
// Fill with transparent color
for (i=0; i<Main_backups->Pages->Nb_layers;i++)
{
memset(Main_backups->Pages->Image[i], Main_backups->Pages->Transparent_color, width*height);
}
Update_buffers(width, height);
Download_infos_page_main(Main_backups->Pages);
// Same code as in End_of_modification(),
// Without saving a safety backup:
#ifndef NOLAYERS
memcpy(Main_visible_image_backup.Image,
Main_visible_image.Image,
Main_image_width*Main_image_height);
#else
Update_screen_targets();
#endif
Update_FX_feedback(Config.FX_Feedback);
// --
return 1;
}
///
/// Resizes a backup step in-place (doesn't add a Undo/Redo step).
/// Should only be called after an actual backup, because it loses the current.
/// pixels. This function is meant to be used from within Lua scripts.
int Backup_in_place(int width,int height)
{
// Retourne 1 si une nouvelle page est disponible (alors pleine de 0) et
// 0 sinon.
int i;
byte ** new_layer;
// Perform all allocations first
new_layer=calloc(Main_backups->Pages->Nb_layers,1);
if (!new_layer)
return 0;
for (i=0; i<Main_backups->Pages->Nb_layers; i++)
{
new_layer[i]=New_layer(height*width);
if (!new_layer[i])
{
// Allocation error
for (; i>0; i--)
free(new_layer[i]);
free(new_layer);
return 0;
}
}
// Now ok to proceed
for (i=0; i<Main_backups->Pages->Nb_layers; i++)
{
// Replace layers
Free_layer(Main_backups->Pages,i);
Main_backups->Pages->Image[i]=new_layer[i];
// Fill with transparency
memset(Main_backups->Pages->Image[i], Main_backups->Pages->Transparent_color, width*height);
}
Main_backups->Pages->Width=width;
Main_backups->Pages->Height=height;
Download_infos_page_main(Main_backups->Pages);
// The following is part of Update_buffers()
// (without changing the backup buffer)
#ifndef NOLAYERS
// At least one dimension is different
if (Main_visible_image.Width*Main_visible_image.Height != width*height)
{
// Current image
free(Main_visible_image.Image);
Main_visible_image.Image = (byte *)malloc(width * height);
if (Main_visible_image.Image == NULL)
return 0;
}
Main_visible_image.Width = width;
Main_visible_image.Height = height;
if (Main_visible_image_depth_buffer.Width*Main_visible_image_depth_buffer.Height != width*height)
{
// Depth buffer
free(Main_visible_image_depth_buffer.Image);
Main_visible_image_depth_buffer.Image = (byte *)malloc(width * height);
if (Main_visible_image_depth_buffer.Image == NULL)
return 0;
}
Main_visible_image_depth_buffer.Width = width;
Main_visible_image_depth_buffer.Height = height;
#endif
Update_screen_targets();
return 1;
}
int Backup_and_resize_the_spare(int width,int height)
@ -872,6 +1022,7 @@ int Backup_and_resize_the_spare(int width,int height)
// Fill it with a copy of the latest history
Copy_S_page(new_page,Spare_backups->Pages);
new_page->Gradients=Dup_gradient(Spare_backups->Pages);
new_page->Width=width;
new_page->Height=height;
@ -927,6 +1078,7 @@ void Backup_layers(dword layer_mask)
// Fill it with a copy of the latest history
Copy_S_page(new_page,Main_backups->Pages);
new_page->Gradients=Dup_gradient(Main_backups->Pages);
Create_new_page(new_page,Main_backups,layer_mask);
Download_infos_page_main(new_page);
@ -963,6 +1115,7 @@ void Backup_the_spare(dword layer_mask)
// Fill it with a copy of the latest history
Copy_S_page(new_page,Spare_backups->Pages);
new_page->Gradients=Dup_gradient(Spare_backups->Pages);
Create_new_page(new_page,Spare_backups,layer_mask);
// Copy the actual pixels from the backup to the latest page
@ -1099,6 +1252,11 @@ void End_of_modification(void)
//Update_buffers(Main_image_width, Main_image_height);
#ifndef NOLAYERS
// Backup buffer can have "wrong" size if a Lua script
// performs a resize.
Update_buffers(Main_image_width, Main_image_height);
//
memcpy(Main_visible_image_backup.Image,
Main_visible_image.Image,
Main_image_width*Main_image_height);

View File

@ -2,6 +2,7 @@
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
@ -39,13 +40,14 @@ extern byte * FX_feedback_screen;
/////////////////////////// BACKUP ///////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
#ifndef NOLAYERS
/// The pixels of visible layers, flattened copy.
extern T_Bitmap Main_visible_image;
/// The pixels of visible layers, flattened copy, used for no-feedback effects.
extern T_Bitmap Main_visible_image_backup;
/// The index of visible pixels from ::Visible image. Points to the right layer.
extern T_Bitmap Main_visible_image_depth_buffer;
#endif
/// The pixels of visible layers for the spare page, flattened copy.
extern T_Bitmap Spare_visible_image;
@ -93,7 +95,13 @@ void Free_page_of_a_list(T_List_of_pages * list);
int Init_all_backup_lists(int width,int height);
void Set_number_of_backups(int nb_backups);
int Backup_with_new_dimensions(int upload,byte layers,int width,int height);
int Backup_new_image(byte layers,int width,int height);
int Backup_with_new_dimensions(int width,int height);
///
/// Resizes a backup step in-place (doesn't add a Undo/Redo step).
/// Should only be called after an actual backup, because it loses the current.
/// pixels. This function is meant to be used from within Lua scripts.
int Backup_in_place(int width,int height);
/// Backup the spare image, the one you don't see.
void Backup_the_spare(dword layer_mask);
int Backup_and_resize_the_spare(int width,int height);

File diff suppressed because it is too large Load Diff

View File

@ -31,6 +31,8 @@ void Button_Secondary_palette(void);
/// Choose the number of graduations for RGB components, from 2 to 256.
void Set_palette_RGB_scale(int);
int Get_palette_RGB_scale(void);
///
/// Scale a component (R, G or B) according to the current RGB graduations.
/// Returns the resulting value, in the [0-255] range.
@ -42,3 +44,17 @@ byte Round_palette_component(byte comp);
@param not_picture 0 if the caller is the palette screen, 1 if it's a preview in the file selector.
*/
void Set_nice_menu_colors(dword * color_usage,int not_picture);
/// Put some colors in the clipboard.
/// @param nb_colors Number of colors to push
/// @param colors First color of the input array
void Set_clipboard_colors(int nb_colors, T_Components *colors);
/// Get some RGB colors from clipboard.
/// @param palette Target palette
/// @param start_color Index of first color to replace
/// @return Number of colors retrieved (0-256)
int Get_clipboard_colors(T_Palette palette, byte start_color);
/// Get the favorite color to use for GUI's black,dark,light or white.
const T_Components * Favorite_GUI_color(byte color_index);

View File

@ -2,6 +2,7 @@
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Peter Gordon
Copyright 2008 Yves Rizoud
Copyright 2007 Adrien Destugues
@ -32,6 +33,7 @@
#include "global.h"
#include "misc.h"
#include "readini.h"
#include "setup.h"
void Load_INI_clear_string(char * str, byte keep_comments)
{
@ -432,6 +434,13 @@ int Load_INI(T_Config * conf)
char value_label[1024];
Line_number_in_INI_file=0;
#if defined(__WIZ__) || defined(__CAANOO__)
conf->Stylus_mode = 1;
#else
conf->Stylus_mode = 0;
#endif
// On alloue les zones de mémoire:
buffer=(char *)malloc(1024);
@ -439,14 +448,14 @@ int Load_INI(T_Config * conf)
// On calcule le nom du fichier qu'on manipule:
strcpy(filename,Config_directory);
strcat(filename,"gfx2.ini");
strcat(filename,INI_FILENAME);
file=fopen(filename,"r");
if (file==0)
{
// Si le fichier ini est absent on le relit depuis gfx2def.ini
strcpy(filename,Data_directory);
strcat(filename,"gfx2def.ini");
strcat(filename,INIDEF_FILENAME);
file=fopen(filename,"r");
if (file == 0)
{
@ -894,6 +903,39 @@ int Load_INI(T_Config * conf)
Menu_bars[index].Visible = (values[0] & (1<<index)) ? 1 : 0;
}
}
conf->Right_click_colorpick=0;
// Optional, right mouse button to pick colors (>=2.3)
if (!Load_INI_get_values (file,buffer,"Right_click_colorpick",1,values))
{
conf->Right_click_colorpick=(values[0]!=0);
}
conf->Sync_views=1;
// Optional, synced view of main and spare (>=2.3)
if (!Load_INI_get_values (file,buffer,"Sync_views",1,values))
{
conf->Sync_views=(values[0]!=0);
}
conf->Swap_buttons=0;
// Optional, key for swap buttons (>=2.3)
if (!Load_INI_get_values (file,buffer,"Swap_buttons",1,values))
{
switch(values[0])
{
case 1:
conf->Swap_buttons=MOD_CTRL;
break;
case 2:
conf->Swap_buttons=MOD_ALT;
break;
}
}
// Insert new values here
fclose(file);

View File

@ -40,6 +40,13 @@
#include "windows.h"
#include "input.h"
// Virtual keyboard is mandatory on these platforms:
#if defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__)
#ifndef VIRT_KEY
#define VIRT_KEY 1
#endif
#endif
#define TEXT_COLOR MC_Black
#define BACKGROUND_COLOR MC_Light
#define CURSOR_COLOR MC_Black
@ -98,8 +105,41 @@ int Valid_character(int c)
void Display_whole_string(word x_pos,word y_pos,char * str,byte position)
{
Print_in_window(x_pos,y_pos,str,TEXT_COLOR,BACKGROUND_COLOR);
Print_char_in_window(x_pos+(position<<3),y_pos,str[position],CURSOR_COLOR,CURSOR_BACKGROUND_COLOR);
char cursor[2];
Print_general(x_pos,y_pos,str,TEXT_COLOR,BACKGROUND_COLOR);
cursor[0]=str[position] ? str[position] : ' ';
cursor[1]='\0';
Print_general(x_pos+(position<<3)*Menu_factor_X,y_pos,cursor,CURSOR_COLOR,CURSOR_BACKGROUND_COLOR);
}
void Init_virtual_keyboard(word y_pos, word keyboard_width, word keyboard_height)
{
int h_pos;
int v_pos;
int parent_window_x=Window_pos_X+2;
h_pos= Window_pos_X+(keyboard_width-Window_width)*Menu_factor_X/-2;
if (h_pos<0)
h_pos=0;
else if (h_pos+keyboard_width*Menu_factor_X>Screen_width)
h_pos=Screen_width-keyboard_width*Menu_factor_X;
v_pos=Window_pos_Y+(y_pos+9)*Menu_factor_Y;
if (v_pos+(keyboard_height*Menu_factor_Y)>Screen_height)
v_pos=Window_pos_Y+(y_pos-keyboard_height-4)*Menu_factor_Y;
Hide_cursor();
Open_popup(h_pos,v_pos,keyboard_width,keyboard_height);
Window_rectangle(1,0,Window_width-1, Window_height-1, MC_Light);
Window_rectangle(0,0,1,Window_height-2, MC_White);
// white border on top left angle, when it exceeds border.
if (parent_window_x>Window_pos_X)
Window_rectangle(0,0,(parent_window_x-Window_pos_X)/Menu_factor_X, 1, MC_White);
Window_rectangle(2,Window_height-2,Window_width-2, 2, MC_Black);
if(keyboard_width<320)
{
Window_rectangle(Window_width-2,2,2,Window_height-2, MC_Black);
}
}
/****************************************************************************
@ -143,28 +183,156 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz
byte size;
word input_key=0;
byte is_authorized;
word window_x=Window_pos_X;
word window_y=Window_pos_Y;
byte offset=0; // index du premier caractère affiché
#ifdef VIRT_KEY
// Virtual keyboard
byte use_virtual_keyboard=0;
static byte caps_lock=0;
word keymapping[] =
{
SDLK_CLEAR,SDLK_BACKSPACE,SDLK_RETURN,KEY_ESC,
'0','1','2','3','4','5','6','7','8','9','.',',',
'Q','W','E','R','T','Y','U','I','O','P',
'A','S','D','F','G','H','J','K','L',
SDLK_CAPSLOCK,'Z','X','C','V','B','N','M',' ',
'-','+','*','/','|','\\',
'(',')','{','}','[',']',
'_','=','<','>','%','@',
':',';','`','\'','"','~',
'!','?','^','&','#','$'
};
#endif
// Si on a commencé à editer par un clic-droit, on vide la chaine.
if (Mouse_K==RIGHT_SIDE)
str[0]='\0';
else if (input_type==1 && str[0]!='\0')
else if (input_type==INPUT_TYPE_INTEGER && str[0]!='\0')
snprintf(str,10,"%d",atoi(str)); // On tasse la chaine à gauche
else if (input_type==3)
else if (input_type==INPUT_TYPE_DECIMAL)
{
// Nothing. The caller should have used Sprint_double, with min_positions
// at zero, so there's no spaces on the left and no useless 0s on the right.
}
else if (input_type==INPUT_TYPE_HEXA)
{
// Nothing. The caller should have initialized a valid hexa number.
}
// Virtual keyboards
#ifdef VIRT_KEY
if (input_type == INPUT_TYPE_STRING || input_type == INPUT_TYPE_FILENAME )
{
int x,y;
Wait_end_of_click();
Init_virtual_keyboard(y_pos, 320, 87);
use_virtual_keyboard=1;
// The order is important, see the array
Window_set_normal_button( 7,67,43,15,"Clr", 0,1,KEY_NONE);
Window_set_normal_button( 51,67,43,15,"Del", 0,1,KEY_NONE);
Window_set_normal_button( 95,67,43,15,"OK", 0,1,KEY_NONE);
Window_set_normal_button(139,67,43,15,"Esc", 0,1,KEY_NONE);
Window_display_frame_in(5,65,179,19);
Window_set_normal_button(193,63,17,19,"0", 0,1,KEY_NONE);
Window_set_normal_button(193,43,17,19,"1", 0,1,KEY_NONE);
Window_set_normal_button(211,43,17,19,"2", 0,1,KEY_NONE);
Window_set_normal_button(229,43,17,19,"3", 0,1,KEY_NONE);
Window_set_normal_button(193,23,17,19,"4", 0,1,KEY_NONE);
Window_set_normal_button(211,23,17,19,"5", 0,1,KEY_NONE);
Window_set_normal_button(229,23,17,19,"6", 0,1,KEY_NONE);
Window_set_normal_button(193, 3,17,19,"7", 0,1,KEY_NONE);
Window_set_normal_button(211, 3,17,19,"8", 0,1,KEY_NONE);
Window_set_normal_button(229, 3,17,19,"9", 0,1,KEY_NONE);
Window_set_normal_button(211,63,17,19,".", 0,1,KEY_NONE);
Window_set_normal_button(229,63,17,19,",", 0,1,KEY_NONE);
Window_set_normal_button( 3, 3,18,19,"Q", 0,1,KEY_NONE);
Window_set_normal_button( 22, 3,18,19,"W", 0,1,KEY_NONE);
Window_set_normal_button( 41, 3,18,19,"E", 0,1,KEY_NONE);
Window_set_normal_button( 60, 3,18,19,"R", 0,1,KEY_NONE);
Window_set_normal_button( 79, 3,18,19,"T", 0,1,KEY_NONE);
Window_set_normal_button( 98, 3,18,19,"Y", 0,1,KEY_NONE);
Window_set_normal_button(117, 3,18,19,"U", 0,1,KEY_NONE);
Window_set_normal_button(136, 3,18,19,"I", 0,1,KEY_NONE);
Window_set_normal_button(155, 3,18,19,"O", 0,1,KEY_NONE);
Window_set_normal_button(174, 3,18,19,"P", 0,1,KEY_NONE);
Window_set_normal_button( 12,23,18,19,"A", 0,1,KEY_NONE);
Window_set_normal_button( 31,23,18,19,"S", 0,1,KEY_NONE);
Window_set_normal_button( 50,23,18,19,"D", 0,1,KEY_NONE);
Window_set_normal_button( 69,23,18,19,"F", 0,1,KEY_NONE);
Window_set_normal_button( 88,23,18,19,"G", 0,1,KEY_NONE);
Window_set_normal_button(107,23,18,19,"H", 0,1,KEY_NONE);
Window_set_normal_button(126,23,18,19,"J", 0,1,KEY_NONE);
Window_set_normal_button(145,23,18,19,"K", 0,1,KEY_NONE);
Window_set_normal_button(164,23,18,19,"L", 0,1,KEY_NONE);
Window_set_normal_button( 3,43,18,19,caps_lock?"\036":"\037", 0,1,KEY_NONE);
Window_set_normal_button( 22,43,18,19,"Z", 0,1,KEY_NONE);
Window_set_normal_button( 41,43,18,19,"X", 0,1,KEY_NONE);
Window_set_normal_button( 60,43,18,19,"C", 0,1,KEY_NONE);
Window_set_normal_button( 79,43,18,19,"V", 0,1,KEY_NONE);
Window_set_normal_button( 98,43,18,19,"B", 0,1,KEY_NONE);
Window_set_normal_button(117,43,18,19,"N", 0,1,KEY_NONE);
Window_set_normal_button(136,43,18,19,"M", 0,1,KEY_NONE);
Window_set_normal_button(155,43,18,19," ", 0,1,KEY_NONE);
for (y=0; y<5; y++)
{
for (x=0; x<6; x++)
{
char label[2]=" ";
label[0]=keymapping[x+y*6+44];
Window_set_normal_button(247+x*12, 3+y*16,11,15,label, 0,1,KEY_NONE);
}
}
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
}
else if (input_type == INPUT_TYPE_INTEGER || input_type == INPUT_TYPE_DECIMAL )
{
Init_virtual_keyboard(y_pos, 215, 47);
use_virtual_keyboard=1;
// The order is important, see the array
Window_set_normal_button( 7,27,43,15,"Clr", 0,1,KEY_NONE);
Window_set_normal_button( 51,27,43,15,"Del", 0,1,KEY_NONE);
Window_set_normal_button( 95,27,43,15,"OK", 0,1,KEY_NONE);
Window_set_normal_button(139,27,43,15,"Esc", 0,1,KEY_NONE);
Window_display_frame_in(5,25,179,19);
Window_set_normal_button(174, 3,18,19,"0", 0,1,KEY_NONE);
Window_set_normal_button( 3, 3,18,19,"1", 0,1,KEY_NONE);
Window_set_normal_button( 22, 3,18,19,"2", 0,1,KEY_NONE);
Window_set_normal_button( 41, 3,18,19,"3", 0,1,KEY_NONE);
Window_set_normal_button( 60, 3,18,19,"4", 0,1,KEY_NONE);
Window_set_normal_button( 79, 3,18,19,"5", 0,1,KEY_NONE);
Window_set_normal_button( 98, 3,18,19,"6", 0,1,KEY_NONE);
Window_set_normal_button(117, 3,18,19,"7", 0,1,KEY_NONE);
Window_set_normal_button(136, 3,18,19,"8", 0,1,KEY_NONE);
Window_set_normal_button(155, 3,18,19,"9", 0,1,KEY_NONE);
Window_set_normal_button(193, 3,18,19,".", 0,1,KEY_NONE);
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
}
#endif
Keyboard_click_allowed = 0;
Hide_cursor();
// Effacement de la chaîne
Block(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y),
Block(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),
visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR);
Update_rect(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y),
Update_rect(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),
visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3));
// Mise à jour des variables se rapportant à la chaîne en fonction de la chaîne initiale
@ -182,19 +350,67 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz
if (visible_size + offset + 1 < size )
display_string[visible_size-1]=RIGHT_TRIANGLE_CHARACTER;
Display_whole_string(x_pos,y_pos,display_string,position - offset);
Update_rect(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y),
Display_whole_string(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),display_string,position - offset);
Update_rect(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),
visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3));
Flush_update();
while ((input_key!=SDLK_RETURN) && (input_key!=KEY_ESC) && Mouse_K == 0)
if (Mouse_K)
{
Display_cursor();
do
Wait_end_of_click();
Hide_cursor();
}
while ((input_key!=SDLK_RETURN) && (input_key!=KEY_ESC))
{
Display_cursor();
#ifdef VIRT_KEY
if (use_virtual_keyboard)
{
if(!Get_input()) SDL_Delay(20);
int clicked_button;
clicked_button=Window_clicked_button();
input_key=Key_ANSI;
} while(input_key==0 && Mouse_K == 0);
if (clicked_button==-1)
input_key=SDLK_RETURN;
else if (clicked_button>0)
{
input_key=keymapping[clicked_button-1];
if (input_key==SDLK_CAPSLOCK)
{
// toggle uppercase
caps_lock=!caps_lock;
Hide_cursor();
Print_in_window(8, 49,caps_lock?"\036":"\037", MC_Black,MC_Light);
Display_cursor();
}
else if (input_key==SDLK_BACKSPACE)
{
// A little hack: the button for backspace will:
// - backspace if the cursor is at end of string
// - delete otherwise
// It's needed for those input boxes that are completely full.
if (position<size)
input_key = SDLK_DELETE;
}
else if (input_key>='A' && input_key<='Z' && !caps_lock)
{
input_key+='a'-'A';
}
}
}
else
#endif
{
do
{
Get_input(20);
input_key=Key_ANSI;
if (Mouse_K)
input_key=SDLK_RETURN;
} while(input_key==0);
}
Hide_cursor();
switch (input_key)
{
@ -205,7 +421,7 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz
size--;
// Effacement de la chaîne
Block(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y),
Block(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),
visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR);
goto affichage;
}
@ -215,7 +431,7 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz
{
// Effacement de la chaîne
if (position==size)
Block(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y),
Block(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),
visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR);
position--;
if (offset > 0 && (position == 0 || position < (offset + 1)))
@ -239,7 +455,7 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz
{
// Effacement de la chaîne
if (position==size)
Block(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y),
Block(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),
visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR);
position = 0;
offset = 0;
@ -265,11 +481,18 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz
Remove_character(str,position);
size--;
// Effacement de la chaîne
Block(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y),
Block(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),
visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR);
goto affichage;
}
break;
case SDLK_CLEAR : // Clear
str[0]='\0';
position=offset=0;
// Effacement de la chaîne
Block(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),
visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR);
goto affichage;
case SDLK_RETURN :
break;
@ -285,15 +508,15 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz
is_authorized=0; // On commence par supposer qu'elle est interdite
switch(input_type)
{
case 0 : // N'importe quelle chaîne:
case INPUT_TYPE_STRING :
if (input_key>=' ' && input_key<= 255)
is_authorized=1;
break;
case 1 : // Nombre
case INPUT_TYPE_INTEGER :
if ( (input_key>='0') && (input_key<='9') )
is_authorized=1;
break;
case 3: // Decimal number
case INPUT_TYPE_DECIMAL:
if ( (input_key>='0') && (input_key<='9') )
is_authorized=1;
else if (input_key=='-' && position==0 && str[0]!='-')
@ -301,10 +524,18 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz
else if (input_key=='.')
is_authorized=1;
break;
default : // Nom de fichier
case INPUT_TYPE_FILENAME:
// On regarde si la touche est autorisée
if ( Valid_character(input_key))
is_authorized=1;
case INPUT_TYPE_HEXA:
if ( (input_key>='0') && (input_key<='9') )
is_authorized=1;
else if ( (input_key>='A') && (input_key<='F') )
is_authorized=1;
else if ( (input_key>='a') && (input_key<='f') )
is_authorized=1;
break;
} // End du "switch(input_type)"
// Si la touche était autorisée...
@ -337,20 +568,29 @@ affichage:
if (visible_size + offset + 0 < size )
display_string[visible_size-1]=RIGHT_TRIANGLE_CHARACTER;
Display_whole_string(x_pos,y_pos,display_string,position - offset);
Update_rect(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y),
Display_whole_string(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),display_string,position - offset);
Update_rect(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),
visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3));
} // End du "switch(input_key)"
Flush_update();
} // End du "while"
Keyboard_click_allowed = 1;
#ifdef VIRT_KEY
if (use_virtual_keyboard)
{
byte old_mouse_k = Mouse_K;
Close_popup();
Mouse_K=old_mouse_k;
Input_sticky_control=0;
}
#endif
// Effacement de la chaîne
Block(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y),
Block(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),
visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR);
// On raffiche la chaine correctement
if (input_type==1)
if (input_type==INPUT_TYPE_INTEGER)
{
if (str[0]=='\0')
{
@ -359,7 +599,7 @@ affichage:
}
Print_in_window(x_pos+((max_size-size)<<3),y_pos,str,TEXT_COLOR,BACKGROUND_COLOR);
}
else if (input_type==3)
else if (input_type==INPUT_TYPE_DECIMAL)
{
double value;
// Discard extra digits
@ -377,10 +617,10 @@ affichage:
{
Print_in_window_limited(x_pos,y_pos,str,visible_size,TEXT_COLOR,BACKGROUND_COLOR);
}
Update_rect(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y),
Update_rect(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),
visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3));
return (input_key==SDLK_RETURN || Mouse_K != 0);
return (input_key==SDLK_RETURN);
}
void Sprint_double(char *str, double value, byte decimal_places, byte min_positions)

View File

@ -24,13 +24,22 @@
/// Text input functions.
//////////////////////////////////////////////////////////////////////////////
enum INPUT_TYPE
{
INPUT_TYPE_STRING=0, ///< Any string
INPUT_TYPE_INTEGER=1, ///< Decimal integer
INPUT_TYPE_FILENAME=2,///< Filename
INPUT_TYPE_DECIMAL=3, ///< Decimal value
INPUT_TYPE_HEXA=4, ///< Hexadecimal integer
};
///
/// Lets the user input a line of text, exit by Esc or Return.
/// @param x_pos Coordinates of input, in window coordinates before scaling.
/// @param y_pos Coordinates of input, in window coordinates before scaling.
/// @param str The original string value (will be modified, unless user cancels.
/// @param visible_size Number of characters visible and editable.
/// @param input_type 0=string, 1=number, 2=filename (255 editable characters)
/// @param input_type one of enum ::INPUT_TYPE
/// @return 0 if user cancelled (esc), 1 if accepted (return)
byte Readline(word x_pos,word y_pos,char * str,byte visible_size,byte input_type);
@ -41,7 +50,7 @@ byte Readline(word x_pos,word y_pos,char * str,byte visible_size,byte input_type
/// @param str The original string value (will be modified, unless user cancels.
/// @param visible_size Number of characters visible.
/// @param max_size Number of characters editable.
/// @param input_type 0=string, 1=integer, 2=filename (255 editable characters) 3=decimal
/// @param input_type one of enum ::INPUT_TYPE
/// @param decimal_places Number of decimal places (used only with decimal type)
/// @return 0 if user cancelled (esc), 1 if accepted (return)
byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_size, byte input_type, byte decimal_places);

View File

@ -6,8 +6,11 @@
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#if defined(__AROS__)
#include <limits.h>
#endif
#if defined(__AROS__) || defined(__BEOS__) || defined(__MORPHOS__) || defined(__GP2X__) || defined(__amigaos__)
#if defined(__AROS__) || defined(__BEOS__) || defined(__MORPHOS__) || defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__) || defined(__amigaos__)
// These platforms don't have realpath().
// We use the following implementation, found in:
// http://amiga.sourceforge.net/amigadevhelp/FUNCTIONS/GeekGadgets/realpath/ex02_realpath.c
@ -17,7 +20,7 @@
// the path. So this implementation is limited, it's really better to
// use realpath() if your platform has it.
#if defined(__GP2X__) || defined(__amigaos__)
#if defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__) || defined(__amigaos__)
// This is a random default value ...
#define PATH_MAX 32768
#endif

View File

@ -2,6 +2,7 @@
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Peter Gordon
Copyright 2008 Yves Rizoud
Copyright 2007 Adrien Destugues
@ -30,6 +31,7 @@
#include "errors.h"
#include "misc.h"
#include "saveini.h"
#include "setup.h"
int Save_INI_reach_group(FILE * old_file,FILE * new_file,char * buffer,char * group)
{
@ -393,8 +395,8 @@ void Save_INI_flush(FILE * old_file,FILE * new_file,char * buffer)
int Save_INI(T_Config * conf)
{
FILE * Ancien_fichier;
FILE * Nouveau_fichier;
FILE * old_file;
FILE * new_file;
char * buffer;
int values[3];
char filename[MAX_PATH_CHARACTERS];
@ -409,13 +411,13 @@ int Save_INI(T_Config * conf)
// On calcule les noms des fichiers qu'on manipule:
strcpy(filename,Config_directory);
strcat(filename,"gfx2.ini");
strcat(filename,INI_FILENAME);
// On vérifie si le fichier INI existe
if ((ini_file_exists = File_exists(filename)))
{
strcpy(temp_filename,Config_directory);
strcat(temp_filename,"gfx2.$$$");
strcat(temp_filename,INISAVE_FILENAME);
// On renome l'ancienne version du fichier INI vers un fichier temporaire:
if (rename(filename,temp_filename)!=0)
@ -425,237 +427,237 @@ int Save_INI(T_Config * conf)
}
// On récupère un fichier INI "propre" à partir de gfx2def.ini
strcpy(ref_ini_file,Data_directory);
strcat(ref_ini_file,"gfx2def.ini");
Ancien_fichier=fopen(ref_ini_file,"rb");
if (Ancien_fichier==0)
strcat(ref_ini_file,INIDEF_FILENAME);
old_file=fopen(ref_ini_file,"rb");
if (old_file==0)
{
fclose(Ancien_fichier);
fclose(old_file);
free(buffer);
return ERROR_INI_MISSING;
}
Nouveau_fichier=fopen(filename,"wb");
if (Nouveau_fichier==0)
new_file=fopen(filename,"wb");
if (new_file==0)
{
free(buffer);
return ERROR_SAVING_INI;
}
if ((return_code=Save_INI_reach_group(Ancien_fichier,Nouveau_fichier,buffer,"[MOUSE]")))
if ((return_code=Save_INI_reach_group(old_file,new_file,buffer,"[MOUSE]")))
goto Erreur_Retour;
values[0]=conf->Mouse_sensitivity_index_x;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"X_sensitivity",1,values,0)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"X_sensitivity",1,values,0)))
goto Erreur_Retour;
values[0]=conf->Mouse_sensitivity_index_y;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Y_sensitivity",1,values,0)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Y_sensitivity",1,values,0)))
goto Erreur_Retour;
values[0]=0;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"X_correction_factor",1,values,0)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"X_correction_factor",1,values,0)))
goto Erreur_Retour;
values[0]=0;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Y_correction_factor",1,values,0)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Y_correction_factor",1,values,0)))
goto Erreur_Retour;
values[0]=(conf->Cursor)+1;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Cursor_aspect",1,values,0)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Cursor_aspect",1,values,0)))
goto Erreur_Retour;
if ((return_code=Save_INI_reach_group(Ancien_fichier,Nouveau_fichier,buffer,"[MENU]")))
if ((return_code=Save_INI_reach_group(old_file,new_file,buffer,"[MENU]")))
goto Erreur_Retour;
values[0]=conf->Fav_menu_colors[2].R>>2;
values[1]=conf->Fav_menu_colors[2].G>>2;
values[2]=conf->Fav_menu_colors[2].B>>2;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Light_color",3,values,0)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Light_color",3,values,0)))
goto Erreur_Retour;
values[0]=conf->Fav_menu_colors[1].R>>2;
values[1]=conf->Fav_menu_colors[1].G>>2;
values[2]=conf->Fav_menu_colors[1].B>>2;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Dark_color",3,values,0)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Dark_color",3,values,0)))
goto Erreur_Retour;
values[0]=conf->Ratio;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Menu_ratio",1,values,0)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Menu_ratio",1,values,0)))
goto Erreur_Retour;
if ((return_code=Save_INI_reach_group(Ancien_fichier,Nouveau_fichier,buffer,"[FILE_SELECTOR]")))
if ((return_code=Save_INI_reach_group(old_file,new_file,buffer,"[FILE_SELECTOR]")))
goto Erreur_Retour;
values[0]=conf->Show_hidden_files?1:0;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Show_hidden_files",1,values,1)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Show_hidden_files",1,values,1)))
goto Erreur_Retour;
values[0]=conf->Show_hidden_directories?1:0;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Show_hidden_directories",1,values,1)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Show_hidden_directories",1,values,1)))
goto Erreur_Retour;
/* values[0]=conf->Show_system_directories?1:0;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Show_system_directories",1,values,1)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Show_system_directories",1,values,1)))
goto Erreur_Retour;
*/
values[0]=conf->Timer_delay;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Preview_delay",1,values,0)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Preview_delay",1,values,0)))
goto Erreur_Retour;
values[0]=conf->Maximize_preview;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Maximize_preview",1,values,1)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Maximize_preview",1,values,1)))
goto Erreur_Retour;
values[0]=conf->Find_file_fast;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Find_file_fast",1,values,0)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Find_file_fast",1,values,0)))
goto Erreur_Retour;
if ((return_code=Save_INI_reach_group(Ancien_fichier,Nouveau_fichier,buffer,"[LOADING]")))
if ((return_code=Save_INI_reach_group(old_file,new_file,buffer,"[LOADING]")))
goto Erreur_Retour;
values[0]=conf->Auto_set_res;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Auto_set_resolution",1,values,1)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Auto_set_resolution",1,values,1)))
goto Erreur_Retour;
values[0]=conf->Set_resolution_according_to;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Set_resolution_according_to",1,values,0)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Set_resolution_according_to",1,values,0)))
goto Erreur_Retour;
values[0]=conf->Clear_palette;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Clear_palette",1,values,1)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Clear_palette",1,values,1)))
goto Erreur_Retour;
if ((return_code=Save_INI_reach_group(Ancien_fichier,Nouveau_fichier,buffer,"[MISCELLANEOUS]")))
if ((return_code=Save_INI_reach_group(old_file,new_file,buffer,"[MISCELLANEOUS]")))
goto Erreur_Retour;
values[0]=conf->Display_image_limits;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Draw_limits",1,values,1)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Draw_limits",1,values,1)))
goto Erreur_Retour;
values[0]=conf->Adjust_brush_pick;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Adjust_brush_pick",1,values,1)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Adjust_brush_pick",1,values,1)))
goto Erreur_Retour;
values[0]=2-conf->Coords_rel;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Coordinates",1,values,0)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Coordinates",1,values,0)))
goto Erreur_Retour;
values[0]=conf->Backup;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Backup",1,values,1)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Backup",1,values,1)))
goto Erreur_Retour;
values[0]=conf->Max_undo_pages;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Undo_pages",1,values,0)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Undo_pages",1,values,0)))
goto Erreur_Retour;
values[0]=conf->Delay_left_click_on_slider;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Gauges_scrolling_speed_Left",1,values,0)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Gauges_scrolling_speed_Left",1,values,0)))
goto Erreur_Retour;
values[0]=conf->Delay_right_click_on_slider;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Gauges_scrolling_speed_Right",1,values,0)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Gauges_scrolling_speed_Right",1,values,0)))
goto Erreur_Retour;
values[0]=conf->Auto_save;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Auto_save",1,values,1)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Auto_save",1,values,1)))
goto Erreur_Retour;
values[0]=conf->Nb_max_vertices_per_polygon;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Vertices_per_polygon",1,values,0)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Vertices_per_polygon",1,values,0)))
goto Erreur_Retour;
values[0]=conf->Fast_zoom;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Fast_zoom",1,values,1)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Fast_zoom",1,values,1)))
goto Erreur_Retour;
values[0]=conf->Separate_colors;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Separate_colors",1,values,1)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Separate_colors",1,values,1)))
goto Erreur_Retour;
values[0]=conf->FX_Feedback;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"FX_feedback",1,values,1)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"FX_feedback",1,values,1)))
goto Erreur_Retour;
values[0]=conf->Safety_colors;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Safety_colors",1,values,1)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Safety_colors",1,values,1)))
goto Erreur_Retour;
values[0]=conf->Opening_message;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Opening_message",1,values,1)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Opening_message",1,values,1)))
goto Erreur_Retour;
values[0]=conf->Clear_with_stencil;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Clear_with_stencil",1,values,1)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Clear_with_stencil",1,values,1)))
goto Erreur_Retour;
values[0]=conf->Auto_discontinuous;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Auto_discontinuous",1,values,1)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Auto_discontinuous",1,values,1)))
goto Erreur_Retour;
values[0]=conf->Screen_size_in_GIF;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Save_screen_size_in_GIF",1,values,1)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Save_screen_size_in_GIF",1,values,1)))
goto Erreur_Retour;
values[0]=conf->Auto_nb_used;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Auto_nb_colors_used",1,values,1)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Auto_nb_colors_used",1,values,1)))
goto Erreur_Retour;
if ((return_code=Save_INI_set_strings (Ancien_fichier,Nouveau_fichier,buffer,"Default_video_mode",Mode_label(conf->Default_resolution))))
if ((return_code=Save_INI_set_strings (old_file,new_file,buffer,"Default_video_mode",Mode_label(conf->Default_resolution))))
goto Erreur_Retour;
values[0]=Video_mode[0].Width;
values[1]=Video_mode[0].Height;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Default_window_size",2,values,0)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Default_window_size",2,values,0)))
goto Erreur_Retour;
values[0]=(conf->Mouse_merge_movement);
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Merge_movement",1,values,0)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Merge_movement",1,values,0)))
goto Erreur_Retour;
values[0]=(conf->Palette_cells_X);
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Palette_cells_X",1,values,0)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Palette_cells_X",1,values,0)))
goto Erreur_Retour;
values[0]=(conf->Palette_cells_Y);
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Palette_cells_Y",1,values,0)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Palette_cells_Y",1,values,0)))
goto Erreur_Retour;
for (index=0;index<NB_BOOKMARKS;index++)
{
if ((return_code=Save_INI_set_strings (Ancien_fichier,Nouveau_fichier,buffer,"Bookmark_label",conf->Bookmark_label[index])))
if ((return_code=Save_INI_set_strings (old_file,new_file,buffer,"Bookmark_label",conf->Bookmark_label[index])))
goto Erreur_Retour;
if ((return_code=Save_INI_set_strings (Ancien_fichier,Nouveau_fichier,buffer,"Bookmark_directory",conf->Bookmark_directory[index])))
if ((return_code=Save_INI_set_strings (old_file,new_file,buffer,"Bookmark_directory",conf->Bookmark_directory[index])))
goto Erreur_Retour;
}
values[0]=(conf->Palette_vertical);
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Palette_vertical",1,values,1)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Palette_vertical",1,values,1)))
goto Erreur_Retour;
values[0]=conf->Window_pos_x;
values[1]=conf->Window_pos_y;
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Window_position",2,values,0)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Window_position",2,values,0)))
goto Erreur_Retour;
values[0]=(conf->Double_click_speed);
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Double_click_speed",1,values,0)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Double_click_speed",1,values,0)))
goto Erreur_Retour;
values[0]=(conf->Double_key_speed);
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Double_key_speed",1,values,0)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Double_key_speed",1,values,0)))
goto Erreur_Retour;
if ((return_code=Save_INI_set_strings (Ancien_fichier,Nouveau_fichier,buffer,"Skin_file",conf->Skin_file)))
if ((return_code=Save_INI_set_strings (old_file,new_file,buffer,"Skin_file",conf->Skin_file)))
goto Erreur_Retour;
if ((return_code=Save_INI_set_strings (Ancien_fichier,Nouveau_fichier,buffer,"Font_file",conf->Font_file)))
if ((return_code=Save_INI_set_strings (old_file,new_file,buffer,"Font_file",conf->Font_file)))
goto Erreur_Retour;
values[0]=(conf->Grid_XOR_color);
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Grid_XOR_color",1,values,0)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Grid_XOR_color",1,values,0)))
goto Erreur_Retour;
values[0]=(Pixel_ratio);
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Pixel_ratio",1,values,0))) {
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Pixel_ratio",1,values,0))) {
DEBUG("saving pixel ratio",return_code);
goto Erreur_Retour;
}
@ -670,14 +672,37 @@ int Save_INI(T_Config * conf)
for (; index<8;index++)
values[0] |= (1<<index);
if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Menubars_visible",1,values,0)))
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Menubars_visible",1,values,0)))
goto Erreur_Retour;
values[0]=(conf->Right_click_colorpick);
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Right_click_colorpick",1,values,1)))
goto Erreur_Retour;
values[0]=(conf->Sync_views);
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Sync_views",1,values,1)))
goto Erreur_Retour;
switch(conf->Swap_buttons)
{
case MOD_CTRL:
values[0]=1;
break;
case MOD_ALT:
values[0]=2;
break;
default:
values[0]=0;
}
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Swap_buttons",1,values,0)))
goto Erreur_Retour;
// Insert new values here
Save_INI_flush(old_file,new_file,buffer);
Save_INI_flush(Ancien_fichier,Nouveau_fichier,buffer);
fclose(Nouveau_fichier);
fclose(Ancien_fichier);
fclose(new_file);
fclose(old_file);
// On efface le fichier temporaire <=> Ancienne version du .INI
if (ini_file_exists)
@ -689,8 +714,8 @@ int Save_INI(T_Config * conf)
Erreur_Retour:
fclose(Nouveau_fichier);
fclose(Ancien_fichier);
fclose(new_file);
fclose(old_file);
free(buffer);
return return_code;

View File

@ -2,6 +2,7 @@
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet
Copyright 2007 Adrien Destugues
@ -23,6 +24,15 @@
#include <string.h>
#include <stdlib.h>
#include <SDL.h>
#include <SDL_endian.h>
#if defined(__WIN32__)
#include <windows.h>
#endif
// There is no WM on the GP2X...
#ifndef __GP2X__
#include <SDL_syswm.h>
#endif
#include "global.h"
#include "sdlscreen.h"
#include "errors.h"
@ -42,14 +52,21 @@
#ifndef UPDATE_METHOD
#if defined(__macosx__)
#define UPDATE_METHOD UPDATE_METHOD_FULL_PAGE
#elif defined(__MINT__)
#define UPDATE_METHOD UPDATE_METHOD_CUMULATED
#else
#define UPDATE_METHOD UPDATE_METHOD_CUMULATED
#endif
#endif
volatile int Allow_colorcycling=1;
/// Sets the new screen/window dimensions.
void Set_mode_SDL(int *width, int *height, int fullscreen)
{
static SDL_Cursor* cur = NULL;
static byte cursorData = 0;
Screen_SDL=SDL_SetVideoMode(*width,*height,8,(fullscreen?SDL_FULLSCREEN:0)|SDL_RESIZABLE);
if(Screen_SDL != NULL)
{
@ -66,7 +83,15 @@ void Set_mode_SDL(int *width, int *height, int fullscreen)
{
DEBUG("Error: Unable to change video mode!",0);
}
SDL_ShowCursor(0); // Hide the SDL mouse cursor, we use our own
// Trick borrowed to Barrage (http://www.mail-archive.com/debian-bugs-dist@lists.debian.org/msg737265.html) :
// Showing the cursor but setting it to fully transparent allows us to get absolute mouse coordinates,
// this means we can use tablet in fullscreen mode.
SDL_ShowCursor(1); // Hide the SDL mouse cursor, we use our own
SDL_FreeCursor(cur);
cur = SDL_CreateCursor(&cursorData, &cursorData, 1,1,0,0);
SDL_SetCursor(cur);
}
#if (UPDATE_METHOD == UPDATE_METHOD_CUMULATED)
@ -194,16 +219,36 @@ byte Get_SDL_pixel_8(SDL_Surface *bmp, int x, int y)
return ((byte *)(bmp->pixels))[(y*bmp->pitch+x)];
}
/// Writes a pixel in a 8-bit SDL surface.
void Set_SDL_pixel_8(SDL_Surface *bmp, int x, int y, byte color)
{
((byte *)(bmp->pixels))[(y*bmp->pitch+x)]=color;
}
/// Reads a pixel in a multi-byte SDL surface.
dword Get_SDL_pixel_hicolor(SDL_Surface *bmp, int x, int y)
{
byte * ptr;
switch(bmp->format->BytesPerPixel)
{
case 4:
default:
return *((dword *)((byte *)bmp->pixels+(y*bmp->pitch+x*4)));
case 3:
return *(((dword *)((byte *)bmp->pixels+(y*bmp->pitch+x*3)))) & 0xFFFFFF;
// Reading a 4-byte number starting at an address that isn't a multiple
// of 2 (or 4?) is not supported on Caanoo console at least (ARM CPU)
// So instead, we will read the 3 individual bytes, and re-construct the
// "dword" expected by SDL.
ptr = ((byte *)bmp->pixels)+(y*bmp->pitch+x*3);
#ifdef SDL_LIL_ENDIAN
// Read ABC, output _CBA : Most Significant Byte is zero.
return (*ptr) | (*(ptr+1)<<8) | (*(ptr+2)<<16);
#else
// Read ABC, output ABC_ : Least Significant Byte is zero.
return ((*ptr)<<24) | (*(ptr+1)<<16) | (*(ptr+2)<<8);
#endif
case 2:
return *((word *)((byte *)bmp->pixels+(y*bmp->pitch+x*2)));
}
@ -257,3 +302,18 @@ void Clear_border(byte color)
}
}
/// Activates or desactivates file drag-dropping in program window.
void Allow_drag_and_drop(int flag)
{
// Inform Windows that we accept drag-n-drop events or not
#ifdef __WIN32__
SDL_SysWMinfo wminfo;
HWND hwnd;
SDL_VERSION(&wminfo.version);
SDL_GetWMInfo(&wminfo);
hwnd = wminfo.window;
DragAcceptFiles(hwnd,flag?TRUE:FALSE);
SDL_EventState (SDL_SYSWMEVENT,flag?SDL_ENABLE:SDL_DISABLE );
#endif
}

View File

@ -56,6 +56,8 @@ SDL_Color Color_to_SDL_color(byte);
byte Get_SDL_pixel_8(SDL_Surface *bmp, int x, int y);
/// Reads a pixel in a multi-byte SDL surface.
dword Get_SDL_pixel_hicolor(SDL_Surface *bmp, int x, int y);
/// Writes a pixel in a 8-bit SDL surface.
void Set_SDL_pixel_8(SDL_Surface *bmp, int x, int y, byte color);
/// Convert a SDL Palette to a grafx2 palette
void Get_SDL_Palette(const SDL_Palette * sdl_palette, T_Palette palette);
@ -65,4 +67,9 @@ void Get_SDL_Palette(const SDL_Palette * sdl_palette, T_Palette palette);
/// size, eg: 3x3 pixels in 1024x768 leaves 1 column on the right, 0 rows on bottom.
void Clear_border(byte color);
extern volatile int Allow_colorcycling;
/// Activates or desactivates file drag-dropping in program window.
void Allow_drag_and_drop(int flag);
#endif // SDLSCREEN_H_INCLUDED

View File

@ -2,6 +2,7 @@
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Peter Gordon
Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet
@ -35,6 +36,9 @@
#import <sys/param.h>
#elif defined(__FreeBSD__)
#import <sys/param.h>
#elif defined(__MINT__)
#include <mint/osbind.h>
#include <mint/sysbind.h>
#elif defined(__linux__)
#include <limits.h>
#include <unistd.h>
@ -44,7 +48,7 @@
#include "io.h"
#include "setup.h"
#if defined(__GP2X__)
#if defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__)
// This is a random default value ...
#define PATH_MAX 32768
#endif
@ -84,7 +88,16 @@ void Set_program_directory(ARG_UNUSED const char * argv0,char * program_dir)
// AmigaOS and alike: hard-coded volume name.
#elif defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__)
strcpy(program_dir,"PROGDIR:");
#elif defined(__MINT__)
static char path[1024]={0};
char currentDrive='A';
currentDrive=currentDrive+Dgetdrv();
Dgetpath(path,0);
sprintf(program_dir,"%c:\%s",currentDrive,path);
// Append trailing slash
strcat(program_dir,PATH_SEPARATOR);
// Linux: argv[0] unreliable
#elif defined(__linux__)
if (argv0[0]!='/')
@ -115,9 +128,14 @@ void Set_data_directory(const char * program_dir, char * data_dir)
#if defined(__macosx__)
strcat(data_dir,"Contents/Resources/");
// On GP2X, executable is not in bin/
#elif defined (__gp2x__)
#elif defined (__GP2X__) || defined (__gp2x__) || defined (__WIZ__) || defined (__CAANOO__)
strcat(data_dir,"share/grafx2/");
//on tos the same directory
#elif defined (__MINT__)
strcpy(data_dir, program_dir);
// All other targets, program is in a "bin" subdirectory
#elif defined (__AROS__)
strcat(data_dir,"/share/grafx2/");
#else
strcat(data_dir,"../share/grafx2/");
#endif
@ -140,21 +158,23 @@ void Set_config_directory(const char * program_dir, char * config_dir)
#if defined(__amigaos4__) || defined(__AROS__)
strcpy(config_dir,"PROGDIR:");
// GP2X
#elif defined(__GP2X__)
#elif defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__)
// On the GP2X, the program is installed to the sdcard, and we don't want to mess with the system tree which is
// on an internal flash chip. So, keep these settings locals.
strcpy(config_dir,program_dir);
#elif defined(__MINT__)
strcpy(config_dir,program_dir);
#else
char filename[MAX_PATH_CHARACTERS];
// In priority: check root directory
strcpy(config_dir, program_dir);
// On all these targets except OSX and GP2X, the executable is in ./bin
#if !defined(__macosx__) && !defined(__gp2x__)
strcat(config_dir, "../");
// On all the remaining targets except OSX, the executable is in ./bin
#if !defined(__macosx__)
strcat(config_dir, "../");
#endif
strcpy(filename, config_dir);
strcat(filename, "gfx2.cfg");
strcat(filename, CONFIG_FILENAME);
if (!File_exists(filename))
{
@ -171,6 +191,10 @@ void Set_config_directory(const char * program_dir, char * config_dir)
// "~/Library/Preferences/com.googlecode.grafx2"
const char* Config_SubDir = "Library/Preferences/com.googlecode.grafx2";
config_parent_dir = getenv("HOME");
#elif defined(__MINT__)
const char* Config_SubDir = "";
printf("GFX2.CFG not found in %s\n",filename);
strcpy(config_parent_dir, config_dir);
#else
// "~/.grafx2"
const char* Config_SubDir = ".grafx2";
@ -203,7 +227,7 @@ void Set_config_directory(const char * program_dir, char * config_dir)
{
// Echec: on se rabat sur le repertoire de l'executable.
strcpy(config_dir,program_dir);
#if !defined(__macosx__) && !defined(__gp2x__)
#if defined(__macosx__)
strcat(config_dir, "../");
#endif
}

View File

@ -2,6 +2,7 @@
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Peter Gordon
Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet
@ -53,4 +54,104 @@ void Set_data_directory(const char * program_dir, char * data_dir);
/// IN: The directory containing the executable
/// OUT: Write into config_dir. Trailing / or \ is kept.
void Set_config_directory(const char * program_dir, char * config_dir);
/// Name of the subdirectory containing fonts, under the data directory (::Set_data_directory())
#if defined (__MINT__)
#define FONTS_SUBDIRECTORY "FONTS"
#else
#define FONTS_SUBDIRECTORY "fonts"
#endif
/// Name of the subdirectory containing fonts, under the data directory (::Set_data_directory())
#if defined (__MINT__)
#define SKINS_SUBDIRECTORY "SKINS"
#else
#define SKINS_SUBDIRECTORY "skins"
#endif
/// Name of the binary file containing some configuration settings.
#if defined (__MINT__)
#define CONFIG_FILENAME "GFX2.CFG"
#else
#define CONFIG_FILENAME "gfx2.cfg"
#endif
/// Name of the text file containing some settings in INI format.
#if defined (__MINT__)
#define INI_FILENAME "GFX2.INI"
#else
#define INI_FILENAME "gfx2.ini"
#endif
/// Name of the backup of the INI file.
#if defined (__MINT__)
#define INISAVE_FILENAME "GFX2.$$$"
#else
#define INISAVE_FILENAME "gfx2.$$$"
#endif
/// Name of the default .INI file (read-only: gives .INI format and defaults)
#if defined (__MINT__)
#define INIDEF_FILENAME "GFX2DEF.INI"
#else
#define INIDEF_FILENAME "gfx2def.ini"
#endif
/// Prefix for filenames of safety backups (main)
#if defined (__MINT__)
#define SAFETYBACKUP_PREFIX_A "A"
#else
#define SAFETYBACKUP_PREFIX_A "a"
#endif
/// Prefix for filenames of safety backups (spare)
#if defined (__MINT__)
#define SAFETYBACKUP_PREFIX_B "B"
#else
#define SAFETYBACKUP_PREFIX_B "b"
#endif
/// Name of the image file that serves as an application icon.
#if defined (__MINT__)
#define GFX2_ICON_FILENAME "GFX2.GIF"
#else
#define GFX2_ICON_FILENAME "gfx2.gif"
#endif
/// Name of the image file for the default (and fallback) GUI skin.
#if defined (__MINT__)
#define DEFAULT_SKIN_FILENAME "SDPAINT.PNG"
#else
#define DEFAULT_SKIN_FILENAME "skin_DPaint.png"
#endif
/// Name of the image file for the default (and fallback) 8x8 font.
#if defined (__MINT__)
#define DEFAULT_FONT_FILENAME "FDPAINT.PNG"
#else
#define DEFAULT_FONT_FILENAME "font_DPaint.png"
#endif
/// File extension for safety backups
#if defined (__MINT__)
#define BACKUP_FILE_EXTENSION ".BKP"
#else
#define BACKUP_FILE_EXTENSION ".bkp"
#endif
/// File prefix for fonts
#if defined (__MINT__)
#define FONT_PREFIX "F"
#else
#define FONT_PREFIX "font_"
#endif
/// File prefix for skins
#if defined (__MINT__)
#define SKIN_PREFIX "S"
#else
#define SKIN_PREFIX "skin_"
#endif

View File

@ -348,7 +348,7 @@ short Wait_click_in_shade_table()
while (selected_cell<0)
{
Get_input();
Get_input(20);
if ( (Mouse_K==LEFT_SIDE)
&& ( ( (Window_click_in_rectangle(8,127,263,179)) && (((((Mouse_Y-Window_pos_Y)/Menu_factor_Y)-127)%7)<4) )
@ -837,7 +837,7 @@ int Menu_shade(void)
case 15 : // Saisie du pas
Num2str(Shade_list[Shade_current].Step,str,3);
Readline(276,176,str,3,1);
Readline(276,176,str,3,INPUT_TYPE_INTEGER);
temp=atoi(str);
// On corrige le pas
if (!temp)
@ -1089,7 +1089,7 @@ void Button_Quick_shade_menu(void)
case 4 : // Saisie du pas
Num2str(Quick_shade_step,str,3);
Readline(42,21,str,3,1);
Readline(42,21,str,3,INPUT_TYPE_INTEGER);
temp=atoi(str);
// On corrige le pas
if (!temp)

View File

@ -431,6 +431,9 @@ void Transparency_set(byte amount)
break;
case 2 :
Effect_function=Effect_substractive_colorize;
break;
case 3 :
Effect_function=Effect_alpha_colorize;
}
Shade_mode=0;
Quick_shade_mode=0;

View File

@ -2,6 +2,7 @@
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Yves Rizoud
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
@ -73,14 +74,23 @@ typedef void (* Func_draw_brush) (byte *,word,word,word,word,word,word,byte,word
typedef void (* Func_draw_list_item) (word,word,word,byte); ///< Draw an item inside a list button. This is done with a callback so it is possible to draw anything, as the list itself doesn't handle the content
/// A set of RGB values.
#ifdef __GNUC__
typedef struct
{
byte R; ///< Red
byte G; ///< Green
byte B; ///< Blue
} __attribute__((__packed__)) T_Components, T_Palette[256] ; ///< A complete 256-entry RGB palette (768 bytes).
#else
#pragma pack(1)
typedef struct
{
byte R; ///< Red
byte G; ///< Green
byte B; ///< Blue
} T_Components, T_Palette[256]; ///< A complete 256-entry RGB palette (768 bytes).
} T_Components, T_Palette[256] ; ///< A complete 256-entry RGB palette (768 bytes).
#pragma pack()
#endif
/// A normal rectangular button in windows and menus.
typedef struct T_Normal_button
@ -105,17 +115,18 @@ typedef struct T_Palette_button
struct T_Palette_button * Next;///< Pointer to the next palette of current window.
} T_Palette_button;
/// A window control that represents a vertical scrollbar, with a slider, and two arrow buttons.
/// A window control that represents a scrollbar, with a slider, and two arrow buttons.
typedef struct T_Scroller_button
{
short Number; ///< Unique identifier for all controls
byte Is_horizontal; ///< Boolean: True if slider is horizontal instead of vertical.
word Pos_X; ///< Coordinate for top of button, relative to the window, before scaling.
word Pos_Y; ///< Coordinate for left of button, relative to the window, before scaling.
word Height; ///< Height before scaling.
word Length; ///< Length before scaling.
word Nb_elements; ///< Number of distinct values it can take.
word Nb_visibles; ///< If this slider is meant to show several elements of a collection, this is their number (otherwise, it's 1).
word Position; ///< Current position of the slider: which item it's pointing.
word Cursor_height; ///< Vertical dimension of the slider, in pixels before scaling.
word Cursor_length; ///< Dimension of the slider, in pixels before scaling.
struct T_Scroller_button * Next;///< Pointer to the next scroller of current window.
} T_Scroller_button;
@ -162,12 +173,20 @@ typedef struct T_Dropdown_button
/// Data for one item (file, directory) in a fileselector.
typedef struct T_Fileselector_item
{
char Short_name[19]; ///< Name to display.
char Full_name[256]; ///< Filesystem value.
byte Type; ///< Type of item: 0 = File, 1 = Directory, 2 = Drive
byte Icon; ///< One of ::ICON_TYPES, ICON_NONE for none.
struct T_Fileselector_item * Next; ///< Pointer to next item of the current fileselector.
struct T_Fileselector_item * Previous;///< Pointer to previous item of the current fileselector.
word Length_short_name; ///< Number of bytes allocated for :Short_name
#if __GNUC__ < 3
char Short_name[0]; ///< Name to display.
#else
char Short_name[]; ///< Name to display.
#endif
// No field after Short_name[] ! Dynamic allocation according to name length.
} T_Fileselector_item;
/// Data for a fileselector
@ -201,6 +220,25 @@ typedef struct T_List_button
struct T_List_button * Next; ///< Pointer to the next list button of current window.
} T_List_button;
/// A stackable window (editor screen)
typedef struct
{
word Pos_X;
word Pos_Y;
word Width;
word Height;
word Nb_buttons;
T_Normal_button *Normal_button_list;
T_Palette_button *Palette_button_list;
T_Scroller_button *Scroller_button_list;
T_Special_button *Special_button_list;
T_Dropdown_button *Dropdown_button_list;
T_List_button *List_button_list;
int Attribute1;
int Attribute2;
byte Draggable;
} T_Window;
/// Data for one line of the "Help" screens.
typedef struct {
char Line_type; ///< Kind of line: 'N' for normal line, 'S' for a bold line, 'K' for a line with keyboard shortcut, 'T' and '-' for upper and lower titles.
@ -223,7 +261,15 @@ typedef struct
dword Inverse; ///< Boolean, true if the gradient goes in descending order
dword Mix; ///< Amount of randomness to add to the mix (0-255)
dword Technique;///< Gradient technique: 0 (no pattern) 1 (dithering), or 2 (big dithering)
} T_Gradient_array;
byte Speed; ///< Speed of cycling. 0 for disabled, 1-64 otherwise.
} T_Gradient_range;
/// Data for a full set of gradients.
typedef struct
{
int Used; ///< Reference count
T_Gradient_range Range[16];
} T_Gradient_array;
/// Data for one setting of shade. Warning, this one is saved/loaded as binary.
typedef struct
@ -233,7 +279,6 @@ typedef struct
byte Mode; ///< Shade mode: Normal, Loop, or No-saturation see ::SHADE_MODES
} T_Shade;
#pragma pack(1) // is it useful ?
/// Data for one fullscreen video mode in configuration file. Warning, this one is saved/loaded as binary.
typedef struct
{
@ -242,8 +287,7 @@ typedef struct
word Height;///< Videomode height in pixels.
} T_Config_video_mode;
/// Header for gfx2.cfg. Warning, this one is saved/loaded as binary.
/// Header for gfx2.cfg
typedef struct
{
char Signature[3]; ///< Signature for the file format. "CFG".
@ -253,24 +297,22 @@ typedef struct
byte Beta2; ///< Major beta version number (ex: 5)
} T_Config_header;
#pragma pack()
/// Header for a config chunk in for gfx2.cfg. Warning, this one is saved/loaded as binary.
/// Header for a config chunk in for gfx2.cfg
typedef struct
{
byte Number; ///< Section identfier. Possible values are in enum ::CHUNKS_CFG
word Size; ///< Size of the configuration block that follows, in bytes.
} T_Config_chunk;
#pragma pack(1)
/// Configuration for one keyboard shortcut in gfx2.cfg. Warning, this one is saved/loaded as binary.
/// Configuration for one keyboard shortcut in gfx2.cfg
typedef struct
{
word Number; ///< Indicates the shortcut action. This is a number starting from 0, which matches ::T_Key_config.Number
word Key; ///< Keyboard shortcut: SDLK_something, or -1 for none
word Key2; ///< Alternate keyboard shortcut: SDLK_something, or -1 for none
} T_Config_shortcut_info;
#pragma pack()
/// This structure holds all the settings saved and loaded as gfx2.ini.
typedef struct
@ -321,6 +363,10 @@ typedef struct
word Double_click_speed; ///< Maximum delay for double-click, in ms.
word Double_key_speed; ///< Maximum delay for double-keypress, in ms.
byte Grid_XOR_color; ///< XOR value to apply for grid color.
byte Right_click_colorpick; ///< Boolean, true to enable a "tablet" mode, where RMB acts as instant colorpicker
byte Sync_views; ///< Boolean, true when the Main and Spare should share their viewport settings.
byte Stylus_mode; ///< Boolean, true to tweak some tools (eg:Curve) for single-button stylus.
word Swap_buttons; ///< Sets which key swaps mouse buttons : 0=none, or MOD_CTRL, or MOD_ALT.
} T_Config;
// Structures utilisées pour les descriptions de pages et de liste de pages.
@ -347,6 +393,7 @@ typedef struct T_Page
byte File_format; ///< File format, in enum ::FILE_FORMATS
struct T_Page *Next; ///< Pointer to the next backup
struct T_Page *Prev; ///< Pointer to the previous backup
T_Gradient_array *Gradients; ///< Pointer to the gradients used by the image.
byte Background_transparent; ///< Boolean, true if Layer 0 should have transparent pixels
byte Transparent_color; ///< Index of transparent color. 0 to 255.
byte Nb_layers; ///< Number of layers
@ -381,6 +428,7 @@ typedef struct
word Height;
byte * Brush; /// < Color brush (if any)
T_Palette Palette;
byte Colormap[256];
byte Transp_color;
} T_Brush_template;
@ -396,21 +444,6 @@ typedef struct
/// Graphic resources for the mouse cursor.
byte Cursor_sprite[NB_CURSOR_SPRITES][CURSOR_SPRITE_HEIGHT][CURSOR_SPRITE_WIDTH];
// Preset paintbrushes
/// Graphic resources for the preset paintbrushes.
byte Paintbrush_sprite [NB_PAINTBRUSH_SPRITES][PAINTBRUSH_HEIGHT][PAINTBRUSH_WIDTH];
/// Width of the preset paintbrushes.
word Preset_paintbrush_width[NB_PAINTBRUSH_SPRITES];
/// Height of the preset paintbrushes.
word Preset_paintbrush_height[NB_PAINTBRUSH_SPRITES];
/// Type of the preset paintbrush: index in enum PAINTBRUSH_SHAPES
byte Paintbrush_type[NB_PAINTBRUSH_SPRITES];
/// Brush handle for the preset brushes. Generally ::Preset_paintbrush_width[]/2
word Preset_paintbrush_offset_X[NB_PAINTBRUSH_SPRITES];
/// Brush handle for the preset brushes. Generally ::Preset_paintbrush_height[]/2
word Preset_paintbrush_offset_Y[NB_PAINTBRUSH_SPRITES];
// Sieve patterns
/// Preset sieve patterns, stored as binary (one word per line)
@ -419,13 +452,13 @@ typedef struct
// Menu and other graphics
/// Bitmap data for the menu, a single rectangle.
byte Menu_block[35][MENU_WIDTH];
byte Layerbar_block[10][144];
byte Statusbar_block[9][20];
byte Menu_block[3][35][MENU_WIDTH];
byte Layerbar_block[3][10][144];
byte Statusbar_block[3][9][20];
/// Bitmap data for the icons that are displayed over the menu.
byte Menu_sprite[NB_MENU_SPRITES][MENU_SPRITE_HEIGHT][MENU_SPRITE_WIDTH];
byte Menu_sprite[2][NB_MENU_SPRITES][MENU_SPRITE_HEIGHT][MENU_SPRITE_WIDTH];
/// Bitmap data for the different "effects" icons.
byte Effect_sprite[NB_EFFECTS_SPRITES][MENU_SPRITE_HEIGHT][MENU_SPRITE_WIDTH];
byte Effect_sprite[NB_EFFECTS_SPRITES][EFFECT_SPRITE_HEIGHT][EFFECT_SPRITE_WIDTH];
/// Bitmap data for the different Layer icons.
byte Layer_sprite[3][16][LAYER_SPRITE_HEIGHT][LAYER_SPRITE_WIDTH];
/// Bitmap data for the Grafx2 logo that appears on splash screen. All 256 colors allowed.
@ -458,16 +491,33 @@ typedef struct
/// Transparent GUI color index in skin file
byte Color_trans;
} T_Gui_skin;
typedef struct {
// Preset paintbrushes
/// Graphic resources for the preset paintbrushes.
byte Sprite[PAINTBRUSH_HEIGHT][PAINTBRUSH_WIDTH];
/// Width of the preset paintbrushes.
word Width;
/// Height of the preset paintbrushes.
word Height;
/// Type of the preset paintbrush: index in enum PAINTBRUSH_SHAPES
byte Shape;
/// Brush handle for the preset brushes. Generally ::Width[]/2
word Offset_X;
/// Brush handle for the preset brushes. Generally ::Height[]/2
word Offset_Y;
} T_Paintbrush;
// A menubar.
typedef struct {
word Width;
word Height;
byte Visible;
word Top; ///< Relative to the top line of the menu, hidden bars don't count.
byte* Skin;
byte* Skin[3]; ///< [0] has normal buttons, [1] has selected buttons, [2] is current.
word Skin_width;
byte Last_button_index;
} T_Menu_Bar;

View File

@ -2,6 +2,7 @@
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2011 Pawel Góralski
Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet
Copyright 2008 Adrien Destugues
@ -36,19 +37,18 @@
#include <SDL_ttf.h>
#endif
#if defined(__linux__)
#if defined(__macosx__)
#if defined(__CAANOO__) || defined(__WIZ__) || defined(__GP2X__)
// No X11
#elif defined(__macosx__)
#include <Carbon/Carbon.h>
#import <corefoundation/corefoundation.h>
#import <sys/param.h>
#else
#elif defined(__linux__)
#include <X11/Xlib.h>
#endif
#endif
#endif
#include <SDL_image.h>
// SFont
#include "SFont.h"
#include "struct.h"
@ -56,6 +56,9 @@
#include "sdlscreen.h"
#include "io.h"
#include "errors.h"
#include "windows.h"
#include "misc.h"
#include "setup.h"
typedef struct T_Font
{
@ -282,7 +285,7 @@ void Init_text(void)
Nb_fonts=0;
// Parcours du répertoire "fonts"
strcpy(directory_name, Data_directory);
strcat(directory_name, "fonts");
strcat(directory_name, FONTS_SUBDIRECTORY);
For_each_file(directory_name, Add_font);
#if defined(__WIN32__)
@ -321,6 +324,8 @@ void Init_text(void)
CFRelease(url);
#endif
#elif defined(__CAANOO__) || defined(__WIZ__) || defined(__GP2X__)
// No X11 : Only use fonts from Grafx2
#elif defined(__linux__)
#ifndef NOTTF
#define USE_XLIB
@ -343,15 +348,22 @@ void Init_text(void)
#ifndef NOTTF
For_each_file( "FONTS:_TrueType", Add_font );
#endif
#elif defined(__BEOS__) || defined(__HAIKU__)
#elif defined(__BEOS__)
#ifndef NOTTF
For_each_file("/etc/fonts/ttfonts", Add_font);
#endif
#elif defined(__HAIKU__)
#ifndef NOTTF
For_each_file("/boot/system/data/fonts/ttfonts/", Add_font);
#endif
#elif defined(__SKYOS__)
#ifndef NOTTF
For_each_file("/boot/system/fonts", Add_font);
#endif
#elif defined(__MINT__)
#ifndef NOTTF
For_each_file("C:/BTFONTS", Add_font);
#endif
#endif
}
@ -368,17 +380,15 @@ int TrueType_is_supported()
#ifndef NOTTF
byte *Render_text_TTF(const char *str, int font_number, int size, int antialias, int bold, int italic, int *width, int *height)
byte *Render_text_TTF(const char *str, int font_number, int size, int antialias, int bold, int italic, int *width, int *height, T_Palette palette)
{
TTF_Font *font;
SDL_Surface * TexteColore;
SDL_Surface * Texte8Bit;
TTF_Font *font;
SDL_Surface * text_surface;
byte * new_brush;
int index;
int style;
SDL_Color Couleur_Avant;
SDL_Color Couleur_Arriere;
SDL_Color fg_color;
SDL_Color bg_color;
// Chargement de la fonte
font=TTF_OpenFont(Font_name(font_number), size);
@ -386,6 +396,7 @@ byte *Render_text_TTF(const char *str, int font_number, int size, int antialias,
{
return NULL;
}
// Style
style=0;
if (italic)
@ -393,82 +404,170 @@ byte *Render_text_TTF(const char *str, int font_number, int size, int antialias,
if (bold)
style|=TTF_STYLE_BOLD;
TTF_SetFontStyle(font, style);
// Couleurs
if (antialias)
{
Couleur_Avant = Color_to_SDL_color(Fore_color);
Couleur_Arriere = Color_to_SDL_color(Back_color);
}
else
{
Couleur_Avant = Color_to_SDL_color(MC_White);
Couleur_Arriere = Color_to_SDL_color(MC_Black);
}
// Rendu du texte: crée une surface SDL RGB 24bits
// Colors: Text will be generated as white on black.
fg_color.r=fg_color.g=fg_color.b=255;
bg_color.r=bg_color.g=bg_color.b=0;
// The following is alpha, supposedly unused
bg_color.unused=fg_color.unused=255;
// Text rendering: creates a 8bit surface with its dedicated palette
if (antialias)
TexteColore=TTF_RenderText_Shaded(font, str, Couleur_Avant, Couleur_Arriere );
text_surface=TTF_RenderText_Shaded(font, str, fg_color, bg_color );
else
TexteColore=TTF_RenderText_Solid(font, str, Couleur_Avant);
if (!TexteColore)
text_surface=TTF_RenderText_Solid(font, str, fg_color);
if (!text_surface)
{
TTF_CloseFont(font);
return NULL;
}
Texte8Bit=SDL_DisplayFormat(TexteColore);
SDL_FreeSurface(TexteColore);
new_brush=Surface_to_bytefield(Texte8Bit, NULL);
new_brush=Surface_to_bytefield(text_surface, NULL);
if (!new_brush)
{
SDL_FreeSurface(TexteColore);
SDL_FreeSurface(Texte8Bit);
SDL_FreeSurface(text_surface);
TTF_CloseFont(font);
return NULL;
}
if (!antialias)
// Import palette
Get_SDL_Palette(text_surface->format->palette, palette);
if (antialias)
{
// Mappage des couleurs
for (index=0; index < Texte8Bit->w * Texte8Bit->h; index++)
int black_col;
// Shaded text: X-Swap the color that is pure black with the BG color number,
// so that the brush is immediately 'transparent'
// Find black (c)
for (black_col=0; black_col<256; black_col++)
{
if (*(new_brush+index) == MC_Black)
*(new_brush+index)=Back_color;
else if (*(new_brush+index) == MC_White)
*(new_brush+index)=Fore_color;
if (palette[black_col].R==0 && palette[black_col].G==0 && palette[black_col].B==0)
break;
} // If not found: c = 256 = 0 (byte)
if (black_col != Back_color)
{
int c;
byte colmap[256];
// Swap palette entries
SWAP_BYTES(palette[black_col].R, palette[Back_color].R)
SWAP_BYTES(palette[black_col].G, palette[Back_color].G)
SWAP_BYTES(palette[black_col].B, palette[Back_color].B)
// Define a colormap
for (c=0; c<256; c++)
colmap[c]=c;
// The swap
colmap[black_col]=Back_color;
colmap[Back_color]=black_col;
Remap_general_lowlevel(colmap, new_brush, new_brush, text_surface->w,text_surface->h, text_surface->w);
// Also, make the BG color in brush palette have same RGB values as
// the current BG color : this will help for remaps.
palette[Back_color].R=Main_palette[Back_color].R;
palette[Back_color].G=Main_palette[Back_color].G;
palette[Back_color].B=Main_palette[Back_color].B;
}
}
*width=Texte8Bit->w;
*height=Texte8Bit->h;
SDL_FreeSurface(Texte8Bit);
else
{
// Solid text: Was rendered as white on black. Now map colors:
// White becomes FG color, black becomes BG. 2-color palette.
// Exception: if BG==FG, FG will be set to black or white - any different color.
long index;
byte new_fore=Fore_color;
if (Fore_color==Back_color)
{
if (Main_palette[Back_color].R+Main_palette[Back_color].G+Main_palette[Back_color].B > 128*3)
// Back color is rather light:
new_fore=MC_Black;
else
// Back color is rather dark:
new_fore=MC_White;
}
for (index=0; index < text_surface->w * text_surface->h; index++)
{
if (palette[*(new_brush+index)].G < 128)
*(new_brush+index)=Back_color;
else
*(new_brush+index)=new_fore;
}
// Now copy the current palette to brushe's, for consistency
// with the indices.
memcpy(palette, Main_palette, sizeof(T_Palette));
}
*width=text_surface->w;
*height=text_surface->h;
SDL_FreeSurface(text_surface);
TTF_CloseFont(font);
return new_brush;
}
#endif
byte *Render_text_SFont(const char *str, int font_number, int *width, int *height)
byte *Render_text_SFont(const char *str, int font_number, int *width, int *height, T_Palette palette)
{
SFont_Font *font;
SDL_Surface * TexteColore;
SDL_Surface * Texte8Bit;
SDL_Surface *Surface_fonte;
SDL_Surface * text_surface;
SDL_Surface *font_surface;
byte * new_brush;
SDL_Rect rectangle;
// Chargement de la fonte
Surface_fonte=IMG_Load(Font_name(font_number));
if (!Surface_fonte)
font_surface=IMG_Load(Font_name(font_number));
if (!font_surface)
{
DEBUG("Font loading failed",0);
Verbose_message("Warning","Error loading font.\nThe file may be corrupt.");
return NULL;
}
font=SFont_InitFont(Surface_fonte);
// Font is 24bit: Perform a color reduction
if (font_surface->format->BitsPerPixel>8)
{
SDL_Surface * reduced_surface;
int x,y,color;
SDL_Color rgb;
reduced_surface=SDL_CreateRGBSurface(SDL_SWSURFACE, font_surface->w, font_surface->h, 8, 0, 0, 0, 0);
if (!reduced_surface)
{
SDL_FreeSurface(font_surface);
return NULL;
}
// Set the quick palette
for (color=0;color<256;color++)
{
rgb.r=((color & 0xE0)>>5)<<5;
rgb.g=((color & 0x1C)>>2)<<5;
rgb.b=((color & 0x03)>>0)<<6;
SDL_SetColors(reduced_surface, &rgb, color, 1);
}
// Perform reduction
for (y=0; y<font_surface->h; y++)
for (x=0; x<font_surface->w; x++)
{
SDL_GetRGB(Get_SDL_pixel_hicolor(font_surface, x, y), font_surface->format, &rgb.r, &rgb.g, &rgb.b);
color=((rgb.r >> 5) << 5) |
((rgb.g >> 5) << 2) |
((rgb.b >> 6));
Set_SDL_pixel_8(reduced_surface, x, y, color);
}
SDL_FreeSurface(font_surface);
font_surface=reduced_surface;
}
font=SFont_InitFont(font_surface);
if (!font)
{
DEBUG("Font init failed",1);
SDL_FreeSurface(font_surface);
return NULL;
}
@ -476,40 +575,36 @@ byte *Render_text_SFont(const char *str, int font_number, int *width, int *heigh
*height=SFont_TextHeight(font);
*width=SFont_TextWidth(font, str);
// Allocation d'une surface SDL
TexteColore=SDL_CreateRGBSurface(SDL_SWSURFACE, *width, *height, 24, 0, 0, 0, 0);
text_surface=SDL_CreateRGBSurface(SDL_SWSURFACE, *width, *height, 8, 0, 0, 0, 0);
// Copy palette
SDL_SetPalette(text_surface, SDL_LOGPAL, font_surface->format->palette->colors, 0, 256);
// Fill with backcolor
rectangle.x=0;
rectangle.y=0;
rectangle.w=*width;
rectangle.h=*height;
SDL_FillRect(TexteColore, &rectangle, SDL_MapRGB(
TexteColore->format,
Main_palette[Back_color].R,
Main_palette[Back_color].G,
Main_palette[Back_color].B
));
SDL_FillRect(text_surface, &rectangle, Back_color);
// Rendu du texte
SFont_Write(TexteColore, font, 0, 0, str);
if (!TexteColore)
SFont_Write(text_surface, font, 0, 0, str);
if (!text_surface)
{
DEBUG("Rendering failed",2);
SFont_FreeFont(font);
return NULL;
}
Texte8Bit=SDL_DisplayFormat(TexteColore);
SDL_FreeSurface(TexteColore);
new_brush=Surface_to_bytefield(Texte8Bit, NULL);
new_brush=Surface_to_bytefield(text_surface, NULL);
if (!new_brush)
{
DEBUG("Converting failed",3);
SDL_FreeSurface(TexteColore);
SDL_FreeSurface(Texte8Bit);
SDL_FreeSurface(text_surface);
SFont_FreeFont(font);
return NULL;
}
SDL_FreeSurface(Texte8Bit);
Get_SDL_Palette(font_surface->format->palette, palette);
SDL_FreeSurface(text_surface);
SFont_FreeFont(font);
return new_brush;
@ -524,7 +619,7 @@ byte *Render_text_SFont(const char *str, int font_number, int *width, int *heigh
// Crée une brosse à partir des paramètres de texte demandés.
// Si cela réussit, la fonction place les dimensions dans width et height,
// et retourne l'adresse du bloc d'octets.
byte *Render_text(const char *str, int font_number, TTFONLY int size, int TTFONLY antialias, TTFONLY int bold, TTFONLY int italic, int *width, int *height)
byte *Render_text(const char *str, int font_number, TTFONLY int size, int TTFONLY antialias, TTFONLY int bold, TTFONLY int italic, int *width, int *height, T_Palette palette)
{
T_Font *font = font_list_start;
int index=font_number;
@ -538,14 +633,14 @@ byte *Render_text(const char *str, int font_number, TTFONLY int size, int TTFONL
if (font->Is_truetype)
{
#ifndef NOTTF
return Render_text_TTF(str, font_number, size, antialias, bold, italic, width, height);
return Render_text_TTF(str, font_number, size, antialias, bold, italic, width, height, palette);
#else
return NULL;
#endif
}
else
{
return Render_text_SFont(str, font_number, width, height);
return Render_text_SFont(str, font_number, width, height, palette);
}
}

View File

@ -41,15 +41,16 @@ void Add_font(const char *name);
/// @param italic Boolean, true to use italic rendering in TrueType
/// @param width Returns the width of the created brush, in pixels.
/// @param height Returns the height of the created brush, in pixels.
/// @param palette Returns the custom palette for the brush.
/// Returns true on success.
byte *Render_text(const char *str, int font_number, int size, int antialias, int bold, int italic, int *width, int *height);
byte *Render_text(const char *str, int font_number, int size, int antialias, int bold, int italic, int *width, int *height, T_Palette palette);
/// Finds a label to display for a font declared with ::Add_font().
char * Font_label(int index);
/// Finds the filename of a font declared with ::Add_font().
char * Font_name(int index);
/// Returns true if the font of this number is TrueType, false if it's a SFont bitmap.
char * TrueType_font(int index);
int TrueType_font(int index);
///
/// Number of fonts declared with a series of ::Add_font(). This is public for
/// convenience, but functionaly it is read-only.

114
src/tiles.c Normal file
View File

@ -0,0 +1,114 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2010 Adrien Destugues
Grafx2 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; version 2
of the License.
Grafx2 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.
You should have received a copy of the GNU General Public License
along with Grafx2; if not, see <http://www.gnu.org/licenses/>
*/
/// \file Handle tiles.
/// Build the tile-area from the current picture
void build_tile_area()
{
word tileAreaWidth = Main_image_width / Snap_width + 1;
word tileAreaHeight = Main_image_height / Snap_height + 1;
int* tileArea = malloc(tileAreaWidth*tileAreaHeight*sizeof(int));
word tile_x, tile_y, pixel_x, pixel_y;
// For each tile, we have to crawl up to the top of the picture and
// find the first identical tile
for (tile_y = 0; tile_y < tileAreaWidth; tile_y++)
for(tile_x = 0; tile_x < tileAreaHeight; tile_x++)
{
// So, this is the "for each tile"
word ctx, cty;
// First we compare the tile with the others one in the same line at the left
for(ctx = tile_x - 1; ctx >= 0; ctx--)
if(compare_tiles(tile_x*Snap_width, tile_y*Snap_height, ctx*Snap_width, tile_y*Snap_height))
{
// We found a match !
tileArea[tile_y*tileAreaWidth+tile_x] = tile_y*tileAreaWidth+ctx;
goto found;
}
// Then we look at all the lines above
for(cty = tile_y - 1; cty >= 0; cty--)
for(ctx = tileAreaWidth - 1; ctx >= 0; ctx--)
if(compare_tiles(tile_x*Snap_width, tile_y*Snap_height, ctx*Snap_width, cty*Snap_height))
{
// We found a match !
tileArea[tile_y*tileAreaWidth+tile_x] = cty*tileAreaWidth+ctx;
goto found;
}
// Then we look at all the lines below
for(cty = tileAreaHeight - 1; cty >= tile_y; cty--)
for(ctx = tileAreaWidth - 1; ctx >= 0; ctx--)
if(compare_tiles(tile_x*Snap_width, tile_y*Snap_height, ctx*Snap_width, cty*Snap_height))
{
// We found a match !
tileArea[tile_y*tileAreaWidth+tile_x] = cty*tileAreaWidth+ctx;
goto found;
}
// Then we look at the tiles at the right of this one
// (including the tile itself, so we are sure we match something this time)
for(ctx = tileAreaHeight; ctx >= tile_x; ctx--)
if(compare_tiles(tile_x*Snap_width, tile_y*Snap_height, ctx*Snap_width, tile_y*Snap_height))
{
// We found a match !
tileArea[tile_y*tileAreaWidth+tile_x] = tile_y*tileAreaWidth+ctx;
}
found:
}
}
// Compare tiles
// The parameters are in pixel-space.
void compare_tiles(word x1, word y1, word x2, word y2)
{
word pixel_x, pixel_y;
byte c1, c2;
for (pixel_y = 0; pixel_y < Snap_width; pixel_y++)
for (pixel_x = 0; pixel_x < Snap_height; pixel_x++)
{
c1 = Main_screen + (y1+pixel_y) * Main_image_width + (x1+pixel_x);
c2 = Main_screen + (y2+pixel_y) * Main_image_width + (x2+pixel_x);
if (c1 != c2) return 0;
}
return 1;
}
/// Copy a tile pixeldata to all the identical ones
// Call this after the end of an operation
void update_tile(word pixel_x, word pixel_y)
{
int tileOffset = (pixel_y/Snap_height)*tileAreaHeight + pixel_x/Snap_width;
int firstTileOffset = tileOffset + 1; // to make sure they are not equal
while(firstTileOffset != tileOffset)
{
tileOffset = tileArea[tileOffset];
//do the copy of a block starting at (pixel_x, pixel_y)
}
}

View File

@ -273,7 +273,7 @@ void Button_Transform_menu(void)
input_button[clicked_button-10]->Pos_Y+2,
buffer,
4,
1))
INPUT_TYPE_INTEGER))
{
// Accept entered value
*(input_value[clicked_button-10])=atoi(buffer);
@ -369,8 +369,9 @@ void Button_Transform_menu(void)
old_width=Main_image_width;
old_height=Main_image_height;
Upload_infos_page_main(Main_backups->Pages);
// Allocate a new page
if (Backup_with_new_dimensions(1,Main_backups->Pages->Nb_layers,new_width,new_height))
if (Backup_with_new_dimensions(new_width,new_height))
{
// The new image is allocated, the new dimensions are already updated.

View File

@ -36,8 +36,11 @@
#include "graph.h"
#include "input.h"
#include "misc.h"
#include "op_c.h"
#include "readline.h"
#include "sdlscreen.h"
#include "palette.h"
/// Width of one layer button, in pixels before scaling
word Layer_button_width = 1;
@ -67,7 +70,7 @@ void Pixel_in_menu(word bar, word x, word y, byte color)
void Pixel_in_menu_and_skin(word bar, word x, word y, byte color)
{
Pixel_in_menu(bar, x, y, color);
Menu_bars[bar].Skin[y*Menu_bars[bar].Skin_width + x] = color;
Menu_bars[bar].Skin[2][y*Menu_bars[bar].Skin_width + x] = color;
}
// Affichage d'un pixel dans la fenêtre (la fenêtre doit être visible)
@ -454,7 +457,7 @@ void Draw_bar_remainder(word current_menu, word x_off)
for (y_pos=0;y_pos<Menu_bars[current_menu].Height;y_pos++)
for (x_pos=x_off;x_pos<Screen_width/Menu_factor_X;x_pos++)
Pixel_in_menu(current_menu, x_pos, y_pos, Menu_bars[current_menu].Skin[y_pos * Menu_bars[current_menu].Skin_width + Menu_bars[current_menu].Skin_width - 2 + (x_pos&1)]);
Pixel_in_menu(current_menu, x_pos, y_pos, Menu_bars[current_menu].Skin[0][y_pos * Menu_bars[current_menu].Skin_width + Menu_bars[current_menu].Skin_width - 2 + (x_pos&1)]);
}
@ -491,7 +494,7 @@ void Display_layerbar(void)
x_off=Menu_bars[MENUBAR_LAYERS].Skin_width;
for (current_button=0; current_button<button_number; current_button++)
{
word x_pos;
word x_pos=0;
word y_pos;
word sprite_index;
@ -566,7 +569,7 @@ void Display_menu(void)
// Skinned area
for (y_pos=0;y_pos<Menu_bars[current_menu].Height;y_pos++)
for (x_pos=0;x_pos<Menu_bars[current_menu].Skin_width;x_pos++)
Pixel_in_menu(current_menu, x_pos, y_pos, Menu_bars[current_menu].Skin[y_pos * Menu_bars[current_menu].Skin_width + x_pos]);
Pixel_in_menu(current_menu, x_pos, y_pos, Menu_bars[current_menu].Skin[2][y_pos * Menu_bars[current_menu].Skin_width + x_pos]);
if (current_menu == MENUBAR_LAYERS)
{
@ -706,6 +709,7 @@ void Print_coordinates(void)
if (Menu_is_visible && !Cursor_in_menu)
{
if ( (Current_operation==OPERATION_COLORPICK)
|| (Current_operation==OPERATION_RMB_COLORPICK)
|| (Current_operation==OPERATION_REPLACE) )
{
if ( (Paintbrush_X>=0) && (Paintbrush_Y>=0)
@ -1073,7 +1077,7 @@ int Requester_window(char* message, int initial_value)
{
clicked_button = Window_clicked_button();
if (clicked_button == 1)
Readline(11, 39, str, 4, 1);
Readline(11, 39, str, 4, INPUT_TYPE_INTEGER);
if (Key == SDLK_ESCAPE) clicked_button = 2;
}
while (clicked_button <= 0);
@ -1179,90 +1183,34 @@ void Verbose_message(const char *caption, const char * message )
// -- Redessiner le sprite d'un bouton dans le menu --
void Display_sprite_in_menu(int btn_number,int sprite_number)
void Display_sprite_in_menu(int btn_number,char sprite_number)
{
word x_pos;
word y_pos;
word menu_x_pos;
word menu_y_pos;
byte color;
Buttons_Pool[btn_number].Icon=sprite_number;
menu_y_pos=Buttons_Pool[btn_number].Y_offset;
menu_x_pos=Buttons_Pool[btn_number].X_offset;
if (Buttons_Pool[btn_number].Shape != BUTTON_SHAPE_TRIANGLE_BOTTOM_RIGHT)
{
menu_y_pos+=1;
menu_x_pos+=1;
}
for (y_pos=0;y_pos<MENU_SPRITE_HEIGHT;y_pos++)
for (x_pos=0;x_pos<MENU_SPRITE_WIDTH;x_pos++)
{
color=Gfx->Menu_sprite[sprite_number][y_pos][x_pos];
Pixel_in_menu_and_skin(MENUBAR_TOOLS, menu_x_pos+x_pos, menu_y_pos+y_pos, color);
}
if (Menu_is_visible && Menu_bars[MENUBAR_TOOLS].Visible)
Update_rect(Menu_factor_X*(Buttons_Pool[btn_number].X_offset+1),
(Buttons_Pool[btn_number].Y_offset+1+Menu_bars[MENUBAR_TOOLS].Top)*Menu_factor_Y+Menu_Y,
MENU_SPRITE_WIDTH*Menu_factor_X,MENU_SPRITE_HEIGHT*Menu_factor_Y);
if (Buttons_Pool[btn_number].Shape == BUTTON_SHAPE_TRIANGLE_TOP_LEFT)
Buttons_Pool[btn_number+1].Icon=sprite_number;
else if (Buttons_Pool[btn_number].Shape == BUTTON_SHAPE_TRIANGLE_BOTTOM_RIGHT)
Buttons_Pool[btn_number-1].Icon=sprite_number;
}
// -- Redessiner la forme du pinceau dans le menu --
void Display_paintbrush_in_menu(void)
{
short x_pos,y_pos;
short start_x;
short menu_x_pos,menu_y_pos;
short menu_start_x;
byte color;
switch (Paintbrush_shape)
switch(Paintbrush_shape)
{
case PAINTBRUSH_SHAPE_COLOR_BRUSH : // Brush en couleur
case PAINTBRUSH_SHAPE_MONO_BRUSH : // Brush monochrome
for (menu_y_pos=2,y_pos=0;y_pos<MENU_SPRITE_HEIGHT;menu_y_pos++,y_pos++)
for (menu_x_pos=1,x_pos=0;x_pos<MENU_SPRITE_WIDTH;menu_x_pos++,x_pos++)
{
color=Gfx->Menu_sprite[4][y_pos][x_pos];
Pixel_in_menu_and_skin(MENUBAR_TOOLS, menu_x_pos, menu_y_pos, color);
}
case PAINTBRUSH_SHAPE_COLOR_BRUSH:
Display_sprite_in_menu(BUTTON_PAINTBRUSHES, MENU_SPRITE_COLOR_BRUSH);
break;
case PAINTBRUSH_SHAPE_MONO_BRUSH:
Display_sprite_in_menu(BUTTON_PAINTBRUSHES, MENU_SPRITE_MONO_BRUSH);
break;
default:
Display_sprite_in_menu(BUTTON_PAINTBRUSHES, -1);
break;
default : // Pinceau
// On efface le pinceau précédent
for (menu_y_pos=2,y_pos=0;y_pos<MENU_SPRITE_HEIGHT;menu_y_pos++,y_pos++)
for (menu_x_pos=1,x_pos=0;x_pos<MENU_SPRITE_WIDTH;menu_x_pos++,x_pos++)
{
Pixel_in_menu_and_skin(MENUBAR_TOOLS, menu_x_pos, menu_y_pos, MC_Light);
}
// On affiche le nouveau
menu_start_x=8-Paintbrush_offset_X;
if (menu_start_x<1)
{
start_x=Paintbrush_offset_X-7;
menu_start_x=1;
}
else
start_x=0;
menu_y_pos=9-Paintbrush_offset_Y;
if (menu_y_pos<2)
{
y_pos=Paintbrush_offset_Y-7;
menu_y_pos=2;
}
else
y_pos=0;
for (;((y_pos<Paintbrush_height) && (menu_y_pos<16));menu_y_pos++,y_pos++)
for (menu_x_pos=menu_start_x,x_pos=start_x;((x_pos<Paintbrush_width) && (menu_x_pos<15));menu_x_pos++,x_pos++)
{
color=(Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)+x_pos])?MC_Black:MC_Light;
Pixel_in_menu_and_skin(MENUBAR_TOOLS, menu_x_pos, menu_y_pos, color);
}
}
if (Menu_is_visible && Menu_bars[MENUBAR_TOOLS].Visible)
Update_rect(0,Menu_Y + Menu_bars[MENUBAR_TOOLS].Top*Menu_factor_Y,MENU_SPRITE_WIDTH*Menu_factor_X+3,MENU_SPRITE_HEIGHT*Menu_factor_Y+3);
Draw_menu_button(BUTTON_PAINTBRUSHES,BUTTON_RELEASED);
}
// -- Dessiner un pinceau prédéfini dans la fenêtre --
@ -1278,6 +1226,8 @@ void Display_paintbrush_in_window(word x,word y,int number)
int y_size;
word origin_x;
word origin_y;
word width;
word height;
x_size=Menu_factor_X/Pixel_height;
if (x_size<1)
@ -1286,18 +1236,22 @@ void Display_paintbrush_in_window(word x,word y,int number)
if (y_size<1)
y_size=1;
origin_x = (x + 8)*Menu_factor_X - (Gfx->Preset_paintbrush_offset_X[number])*x_size+Window_pos_X;
origin_y = (y + 8)*Menu_factor_Y - (Gfx->Preset_paintbrush_offset_Y[number])*y_size+Window_pos_Y;
width=Min(Paintbrush[number].Width,PAINTBRUSH_WIDTH);
height=Min(Paintbrush[number].Height,PAINTBRUSH_WIDTH);
origin_x = (x + 8)*Menu_factor_X - (width/2)*x_size+Window_pos_X;
origin_y = (y + 8)*Menu_factor_Y - (height/2)*y_size+Window_pos_Y;
for (window_y_pos=0,y_pos=0; y_pos<Gfx->Preset_paintbrush_height[number]; window_y_pos++,y_pos++)
for (window_x_pos=0,x_pos=0; x_pos<Gfx->Preset_paintbrush_width[number]; window_x_pos++,x_pos++)
Block(origin_x+window_x_pos*x_size,origin_y+window_y_pos*y_size,x_size,y_size,(Gfx->Paintbrush_sprite[number][y_pos][x_pos])?MC_Black:MC_Light);
for (window_y_pos=0,y_pos=0; y_pos<height; window_y_pos++,y_pos++)
for (window_x_pos=0,x_pos=0; x_pos<width; window_x_pos++,x_pos++)
if (Paintbrush[number].Sprite[y_pos][x_pos])
Block(origin_x+window_x_pos*x_size,origin_y+window_y_pos*y_size,x_size,y_size,MC_Black);
// On n'utilise pas Pixel_in_window() car on ne dessine pas
// forcément avec la même taille de pixel.
Update_rect( ToWinX(origin_x), ToWinY(origin_y),
ToWinL(Gfx->Preset_paintbrush_width[number]),
ToWinH(Gfx->Preset_paintbrush_height[number])
ToWinL(Paintbrush[number].Width),
ToWinH(Paintbrush[number].Height)
);
}
@ -1553,6 +1507,7 @@ void Compute_paintbrush_coordinates(void)
{
// Operations that don't implement it
case OPERATION_LINE:
case OPERATION_ROTATE_BRUSH:
Snap_axis=0;
break;
// Operations that implement it
@ -1857,7 +1812,36 @@ void Change_magnifier_factor(byte factor_index, byte point_at_mouse)
Compute_paintbrush_coordinates();
}
void Copy_view_to_spare(void)
{
// Don't do anything if the pictures have different dimensions
if (Main_image_width!=Spare_image_width || Main_image_height!=Spare_image_height)
return;
// Copie des décalages de la fenêtre principale (non zoomée) de l'image
Spare_offset_X=Main_offset_X;
Spare_offset_Y=Main_offset_Y;
// Copie du booléen "Mode loupe" de l'image
Spare_magnifier_mode=Main_magnifier_mode;
// Copie du facteur de zoom du brouillon
Spare_magnifier_factor=Main_magnifier_factor;
// Copie des dimensions de la fenêtre de zoom
Spare_magnifier_width=Main_magnifier_width;
Spare_magnifier_height=Main_magnifier_height;
// Copie des décalages de la fenêtre de zoom
Spare_magnifier_offset_X=Main_magnifier_offset_X;
Spare_magnifier_offset_Y=Main_magnifier_offset_Y;
// Copie des données du split du zoom
Spare_separator_position=Main_separator_position;
Spare_X_zoom=Main_X_zoom;
Spare_separator_proportion=Main_separator_proportion;
}
// -- Afficher la barre de séparation entre les parties zoomées ou non en
// mode Loupe --
@ -2629,7 +2613,7 @@ void Display_all_screen(void)
byte Best_color(byte r,byte g,byte b)
{
short col;
int col;
int delta_r,delta_g,delta_b;
int dist;
int best_dist=0x7FFFFFFF;
@ -2663,7 +2647,7 @@ byte Best_color(byte r,byte g,byte b)
byte Best_color_nonexcluded(byte red,byte green,byte blue)
{
short col;
int col;
int delta_r,delta_g,delta_b;
int dist;
int best_dist=0x7FFFFFFF;
@ -2692,65 +2676,50 @@ byte Best_color_nonexcluded(byte red,byte green,byte blue)
return best_color;
}
void Compute_4_best_colors_for_1_menu_color
(byte red, byte green, byte blue, T_Components * palette, byte * table)
byte Best_color_perceptual(byte r,byte g,byte b)
{
short col;
int delta_r,delta_g,delta_b;
int dist;
int best_dist[4]={0x7FFFFFFF,0x7FFFFFFF,0x7FFFFFFF,0x7FFFFFFF};
int col;
float best_diff=255.0*1.56905;
byte best_color=0;
float target_bri;
float bri;
float diff_b, diff_c, diff;
// Similar to Perceptual_lightness();
target_bri = sqrt(0.26*r*0.26*r + 0.55*g*0.55*g + 0.19*b*0.19*b);
for (col=0; col<256; col++)
{
delta_r=(int)palette[col].R-red;
delta_g=(int)palette[col].G-green;
delta_b=(int)palette[col].B-blue;
if (Exclude_color[col])
continue;
dist=(delta_r*delta_r*30)+(delta_g*delta_g*59)+(delta_b*delta_b*11);
diff_c = sqrt(
(0.26*(Main_palette[col].R-r))*
(0.26*(Main_palette[col].R-r))+
(0.55*(Main_palette[col].G-g))*
(0.55*(Main_palette[col].G-g))+
(0.19*(Main_palette[col].B-b))*
(0.19*(Main_palette[col].B-b)));
// Exact match
if (diff_c==0)
return col;
if (dist<best_dist[0])
bri = sqrt(0.26*Main_palette[col].R*0.26*Main_palette[col].R + 0.55*Main_palette[col].G*0.55*Main_palette[col].G + 0.19*Main_palette[col].B*0.19*Main_palette[col].B);
diff_b = abs(target_bri-bri);
diff=0.25*(diff_b-diff_c)+diff_c;
if (diff<best_diff)
{
best_dist[3]=best_dist[2];
best_dist[2]=best_dist[1];
best_dist[1]=best_dist[0];
best_dist[0]=dist;
table[3]=table[2];
table[2]=table[1];
table[1]=table[0];
table[0]=col;
}
else
{
if (dist<best_dist[1])
{
best_dist[3]=best_dist[2];
best_dist[2]=best_dist[1];
best_dist[1]=dist;
table[3]=table[2];
table[2]=table[1];
table[1]=col;
}
else
{
if (dist<best_dist[2])
{
best_dist[3]=best_dist[2];
best_dist[2]=dist;
table[3]=table[2];
table[2]=col;
}
else
if (dist<best_dist[3])
{
best_dist[3]=dist;
table[3]=col;
}
}
}
best_diff=diff;
best_color=col;
}
}
}
return best_color;
}
byte Old_black;
@ -2835,11 +2804,32 @@ void Remap_screen_after_menu_colors_change(void)
}
int Same_color(T_Components * palette, byte c1, byte c2)
{
if (palette[c1].R==palette[c2].R &&
palette[c1].G==palette[c2].G &&
palette[c1].B==palette[c2].B)
return 1;
return 0;
}
void Compute_optimal_menu_colors(T_Components * palette)
{
byte table[4];
int i;
byte l[256];
byte s[256];
byte h;
int max_l = -1, min_l = 256;
int low_l, hi_l;
int delta_low = 999999;
int delta_high = 999999;
const int tolerence=16;
const T_Components cpc_colors[4] = {
{ 0, 0, 0},
{ 0, 0,128}, // Dark blue
{128,128,128}, // Grey
{255,255,255}
};
Old_black =MC_Black;
Old_dark = MC_Dark;
@ -2847,62 +2837,208 @@ void Compute_optimal_menu_colors(T_Components * palette)
Old_white = MC_White;
Old_trans = MC_Trans;
// Recherche du noir
Compute_4_best_colors_for_1_menu_color
(Gfx->Default_palette[Gfx->Color[0]].R, Gfx->Default_palette[Gfx->Color[0]].G, Gfx->Default_palette[Gfx->Color[0]].B,palette,table);
MC_Black=table[0];
// Recherche du blanc
Compute_4_best_colors_for_1_menu_color
(Gfx->Default_palette[Gfx->Color[3]].R, Gfx->Default_palette[Gfx->Color[3]].G, Gfx->Default_palette[Gfx->Color[3]].B,palette,table);
if (MC_Black!=table[0])
MC_White=table[0];
else
MC_White=table[1];
// Recherche du gris clair
Compute_4_best_colors_for_1_menu_color
(Gfx->Default_palette[Gfx->Color[2]].R, Gfx->Default_palette[Gfx->Color[2]].G, Gfx->Default_palette[Gfx->Color[2]].B,palette,table);
if ( (MC_Black!=table[0]) && (MC_White!=table[0]) )
MC_Light=table[0];
else
// First method:
// If all close matches for the ideal colors exist, pick them.
for (i=255; i>=0; i--)
{
if ( (MC_Black!=table[1]) && (MC_White!=table[1]) )
MC_Light=table[1];
else
MC_Light=table[2];
}
// Recherche du gris foncé
Compute_4_best_colors_for_1_menu_color
(Gfx->Default_palette[Gfx->Color[1]].R, Gfx->Default_palette[Gfx->Color[1]].G, Gfx->Default_palette[Gfx->Color[1]].B,palette,table);
if ( (MC_Black!=table[0]) && (MC_White!=table[0]) && (MC_Light!=table[0]) )
MC_Dark=table[0];
else
{
if ( (MC_Black!=table[1]) && (MC_White!=table[1]) && (MC_Light!=table[1]) )
MC_Dark=table[1];
else
if (Round_palette_component(palette[i].R)/tolerence==Gfx->Default_palette[Gfx->Color[3]].R/tolerence
&& Round_palette_component(palette[i].G)/tolerence==Gfx->Default_palette[Gfx->Color[3]].G/tolerence
&& Round_palette_component(palette[i].B)/tolerence==Gfx->Default_palette[Gfx->Color[3]].B/tolerence)
{
if ( (MC_Black!=table[2]) && (MC_White!=table[2]) && (MC_Light!=table[2]) )
MC_Dark=table[2];
else
MC_Dark=table[3];
MC_White=i;
for (i=255; i>=0; i--)
{
if (Round_palette_component(palette[i].R)/tolerence==Gfx->Default_palette[Gfx->Color[2]].R/tolerence
&& Round_palette_component(palette[i].G)/tolerence==Gfx->Default_palette[Gfx->Color[2]].G/tolerence
&& Round_palette_component(palette[i].B)/tolerence==Gfx->Default_palette[Gfx->Color[2]].B/tolerence)
{
MC_Light=i;
for (i=255; i>=0; i--)
{
if (Round_palette_component(palette[i].R)/tolerence==Gfx->Default_palette[Gfx->Color[1]].R/tolerence
&& Round_palette_component(palette[i].G)/tolerence==Gfx->Default_palette[Gfx->Color[1]].G/tolerence
&& Round_palette_component(palette[i].B)/tolerence==Gfx->Default_palette[Gfx->Color[1]].B/tolerence)
{
MC_Dark=i;
for (i=255; i>=0; i--)
{
if (Round_palette_component(palette[i].R)/tolerence==Gfx->Default_palette[Gfx->Color[0]].R/tolerence
&& Round_palette_component(palette[i].G)/tolerence==Gfx->Default_palette[Gfx->Color[0]].G/tolerence
&& Round_palette_component(palette[i].B)/tolerence==Gfx->Default_palette[Gfx->Color[0]].B/tolerence)
{
MC_Black=i;
// On cherche une couleur de transparence différente des 4 autres.
for (MC_Trans=0; ((MC_Trans==MC_Black) || (MC_Trans==MC_Dark) ||
(MC_Trans==MC_Light) || (MC_Trans==MC_White)); MC_Trans++);
// Easy case
MC_OnBlack=MC_Dark;
MC_Window=MC_Light;
MC_Lighter=MC_White;
MC_Darker=MC_Dark;
Remap_menu_sprites();
return;
}
}
}
}
}
}
}
}
// C'est peu probable mais il est possible que MC_Light soit plus foncée que
// MC_Dark. Dans ce cas, on les inverse.
if ( ((palette[MC_Light].R*30)+(palette[MC_Light].G*59)+(palette[MC_Light].B*11)) <
((palette[MC_Dark].R*30)+(palette[MC_Dark].G*59)+(palette[MC_Dark].B*11)) )
// Second method: For CPC 27-color modes only
// Try to find colors that just work
if (Get_palette_RGB_scale()==3)
for (i=255; i>=0; i--)
{
SWAP_BYTES(MC_Light, MC_Dark);
if (Round_palette_component(palette[i].R)/tolerence==cpc_colors[3].R/tolerence
&& Round_palette_component(palette[i].G)/tolerence==cpc_colors[3].G/tolerence
&& Round_palette_component(palette[i].B)/tolerence==cpc_colors[3].B/tolerence)
{
MC_White=i;
for (i=255; i>=0; i--)
{
if (Round_palette_component(palette[i].R)/tolerence==cpc_colors[2].R/tolerence
&& Round_palette_component(palette[i].G)/tolerence==cpc_colors[2].G/tolerence
&& Round_palette_component(palette[i].B)/tolerence==cpc_colors[2].B/tolerence)
{
MC_Light=i;
for (i=255; i>=0; i--)
{
if (Round_palette_component(palette[i].R)/tolerence==cpc_colors[1].R/tolerence
&& Round_palette_component(palette[i].G)/tolerence==cpc_colors[1].G/tolerence
&& Round_palette_component(palette[i].B)/tolerence==cpc_colors[1].B/tolerence)
{
MC_Dark=i;
for (i=255; i>=0; i--)
{
if (Round_palette_component(palette[i].R)/tolerence==cpc_colors[0].R/tolerence
&& Round_palette_component(palette[i].G)/tolerence==cpc_colors[0].G/tolerence
&& Round_palette_component(palette[i].B)/tolerence==cpc_colors[0].B/tolerence)
{
MC_Black=i;
// On cherche une couleur de transparence différente des 4 autres.
for (MC_Trans=0; ((MC_Trans==MC_Black) || (MC_Trans==MC_Dark) ||
(MC_Trans==MC_Light) || (MC_Trans==MC_White)); MC_Trans++);
// Easy case
MC_OnBlack=MC_Dark;
MC_Window=MC_Light;
MC_Lighter=MC_White;
MC_Darker=MC_Dark;
Remap_menu_sprites();
return;
}
}
}
}
}
}
}
}
// Third method:
// Compute luminance for whole palette
// Take the darkest as black, the brightest white
for(i = 0; i < 256; i++)
{
RGB_to_HSL(palette[i].R, palette[i].G, palette[i].B, &h, &s[i], &l[i]);
// Another formula for lightness, in 0-255 range
//l[i]=Perceptual_lightness(&palette[i])/4062/255;
if (l[i] > max_l)
{
max_l = l[i];
MC_White = i;
}
}
for(i = 0; i < 256; i++)
{
if (l[i] < min_l && i!=MC_White)
{
min_l = l[i];
MC_Black = i;
}
}
// Alter the S values according to the L range - this is for the future
// comparisons, so that highly variable saturation doesn't weigh
// too heavily when the the lightness is in a narrow range.
for(i = 0; i < 256; i++)
{
s[i]=s[i]*(max_l-min_l)/255;
}
for(i = 0; i < 256; i++)
{
// Adjust (reduce) perceived saturation at both ends of L spectrum
if (l[i]>192)
s[i]=s[i]*(255-l[i])/64;
else if (l[i]<64)
s[i]=s[i]*l[i]/64;
}
// Find color nearest to min+2(max-min)/3
// but at the same time we try to minimize the saturation so that the menu
// still looks grey
hi_l = min_l + 2*(max_l - min_l)/3;
for (i = 0; i < 256; i++)
{
if ( abs(l[i] - hi_l) + s[i]/2 < delta_high && i!=MC_White && i!=MC_Black)
{
delta_high = abs(l[i] - hi_l) + s[i]/2;
MC_Light = i;
}
}
// Target "Dark color" is 2/3 between Light and Black
low_l = ((int)l[MC_Light]*2+l[MC_Black])/3;
for (i = 0; i < 256; i++)
{
if ( abs((int)l[i] - low_l) + s[i]/6 < delta_low && i!=MC_White && i!=MC_Black && i!=MC_Light)
{
delta_low = abs((int)l[i] - low_l)+ s[i]/6;
MC_Dark = i;
}
}
//if (l[MC_Light]<l[MC_Dark])
//{
// // Not sure if that can happen, but just in case:
// SWAP_BYTES(MC_Light, MC_Dark)
//}
// Si deux des couleurs choisies ont le même index, c'est destructif car
// on fait ensuite un remap de l'image. Donc on évite ce problème (un
// peu brutalement)
// On commence par déplacer les gris, comme ça on a plus de chances de garder au moins
// le blanc et le noir
//while (MC_Dark == MC_Light || MC_Dark == MC_White || MC_Black == MC_Dark || Same_color(palette, MC_Dark, MC_White)) MC_Dark--;
//while (MC_White == MC_Light || MC_Dark == MC_Light || MC_Black == MC_Light || Same_color(palette, MC_Light, MC_Black)) MC_Light--;
//while (MC_White == MC_Light || MC_Dark == MC_White || MC_Black == MC_White) MC_White--;
// On cherche une couleur de transparence différente des 4 autres.
for (MC_Trans=0; ((MC_Trans==MC_Black) || (MC_Trans==MC_Dark) ||
(MC_Trans==MC_Light) || (MC_Trans==MC_White)); MC_Trans++);
if (Same_color(palette, MC_Black, MC_Dark))
MC_OnBlack=MC_Light;
else
MC_OnBlack=MC_Dark;
if (Same_color(palette, MC_White, MC_Light))
{
MC_Window=MC_Dark;
MC_Darker=MC_Black;
}
else
{
MC_Window=MC_Light;
MC_Darker=MC_Dark;
}
MC_Lighter=MC_White;
Remap_menu_sprites();
}
@ -2923,18 +3059,20 @@ void Remap_menu_sprites()
for (i=0; i<CURSOR_SPRITE_WIDTH; i++)
Remap_pixel(&Gfx->Cursor_sprite[k][j][i]);
// Main menu bar
for (j=0; j<Menu_bars[MENUBAR_TOOLS].Height; j++)
for (i=0; i<Menu_bars[MENUBAR_TOOLS].Skin_width; i++)
Remap_pixel(&Gfx->Menu_block[j][i]);
for (k=0; k<3; k++)
for (j=0; j<Menu_bars[MENUBAR_TOOLS].Height; j++)
for (i=0; i<Menu_bars[MENUBAR_TOOLS].Skin_width; i++)
Remap_pixel(&Gfx->Menu_block[k][j][i]);
// Menu sprites
for (k=0; k<NB_MENU_SPRITES; k++)
for (j=0; j<MENU_SPRITE_HEIGHT; j++)
for (i=0; i<MENU_SPRITE_WIDTH; i++)
Remap_pixel(&Gfx->Menu_sprite[k][j][i]);
for (l=0; l<2; l++)
for (k=0; k<NB_MENU_SPRITES; k++)
for (j=0; j<MENU_SPRITE_HEIGHT; j++)
for (i=0; i<MENU_SPRITE_WIDTH; i++)
Remap_pixel(&Gfx->Menu_sprite[l][k][j][i]);
// Effects sprites
for (k=0; k<NB_EFFECTS_SPRITES; k++)
for (j=0; j<MENU_SPRITE_HEIGHT; j++)
for (i=0; i<MENU_SPRITE_WIDTH; i++)
for (j=0; j<EFFECT_SPRITE_HEIGHT; j++)
for (i=0; i<EFFECT_SPRITE_WIDTH; i++)
Remap_pixel(&Gfx->Effect_sprite[k][j][i]);
// Layers buttons
for (l=0; l<3; l++)
@ -2944,13 +3082,15 @@ void Remap_menu_sprites()
Remap_pixel(&Gfx->Layer_sprite[l][k][j][i]);
// Status bar
for (j=0; j<Menu_bars[MENUBAR_STATUS].Height; j++)
for (i=0; i<Menu_bars[MENUBAR_STATUS].Skin_width; i++)
Remap_pixel(&Gfx->Statusbar_block[j][i]);
for (k=0; k<3; k++)
for (j=0; j<Menu_bars[MENUBAR_STATUS].Height; j++)
for (i=0; i<Menu_bars[MENUBAR_STATUS].Skin_width; i++)
Remap_pixel(&Gfx->Statusbar_block[k][j][i]);
// Layer bar
for (j=0; j<Menu_bars[MENUBAR_LAYERS].Height; j++)
for (i=0; i<Menu_bars[MENUBAR_LAYERS].Skin_width; i++)
Remap_pixel(&Gfx->Layerbar_block[j][i]);
for (k=0; k<3; k++)
for (j=0; j<Menu_bars[MENUBAR_LAYERS].Height; j++)
for (i=0; i<Menu_bars[MENUBAR_LAYERS].Skin_width; i++)
Remap_pixel(&Gfx->Layerbar_block[k][j][i]);
// Help fonts
for (k=0; k<256; k++)

View File

@ -89,7 +89,7 @@ void Window_display_frame_in(word x_pos,word y_pos,word width,word height);
void Window_display_frame_out(word x_pos,word y_pos,word width,word height);
void Window_display_frame(word x_pos,word y_pos,word width,word height);
void Display_sprite_in_menu(int btn_number,int sprite_number);
void Display_sprite_in_menu(int btn_number,char sprite_number);
void Display_paintbrush_in_menu(void);
void Display_paintbrush_in_window(word x,word y,int number);
@ -99,6 +99,7 @@ void Window_display_icon_sprite(word x_pos,word y_pos,byte type);
byte Best_color(byte red,byte green,byte blue);
byte Best_color_nonexcluded(byte red,byte green,byte blue);
byte Best_color_perceptual(byte r,byte g,byte b);
void Horizontal_XOR_line_zoom(short x_pos, short y_pos, short width);
void Vertical_XOR_line_zoom(short x_pos, short y_pos, short height);
@ -108,4 +109,7 @@ void Change_magnifier_factor(byte factor_index, byte point_at_mouse);
/// Width of one layer button, in pixels before scaling
extern word Layer_button_width;
/// Copy viewport settings and offsets from the Main to the Spare.
void Copy_view_to_spare(void);
#endif