Please, need help for optimisation

BlitzMax Forums/BlitzMax Programming/Please, need help for optimisation

Hello :-)

Since i've not found any deluxepaint like program under linux, i'm trying to program one.
But i'm new to linux and i'm new to Bmax.
Can someone help me to optimise the code ? Because it's too slow to under a Pentium D925 with 2,5Go Ram.

This is the code i've done for now :

AppTitle = "delinux-paint"

#palettedefaut

DefData 0,0,0, 15,15,15, 31,31,31, 47,47,47, 63,63,63, 79,79,79, 95,95,95, 111,111,111
DefData 127,127,127, 143,143,143, 159,159,159, 175,175,175, 191,191,191, 207,207,207, 223,223,223, 239,239,239

DefData 15,0,0, 31,0,0, 47,0,0, 63,0,0, 79,0,0, 95,0,0, 111,0,0, 127,0,0
DefData 143,0,0, 159,0,0, 175,0,0, 191,0,0, 207,0,0, 223,0,0, 239,0,0, 255,0,0

DefData 255,15,0, 255,31,0, 255,47,0, 255,63,0, 255,79,0, 255,95,0, 255,111,0, 255,127,0
DefData 255,143,0, 255,159,0, 255,175,0, 255,191,0, 255,207,0, 255,223,0, 255,239,0, 255,255,0

DefData 239,255,0, 223,255,0, 207,255,0, 191,255,0, 175,255,0, 159,255,0, 143,255,0, 127,255,0
DefData 111,255,0, 95,255,0, 79,255,0, 63,255,0, 47,255,0, 31,255,0, 15,255,0, 0,255,0

DefData 0,15,0, 0,31,0, 0,47,0, 0,63,0, 0,79,0, 0,95,0, 0,111,0, 0,127,0
DefData 0,143,0, 0,159,0, 0,175,0, 0,191,0, 0,207,0, 0,223,0, 0,239,0, 0,255,0

DefData 0,15,15, 0,31,31, 0,47,47, 0,63,63, 0,79,79, 0,95,95, 0,111,111, 0,127,127
DefData 0,143,143, 0,159,159, 0,175,175, 0,191,191, 0,207,207, 0,223,223, 0,239,239, 0,255,255

DefData 0,0,15, 0,0,31, 0,0,47, 0,0,63, 0,0,79, 0,0,95, 0,0,111, 0,0,127
DefData 0,0,143, 0,0,159, 0,0,175, 0,0,191, 0,0,207, 0,0,223, 0,0,239, 0,0,255

DefData 15,15,255, 31,31,255, 47,47,255, 63,63,255, 79,79,255, 95,95,255, 111,111,255, 127,127,255
DefData 143,143,255, 159,159,255, 175,175,255, 191,191,255, 207,207,255, 223,223,255, 239,239,255, 255,255,255

DefData 15,0,255, 31,0,255, 47,0,255, 63,0,255, 79,0,255, 95,0,255, 111,0,255, 127,0,255
DefData 143,0,255, 159,0,255, 175,0,255, 191,0,255, 207,0,255, 223,0,255, 239,0,255, 255,0,255

DefData 255,0,239, 255,0,223, 255,0,207, 255,0,191, 255,0,175, 255,0,159, 255,0,143, 255,0,127
DefData 255,0,111, 255,0,95, 255,0,79, 255,0,63, 255,0,47, 255,0,31, 255,0,15, 255,0,0

DefData 10,10,0, 20,20,0, 30,30,0, 40,40,0, 50,50,0 ,60,60,0 ,70,70,0, 80,80,0
DefData 90,90,0, 100,100,0, 110,110,0 ,120,120,0, 130,130,0, 140,140,0, 150,150,0, 160,160,0

DefData 10,20,30, 20,30,40, 30,40,50, 40,50,60, 50,60,70, 60,70,80, 70,80,90, 80,90,100
DefData 90,100,110, 100,110,120, 110,120,130, 120,130,140, 130,140,150, 150,160,170, 160,170,180, 170,180,190

DefData 15,50,50, 31,50,50, 47,50,50, 63,50,50, 79,50,50, 95,50,50, 111,50,50, 127,50,50
DefData 143,50,50, 159,50,50, 175,50,50, 191,50,50, 207,50,50, 223,50,50, 239,50,50, 255,50,50

DefData 255,15,100, 255,31,100, 255,47,100, 255,63,100, 255,79,100, 255,95,100, 255,111,100, 255,127,100
DefData 255,143,100, 255,159,100, 255,175,100, 255,191,100, 255,207,100, 255,223,100, 255,239,100, 255,255,100

DefData 239,255,150, 223,255,150, 207,255,150, 191,255,150, 175,255,150, 159,255,150, 143,255,150, 127,255,150
DefData 111,255,150, 95,255,150, 79,255,150, 63,255,150, 47,255,150, 31,255,150, 15,255,150, 0,255,150

DefData 0,255,0, 15,255,15, 31,255,31, 47,255,47, 63,255,63, 79,255,79, 95,255,95, 111,255,111
DefData 127,255,127, 143,255,143, 159,255,159, 175,255,175, 191,255,191, 207,255,207, 223,255,223, 255,255,255

#iconames
DefData "dots","draw","lines","curves","fill","airbrush","box","circle","oval","losange","select","text","grid","simmetry","zoom","colorpick","undo","clear"

x=0
y=0
width=800
height=600
If width<GadgetWidth(Desktop()) x=(GadgetWidth(Desktop())-800)/2 
If height<GadgetHeight(Desktop()) y=(GadgetHeight(Desktop())-600)/2 
Global window:TGadget = CreateWindow("Delinux-Paint",x,y,width,height,Null,WINDOW_MENU | WINDOW_TITLEBAR)

Global mymousex=0
Global mymousey=0
Global myclick=0
Global startclick=0
Global oldmousex=0
Global oldmousey=0
Global myzoom=1

Global windowflag=0

Global starting=1

If window
	file:TGadget=CreateMenu("File",1,WindowMenu(window))
		newfile:TGadget=CreateMenu("New Animation",101,file)
		CreateMenu("",0,file)
		loadimg:TGadget=CreateMenu("Load Image",102,file)
		saveimg:TGadget=CreateMenu("Save Image",103,file)
		saveimgas:TGadget=CreateMenu("Save Image As...",104,file)
		CreateMenu("",0,file)
		loadanim:TGadget=CreateMenu("Load Animation",105,file)
		saveanim:TGadget=CreateMenu("Save Animation",106,file)
		saveanimas:TGadget=CreateMenu("Save Animation As...",107,file)
		CreateMenu("",0,file)
		xit:TGadget=CreateMenu("Exit",199,file)
	edit:TGadget=CreateMenu("Edit",2,WindowMenu(window))
		undo:TGadget=CreateMenu("Undo",201,edit)
		redo:TGadget=CreateMenu("Redo",202,edit)
		CreateMenu("",0,edit)
		cutframe:TGadget=CreateMenu("Cut Frame",203,edit)
		copyframe:TGadget=CreateMenu("Copy Frame",204,edit)
		pasteframe:TGadget=CreateMenu("Paste Frame",205,edit)
		insertframe:TGadget=CreateMenu("Insert Frame",206,edit)
	brush:TGadget=CreateMenu("Brush",3,WindowMenu(window))
	mode:TGadget=CreateMenu("Mode",4,WindowMenu(window))
		paint:TGadget=CreateMenu("Paint",401,mode)
		brighten:TGadget=CreateMenu("Brighten",402,mode)
		darken:TGadget=CreateMenu("Darken",403,mode)
		CheckMenu paint
	frame:TGadget=CreateMenu("Frame",5,WindowMenu(window))
	animation:TGadget=CreateMenu("Animation",6,WindowMenu(window))
	colors:TGadget=CreateMenu("Colors",7,WindowMenu(window))
	options:TGadget=CreateMenu("Options",8,WindowMenu(window))
	help:TGadget=CreateMenu("Help",9,WindowMenu(window))
	UpdateWindowMenu(window)

	Global canvas:TGadget=CreateCanvas(130,10,370,370,window)
	Global canvash:TGadget=CreateSlider(130,380,370,20,window,SLIDER_HORIZONTAL)
	Global canvasv:TGadget=CreateSlider(500,10,20,370,window,SLIDER_VERTICAL)

	Global mypal:TGadget=CreateCanvas(530,10,256,256,window)


	' ImgBuffer[0] => Buffer where the program works
	' ImgBuffer[1] to [10] => Buffers for undo function
	Global ImgBuffer:TPixmap[11]
	Global ImgScrollX:Int=0
	Global ImgScrollY:Int=0
	For i=0 To 10	
		ImgBuffer[i]=CreatePixmap(640,480,PF_RGBA8888)
		ClearPixels ImgBuffer[i],$00000000
	Next
	Global myundo=0

	Global ink:Int[256*3]
	palettetype=1 ' 1=defaut, 2= greys
	
	If palettetype=2
		For i=0 To 255
			For j=0 To 2
				ink[i+(256*j)]=i
			Next
		Next
	Else
		RestoreData palettedefaut
		For i=0 To 255
			For j=0 To 2
				ReadData ink[i+(256*j)]
			Next
		Next	
	EndIf
	
	updatemypal()


Function updatemypal()
	SetGraphics CanvasGraphics(mypal)
	Local fi:Int
	Local fj:Int
	Local fc1:Int
	Local fc2:Int
	Local fc3:Int
	For fj=0 To 15
		For fi=0 To  15
			fc1=ink[fi+(fj*16)+(256*0)]
			fc2=ink[fi+(fj*16)+(256*1)]
			fc3=ink[fi+(fj*16)+(256*2)]
			SetColor fc1,fc2,fc3
			DrawRect fi*16,fj*16,16,16
			SetColor 0,0,0
			If fi+(fj*16)=pen Or fi+(fj*16)=paper Then SetColor (fc1+128) Mod 256,(fc2+128) Mod 256,(fc3+128) Mod 256
			DrawLine (fi*16),(fj*16),(fi*16)+15,(fj*16)
			DrawLine (fi*16)+15,(fj*16),(fi*16)+15,(fj*16)+15
			DrawLine (fi*16)+15,(fj*16)+15,(fi*16),(fj*16)+15
			DrawLine (fi*16),(fj*16)+15,(fi*16),(fj*16)
		Next
	Next
	Flip
EndFunction

	Global paper=0
	Global pen=255
	Global penwidth=1

	Global Icones:Tgadget[18]
	RestoreData iconames
	For j=0 To 8
		For i=0 To 1
			ReadData myname$
			Icones[i+(j*2)]=CreateButton(myname$,5+(i*60),10+(j*40),60,40,window)
		Next
	Next
	
	Global mytool=1

	updatetool()

Function updatetool()
	Local fi:Int
	For fi=0 To 17
		SetGadgetColor Icones[fi],80,80,80
		RedrawGadget  Icones[fi]
	Next
		SetGadgetColor Icones[mytool-1],255,255,255
		RedrawGadget  Icones[mytool-1]
EndFunction

	CreateTimer 60

	AddHook EmitEventHook, paintfnc

Function Dot(buf:TPixmap,X1:Int,Y1:Int,mcol:Int)
	X1=X1+ImgScrollX
	Y1=Y1+ImgScrollY
	If X1<0 Then X1=0
	If Y1<0 Then Y1=0
	If X1>=PixmapWidth(buf) Then X1=PixmapWidth(buf)-1
	If Y1>=PixmapHeight(buf) Then Y1=PixmapHeight(buf)-1
	buf.WritePixel(X1,Y1,ink[mcol+(256*0)]+(256*ink[mcol+(256*1)])+(256*256*ink[mcol+(256*2)]))
End Function

Function Line(buf:TPixmap,X1:Int,Y1:Int,X2:Int,Y2:Int,mcol:Int)
	'Draws a line of individual pixels from X1,Y1 to X2,Y2 at any angle
 	Local Steep:Int=Abs(Y2-Y1) > Abs(X2-X1)			'Boolean
	If Steep
		Local Temp:Int=X1; X1=Y1; Y1=Temp		'Swap X1,Y1
		Temp=X2; X2=Y2; Y2=Temp		'Swap X2,Y2
	EndIf
	Local DeltaX:Int=Abs(X2-X1)		'X Difference
	Local DeltaY:Int=Abs(Y2-Y1)		'Y Difference
	Local Error:Int=0		'Overflow counter
	Local DeltaError:Int=DeltaY		'Counter adder
	Local fX:Int=X1		'Start at X1,Y1
	Local fY:Int=Y1		
	Local XStep:Int
	Local YStep:Int
	If X1<X2 Then XStep=1 Else XStep=-1	'Direction
	If Y1<Y2 Then YStep=1 Else YStep=-1	'Direction
	If Steep Then dot buf,fY,fX,mcol Else dot buf,fX,fY,mcol		'Draw
	While fX<>X2
		fX:+XStep		'Move in X
		Error:+DeltaError		'Add to counter
		If (Error Shl 1)>DeltaX		'Would it overflow?
			fY:+YStep		'Move in Y
			Error=Error-DeltaX		'Overflow/wrap the counter
		EndIf
	If Steep Then dot buf,fY,fX,mcol Else dot buf,fX,fY,mcol		'Draw
	Wend
End Function

Function paintfnc:Object( id:Int, data:Object, context:Object)
	Local x1:Int,y1:Int,x2:Int,y2:Int
	Local ev:TEvent = TEvent(data)
	Local abcd
	If Not ev Then Return data
	If ev.ID = EVENT_TIMERTICK Then
		RedrawGadget mypal
		RedrawGadget canvas
		'copy a portion of pixmap buffer into the canvas
		x1=ImgScrollX
		y1=ImgScrollY
		x2=x1+369
		y2=y1+369
		If x2>=PixmapWidth(ImgBuffer[0]) Then x2=PixmapWidth(ImgBuffer[0])-1
		If y2>=PixmapHeight(ImgBuffer[0]) Then y2=PixmapHeight(ImgBuffer[0])-1
		DrawPixmap ImgBuffer[0],0,0
	ElseIf ev.ID = EVENT_GADGETPAINT Then
		updatemypal()
		SetGraphics CanvasGraphics( canvas)
		SetOrigin 0,0
		If myclick=1 Or starting=1
			starting=0
			SetLineWidth penwidth
			Select mytool
				Case 1
					dot ImgBuffer[0],mymousex,mymousey,pen
				Case 2
					If startclick=1
						dot ImgBuffer[0],mymousex,mymousey,pen
						oldmousex=mymousex
						oldmousey=mymousey
						startclick=0
					 Else 
						line ImgBuffer[0],oldmousex,oldmousey,mymousex,mymousey,pen			
						oldmousex=mymousex
						oldmousey=mymousey
					EndIf
				Case 18
					Cls
					Flip
					mytool=1
					updatetool()
			End Select
			Flip
		EndIf
		Return Null
	EndIf
	Return data
EndFunction

Function ShowGetResolution()
Local fx=0
Local fy=0
Local fwidth=400
Local fheight=300
If fwidth<GadgetWidth(window) fx=(GadgetWidth(window)-400)/2 
If fheight<GadgetHeight(window) fy=(GadgetHeight(window)-300)/2 
Global tempwindow:TGadget = CreateWindow("New Animation",fx,fy,fwidth,fheight,window,WINDOW_TOOL | WINDOW_CLIENTCOORDS)
EndFunction

	Repeat
		Select WaitEvent()
			Case EVENT_WINDOWCLOSE
				FreeGadget canvas
				FreeGadget mypal
				End
			Case EVENT_APPTERMINATE
				End
			Case EVENT_MENUACTION
				Select EventData()
					Case 101
						If windowflag=0
							windowflag=1
							'ShowGetResolution()
						EndIf
					Case 199
						FreeGadget canvas
						FreeGadget mypal
						End
				End Select
			Case EVENT_MOUSEMOVE
				If EventSource()=canvas
					mymousex=EventX()
					mymousey=EventY()
					RedrawGadget canvas
				EndIf
			Case EVENT_MOUSEDOWN
				If EventSource()=canvas
					If myclick=0 Then startclick=1
					myclick=1
					RedrawGadget canvas
				EndIf
			Case EVENT_MOUSEUP
				If EventSource()=canvas
					myclick=0
					startclick=0
					RedrawGadget canvas
				EndIf
			Case EVENT_MOUSEENTER
				SetPointer POINTER_CROSS
			Case EVENT_MOUSELEAVE
				SetPointer POINTER_DEFAULT
			Case EVENT_GADGETACTION
				For i=0 To 17
					If EventSource()=Icones[i]
						mytool=i+1
						updatetool()
					EndIf
				Next
		End Select
	Forever

EndIf


End

You should post it in the forum in a codebox or something: http://blitzbasic.com/faq/faq_entry.php?id=2

Thanks Azathoth, this is a long time i search to do that.
So, does someone see the problem i have ?
It is very slow.

The Gimp does pixel-based painting, doesn't it ?

You might even find it already installed on your Linux distro. (it appears under Graphics, in my taskbar menu).

In your Dot function I'm sure you can change this:
If X1<0 Then X1=0
If X1>=PixmapWidth(buf) Then X1=PixmapWidth(buf)-1

into this
X1 = Min(Max(X1, 0), PixmapWidth(buf) - 1)


As Azathoth says though, stick the code into a {codebox}{/codebox} (replace the curly brackets with square ones).

:o)

Thanks Brucey :-)
(I'm running Bmax under Mandriva Spring 2007)

The main problems appear to be the events.

Your drawing code is wrapped up inside the paint function.
You might find it will work better if you call the drawing functions as part of your mouse move/down/up code, rather than forcing a redraw of the gadget.
The time before the gadget is actually redrawn is undetermined, especially since you appear to be updating it 60 times a second anyways.

You could always only refresh the canvas when it needs to be refreshed (ie. after you've changed the underlying pixmap in some way).

Also, drawing the pixmap every frame (instead of its Image), is slow.

Thanks Brucey

I will see what i can do

I've changed a lot of things and it works better now.
Is there a command to free the events queue ?
(i would like to free it when the menu is opened ?

AppTitle = "delinux-paint"

#palettedefaut

DefData 0,0,0, 15,15,15, 31,31,31, 47,47,47, 63,63,63, 79,79,79, 95,95,95, 111,111,111
DefData 127,127,127, 143,143,143, 159,159,159, 175,175,175, 191,191,191, 207,207,207, 223,223,223, 239,239,239

DefData 15,0,0, 31,0,0, 47,0,0, 63,0,0, 79,0,0, 95,0,0, 111,0,0, 127,0,0
DefData 143,0,0, 159,0,0, 175,0,0, 191,0,0, 207,0,0, 223,0,0, 239,0,0, 255,0,0

DefData 255,15,0, 255,31,0, 255,47,0, 255,63,0, 255,79,0, 255,95,0, 255,111,0, 255,127,0
DefData 255,143,0, 255,159,0, 255,175,0, 255,191,0, 255,207,0, 255,223,0, 255,239,0, 255,255,0

DefData 239,255,0, 223,255,0, 207,255,0, 191,255,0, 175,255,0, 159,255,0, 143,255,0, 127,255,0
DefData 111,255,0, 95,255,0, 79,255,0, 63,255,0, 47,255,0, 31,255,0, 15,255,0, 0,255,0

DefData 0,15,0, 0,31,0, 0,47,0, 0,63,0, 0,79,0, 0,95,0, 0,111,0, 0,127,0
DefData 0,143,0, 0,159,0, 0,175,0, 0,191,0, 0,207,0, 0,223,0, 0,239,0, 0,255,0

DefData 0,15,15, 0,31,31, 0,47,47, 0,63,63, 0,79,79, 0,95,95, 0,111,111, 0,127,127
DefData 0,143,143, 0,159,159, 0,175,175, 0,191,191, 0,207,207, 0,223,223, 0,239,239, 0,255,255

DefData 0,0,15, 0,0,31, 0,0,47, 0,0,63, 0,0,79, 0,0,95, 0,0,111, 0,0,127
DefData 0,0,143, 0,0,159, 0,0,175, 0,0,191, 0,0,207, 0,0,223, 0,0,239, 0,0,255

DefData 15,15,255, 31,31,255, 47,47,255, 63,63,255, 79,79,255, 95,95,255, 111,111,255, 127,127,255
DefData 143,143,255, 159,159,255, 175,175,255, 191,191,255, 207,207,255, 223,223,255, 239,239,255, 255,255,255

DefData 15,0,255, 31,0,255, 47,0,255, 63,0,255, 79,0,255, 95,0,255, 111,0,255, 127,0,255
DefData 143,0,255, 159,0,255, 175,0,255, 191,0,255, 207,0,255, 223,0,255, 239,0,255, 255,0,255

DefData 255,0,239, 255,0,223, 255,0,207, 255,0,191, 255,0,175, 255,0,159, 255,0,143, 255,0,127
DefData 255,0,111, 255,0,95, 255,0,79, 255,0,63, 255,0,47, 255,0,31, 255,0,15, 255,0,0

DefData 10,10,0, 20,20,0, 30,30,0, 40,40,0, 50,50,0 ,60,60,0 ,70,70,0, 80,80,0
DefData 90,90,0, 100,100,0, 110,110,0 ,120,120,0, 130,130,0, 140,140,0, 150,150,0, 160,160,0

DefData 10,20,30, 20,30,40, 30,40,50, 40,50,60, 50,60,70, 60,70,80, 70,80,90, 80,90,100
DefData 90,100,110, 100,110,120, 110,120,130, 120,130,140, 130,140,150, 150,160,170, 160,170,180, 170,180,190

DefData 15,50,50, 31,50,50, 47,50,50, 63,50,50, 79,50,50, 95,50,50, 111,50,50, 127,50,50
DefData 143,50,50, 159,50,50, 175,50,50, 191,50,50, 207,50,50, 223,50,50, 239,50,50, 255,50,50

DefData 255,15,100, 255,31,100, 255,47,100, 255,63,100, 255,79,100, 255,95,100, 255,111,100, 255,127,100
DefData 255,143,100, 255,159,100, 255,175,100, 255,191,100, 255,207,100, 255,223,100, 255,239,100, 255,255,100

DefData 239,255,150, 223,255,150, 207,255,150, 191,255,150, 175,255,150, 159,255,150, 143,255,150, 127,255,150
DefData 111,255,150, 95,255,150, 79,255,150, 63,255,150, 47,255,150, 31,255,150, 15,255,150, 0,255,150

DefData 0,255,0, 15,255,15, 31,255,31, 47,255,47, 63,255,63, 79,255,79, 95,255,95, 111,255,111
DefData 127,255,127, 143,255,143, 159,255,159, 175,255,175, 191,255,191, 207,255,207, 223,255,223, 255,255,255

#iconames
DefData "dots","draw","lines","curves","fill","airbrush","box","circle","oval","losange","select","text","grid","simmetry","zoom","colorpick","undo","clear"

Global youcandraw:Int

x=0
y=0
width=800
height=600
If width<GadgetWidth(Desktop()) x=(GadgetWidth(Desktop())-800)/2 
If height<GadgetHeight(Desktop()) y=(GadgetHeight(Desktop())-600)/2 
Global window:TGadget = CreateWindow("Delinux-Paint",x,y,width,height,Null,WINDOW_MENU | WINDOW_TITLEBAR)

Global mymousex=0
Global mymousey=0
Global myclick=0
Global startclick=0
Global oldmousex=0
Global oldmousey=0
Global myzoom=1

Global windowflag=0


If window
	file:TGadget=CreateMenu("File",1,WindowMenu(window))
		newfile:TGadget=CreateMenu("New Animation",101,file)
		CreateMenu("",0,file)
		loadimg:TGadget=CreateMenu("Load Image",102,file)
		saveimg:TGadget=CreateMenu("Save Image",103,file)
		saveimgas:TGadget=CreateMenu("Save Image As...",104,file)
		CreateMenu("",0,file)
		loadanim:TGadget=CreateMenu("Load Animation",105,file)
		saveanim:TGadget=CreateMenu("Save Animation",106,file)
		saveanimas:TGadget=CreateMenu("Save Animation As...",107,file)
		CreateMenu("",0,file)
		xit:TGadget=CreateMenu("Exit",199,file)
	edit:TGadget=CreateMenu("Edit",2,WindowMenu(window))
		undo:TGadget=CreateMenu("Undo",201,edit)
		redo:TGadget=CreateMenu("Redo",202,edit)
		CreateMenu("",0,edit)
		cutframe:TGadget=CreateMenu("Cut Frame",203,edit)
		copyframe:TGadget=CreateMenu("Copy Frame",204,edit)
		pasteframe:TGadget=CreateMenu("Paste Frame",205,edit)
		insertframe:TGadget=CreateMenu("Insert Frame",206,edit)
	brush:TGadget=CreateMenu("Brush",3,WindowMenu(window))
	mode:TGadget=CreateMenu("Mode",4,WindowMenu(window))
		paint:TGadget=CreateMenu("Paint",401,mode)
		brighten:TGadget=CreateMenu("Brighten",402,mode)
		darken:TGadget=CreateMenu("Darken",403,mode)
		CheckMenu paint
	frame:TGadget=CreateMenu("Frame",5,WindowMenu(window))
	animation:TGadget=CreateMenu("Animation",6,WindowMenu(window))
	colors:TGadget=CreateMenu("Colors",7,WindowMenu(window))
	options:TGadget=CreateMenu("Options",8,WindowMenu(window))
	help:TGadget=CreateMenu("Help",9,WindowMenu(window))
	UpdateWindowMenu(window)

	Global canvas:TGadget=CreateCanvas(130,10,370,370,window)
	Global canvash:TGadget=CreateSlider(130,380,370,20,window,SLIDER_HORIZONTAL)
	Global canvasv:TGadget=CreateSlider(500,10,20,370,window,SLIDER_VERTICAL)

	Global mypal:TGadget=CreateCanvas(530,10,256,256,window)


	' ImgBuffer[0] => Buffer where the program works
	' ImgBuffer[1] to [10] => Buffers for undo function
	Global ImgBuffer:TPixmap[11]
	Global ImgScrollX:Int=0
	Global ImgScrollY:Int=0
	For i=0 To 10	
		ImgBuffer[i]=CreatePixmap(640,480,PF_RGBA8888)
		ClearPixels ImgBuffer[i],$00000000
	Next
	Global myundo=0

	Global ink:Int[256*3]
	palettetype=1 ' 1=defaut, 2= greys
	
	If palettetype=2
		For i=0 To 255
			For j=0 To 2
				ink[i+(256*j)]=i
			Next
		Next
	Else
		RestoreData palettedefaut
		For i=0 To 255
			For j=0 To 2
				ReadData ink[i+(256*j)]
			Next
		Next	
	EndIf
	
	updatemypal()


Function updatemypal()
	SetGraphics CanvasGraphics(mypal)
	Local fi:Int
	Local fj:Int
	Local fc1:Int
	Local fc2:Int
	Local fc3:Int
	For fj=0 To 15
		For fi=0 To  15
			fc1=ink[fi+(fj*16)+(256*0)]
			fc2=ink[fi+(fj*16)+(256*1)]
			fc3=ink[fi+(fj*16)+(256*2)]
			SetColor fc1,fc2,fc3
			DrawRect fi*16,fj*16,16,16
			SetColor 0,0,0
			If fi+(fj*16)=pen Or fi+(fj*16)=paper Then SetColor (fc1+128) Mod 256,(fc2+128) Mod 256,(fc3+128) Mod 256
			DrawLine (fi*16),(fj*16),(fi*16)+15,(fj*16)
			DrawLine (fi*16)+15,(fj*16),(fi*16)+15,(fj*16)+15
			DrawLine (fi*16)+15,(fj*16)+15,(fi*16),(fj*16)+15
			DrawLine (fi*16),(fj*16)+15,(fi*16),(fj*16)
		Next
	Next
	Flip
EndFunction

	Global paper=0
	Global pen=255
	Global penwidth=1

	Global Icones:Tgadget[18]
	RestoreData iconames
	For j=0 To 8
		For i=0 To 1
			ReadData myname$
			Icones[i+(j*2)]=CreateButton(myname$,5+(i*60),10+(j*40),60,40,window)
		Next
	Next
	
	Global mytool=1

	updatetool()

Function updatetool()
	Local fi:Int
	For fi=0 To 17
		SetGadgetColor Icones[fi],80,80,80
		RedrawGadget  Icones[fi]
	Next
		SetGadgetColor Icones[mytool-1],255,255,255
		RedrawGadget  Icones[mytool-1]
EndFunction


	CreateTimer 25

	AddHook EmitEventHook, paintfnc

Function Dot(buf:TPixmap,X1:Int,Y1:Int,mcol:Int)
	X1=X1+ImgScrollX
	Y1=Y1+ImgScrollY
	X1=Min(Max(X1,0),PixmapWidth(buf)-1)
	Y1=Min(Max(Y1,0),PixmapHeight(buf)-1)
	buf.WritePixel(X1,Y1,ink[mcol+(256*0)]+(256*ink[mcol+(256*1)])+(256*256*ink[mcol+(256*2)]))
End Function

Function Line(buf:TPixmap,X1:Int,Y1:Int,X2:Int,Y2:Int,mcol:Int)
	'Draws a line of individual pixels from X1,Y1 to X2,Y2 at any angle
 	Local Steep:Int=Abs(Y2-Y1) > Abs(X2-X1)			'Boolean
	If Steep
		Local Temp:Int=X1; X1=Y1; Y1=Temp		'Swap X1,Y1
		Temp=X2; X2=Y2; Y2=Temp		'Swap X2,Y2
	EndIf
	Local DeltaX:Int=Abs(X2-X1)		'X Difference
	Local DeltaY:Int=Abs(Y2-Y1)		'Y Difference
	Local Error:Int=0		'Overflow counter
	Local DeltaError:Int=DeltaY		'Counter adder
	Local fX:Int=X1		'Start at X1,Y1
	Local fY:Int=Y1		
	Local XStep:Int
	Local YStep:Int
	If X1<X2 Then XStep=1 Else XStep=-1	'Direction
	If Y1<Y2 Then YStep=1 Else YStep=-1	'Direction
	If Steep Then dot buf,fY,fX,mcol Else dot buf,fX,fY,mcol		'Draw
	While fX<>X2
		fX:+XStep		'Move in X
		Error:+DeltaError		'Add to counter
		If (Error Shl 1)>DeltaX		'Would it overflow?
			fY:+YStep		'Move in Y
			Error=Error-DeltaX		'Overflow/wrap the counter
		EndIf
	If Steep Then dot buf,fY,fX,mcol Else dot buf,fX,fY,mcol		'Draw
	Wend
End Function

Function paintfnc:Object( id:Int, data:Object, context:Object)
	Local x1:Int,y1:Int,x2:Int,y2:Int
	Local ev:TEvent = TEvent(data)
	Local abcd
	If Not ev Then Return data
	If ev.ID = EVENT_TIMERTICK Then
			youcandraw=1
			If myclick=0
				RedrawGadget mypal
				RedrawGadget canvas
			EndIf
	ElseIf ev.ID = EVENT_GADGETPAINT Then
			If myclick=0
				SetGraphics CanvasGraphics( canvas)
				SetOrigin 0,0
					'copy a portion of pixmap buffer into the canvas
					x1=ImgScrollX
					y1=ImgScrollY
					x2=x1+369
					y2=y1+369
					If x2>=PixmapWidth(ImgBuffer[0]) Then x2=PixmapWidth(ImgBuffer[0])-1
					If y2>=PixmapHeight(ImgBuffer[0]) Then y2=PixmapHeight(ImgBuffer[0])-1
					DrawPixmap ImgBuffer[0],0,0
					Flip
			EndIf
		Return Null
	EndIf
	Return data
EndFunction

Function ShowGetResolution()
Local fx=0
Local fy=0
Local fwidth=400
Local fheight=300
If fwidth<GadgetWidth(window) fx=(GadgetWidth(window)-400)/2 
If fheight<GadgetHeight(window) fy=(GadgetHeight(window)-300)/2 
Global tempwindow:TGadget = CreateWindow("New Animation",fx,fy,fwidth,fheight,window,WINDOW_TOOL | WINDOW_CLIENTCOORDS)
EndFunction

	Repeat
		Select WaitEvent()
			Case EVENT_WINDOWCLOSE
				FreeGadget canvas
				FreeGadget mypal
				End
			Case EVENT_APPTERMINATE
				End
			Case EVENT_MENUACTION
				Select EventData()
					Case 101
						If windowflag=0
							windowflag=1
							'ShowGetResolution()
						EndIf
					Case 199
						FreeGadget canvas
						FreeGadget mypal
						End
				End Select
				
			Case EVENT_MOUSEMOVE
				If EventSource()=canvas
					mymousex=EventX()
					mymousey=EventY()
					If myclick=1 And youcandraw=1
						SetGraphics CanvasGraphics( canvas)
						SetOrigin 0,0
						SetLineWidth penwidth
						Select mytool
							Case 1
								dot ImgBuffer[0],mymousex,mymousey,pen
							Case 2
								If startclick=1
									dot ImgBuffer[0],mymousex,mymousey,pen
									oldmousex=mymousex
									oldmousey=mymousey
									startclick=0
								 Else 
									line ImgBuffer[0],oldmousex,oldmousey,mymousex,mymousey,pen			
									oldmousex=mymousex
									oldmousey=mymousey
								EndIf
							Case 18
								Cls
								Flip
								mytool=1
								updatetool()
						End Select
						'copy a portion of pixmap buffer into the canvas
						x1=ImgScrollX
						y1=ImgScrollY
						x2=x1+369
						y2=y1+369
						If x2>=PixmapWidth(ImgBuffer[0]) Then x2=PixmapWidth(ImgBuffer[0])-1
						If y2>=PixmapHeight(ImgBuffer[0]) Then y2=PixmapHeight(ImgBuffer[0])-1
						DrawPixmap ImgBuffer[0],0,0
						Flip
					EndIf
					If youcandraw=1
						youcandraw=0
						RedrawGadget mypal
						RedrawGadget canvas
					EndIf
				EndIf
				updatemypal()
			Case EVENT_MOUSEDOWN
				If EventSource()=canvas
					If myclick=0 Then startclick=1
					myclick=1
				EndIf
			Case EVENT_MOUSEUP
				If EventSource()=canvas
					myclick=0
					startclick=0
				EndIf
			Case EVENT_MOUSEENTER
				SetPointer POINTER_CROSS
			Case EVENT_MOUSELEAVE
				SetPointer POINTER_DEFAULT
			Case EVENT_GADGETACTION
				For i=0 To 17
					If EventSource()=Icones[i]
						mytool=i+1
						updatetool()
					EndIf
				Next
		End Select
	Forever

EndIf

End