forgotten commit. disabled until egl is adapted.
[AROS-Contrib.git] / gfx / lunapaint / src / app / canvas.c
blob40fd7b4e5b37ef1652271217ca876c1e3d3400fd
1 /****************************************************************************
2 * *
3 * canvas.c -- Lunapaint, *
4 * http://developer.berlios.de/projects/lunapaintami/ *
5 * Copyright (C) 2006, 2007, Hogne Titlestad <hogga@sub-ether.org> *
6 * Copyright (C) 2009-2011 LunaPaint Development Team *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the Free Software Foundation, *
20 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21 * *
22 ****************************************************************************/
25 #include <SDI_hook.h>
27 #include "canvas.h"
29 BOOL isZooming;
30 BOOL isScrolling;
31 BOOL fullscreenEditing;
32 int AskMinMaxTimes;
33 Object *windowFullscreen;
34 Object *fullscreenGroup;
36 //---------------------------------------------------------------------
39 Change project info
42 HOOKPROTONHNO(projFunc, void, int *param)
44 // We allocate but do not deallocate as
45 // this var is freed by Zune when it becomes part
46 // of it
47 unsigned char *projectName = NULL;
49 struct WindowList *lst = *( struct WindowList **)param;
51 get ( lst->projName, MUIA_String_Contents, &projectName );
52 set ( lst->win, MUIA_Window_Title, projectName );
53 set ( lst->projectWin, MUIA_Window_Open, FALSE );
59 Dispatcher for our RGBitmapObject
61 BOOPSI_DISPATCHER(IPTR, RGBitmapDispatcher, cl, obj, msg)
63 switch ( msg->MethodID )
65 case MUIM_Draw: return MUIM_RGB_Draw ( cl, obj, msg );
66 case MUIM_Luna_Canvas_Redraw: return MUIM_RGB_Redraw ( );
67 case MUIM_Luna_Canvas_RedrawArea: return MUIM_RGB_RedrawArea ( );
68 case MUIM_HandleInput: return MUIM_RGB_HandleInput ( cl, obj, msg );
69 case MUIM_Setup: return MUIM_RGB_Setup ( cl, obj, msg );
70 case MUIM_Cleanup: return MUIM_RGB_Cleanup ( cl, obj, msg );
71 case MUIM_Luna_Canvas_ScrollingNotify: return MUIM_RGB_ScrollingNotify ( );
72 case MUIM_Luna_CanvasActivate: return MUIM_RGB_CanvasActivate ( cl, obj, msg );
73 case MUIM_Luna_CanvasDeactivate: return MUIM_RGB_CanvasDeactivate ( cl, obj, msg );
74 case MUIM_Luna_ZoomIn: return MUIM_RGB_ZoomIn ( );
75 case MUIM_Luna_ZoomOut: return MUIM_RGB_ZoomOut ( );
76 case MUIM_Luna_ShowAll: return MUIM_RGB_ShowAll ( );
77 case MUIM_AskMinMax: return MUIM_RGB_AskMinMax ( cl, obj, msg );
78 case MUIM_Luna_CloseCanvasWin: return MUIM_RGB_CloseCanvasWin ( cl, obj, msg );
79 default: return DoSuperMethodA ( cl, obj, msg );
81 return ( IPTR )NULL;
83 BOOPSI_DISPATCHER_END
86 /******************************************************************************
87 Public functions
88 ******************************************************************************/
90 IPTR MUIM_RGB_Draw ( Class *CLASS, Object *self, Msg message )
92 // Redrawing
93 if ( globalActiveCanvas != NULL )
95 AskMinMaxTimes = 0;
96 globalActiveWindow->prevBlit.w = 0;
97 _RGBitmapRedraw ( CLASS, self );
98 return ( IPTR )NULL;
100 return DoSuperMethodA ( CLASS, self, message );
102 IPTR MUIM_RGB_Redraw ( )
104 if ( globalActiveCanvas )
106 MUI_Redraw ( globalActiveWindow->area, MADF_DRAWUPDATE );
108 return ( IPTR )NULL;
111 // Called from outside the object
112 IPTR MUIM_RGB_RedrawArea ( )
114 if ( globalActiveCanvas != NULL )
116 globalActiveCanvas->winHasChanged = TRUE;
117 if ( redrawTimes < 5 )
118 redrawTimes++;
120 return ( IPTR )NULL;
123 IPTR MUIM_RGB_HandleInput ( Class *CLASS, Object *self, Msg message )
125 if ( CLASS == NULL || isZooming || globalActiveCanvas == NULL )
126 return ( IPTR )NULL;
128 struct MUIP_HandleInput *Message = ( struct MUIP_HandleInput *)message;
130 struct RGBitmapData *data = ( struct RGBitmapData *)INST_DATA ( CLASS, self );
131 char movement = 0;
133 // Immediately set this window as active window!
134 if ( globalActiveCanvas != data->window->canvas )
136 globalActiveCanvas = data->window->canvas;
137 globalActiveWindow = data->window;
140 // Get current zoom in a simpler to write variable
141 int zoom = globalActiveCanvas->zoom;
143 // Get correct offset coordinates
144 // and align them to zoom "grid"
145 int ox = XGET ( globalActiveWindow->scrollH, MUIA_Prop_First );
146 int oy = XGET ( globalActiveWindow->scrollV, MUIA_Prop_First );
147 ox = ( int )( ( double )ox / zoom ) * zoom;
148 oy = ( int )( ( double )oy / zoom ) * zoom;
150 // If the offset has changed (with a window resize etc) or we got a scroll event
151 // notification
152 if (
153 ( ox != globalActiveCanvas->offsetx || oy != globalActiveCanvas->offsety ) &&
154 isScrolling
157 ScrollCanvas ( ox, oy );
158 isScrolling = FALSE;
161 // Get dimensions
162 ULONG areaWidth = _getAreaWidth ( );
164 // Make sure we have a message
165 if ( Message->imsg )
167 switch ( Message->imsg->Class )
169 case IDCMP_MOUSEMOVE:
171 if ( !data->window->isActive )
173 data->window->isActive = TRUE;
174 break;
177 // Signalize that we have movement
178 movement = 1;
179 MouseHasMoved = TRUE;
181 // Get the mose coordinates relative to top and left widget edges
182 data->zuneAreaLeft = XGET ( self, MUIA_LeftEdge );
183 data->zuneAreaTop = XGET ( self, MUIA_TopEdge );
185 // Update window edge coordinates
186 data->window->canvas->winEdgeWidth = data->zuneAreaLeft;
187 data->window->canvas->winEdgeHeight = data->zuneAreaTop;
189 // Update coordinates on display
190 STRPTR coord = AllocVec ( 20, MEMF_CLEAR );
191 sprintf ( coord, "X: %d ", ( int )cMouseX );
192 set ( data->window->txtCoordX, MUIA_Text_Contents, ( IPTR )coord );
193 FreeVec ( coord );
194 coord = AllocVec ( 20, MEMF_CLEAR );
195 sprintf ( coord, "Y: %d ", ( int )cMouseY );
196 set ( data->window->txtCoordY, MUIA_Text_Contents, ( IPTR )coord );
197 FreeVec ( coord );
200 case IDCMP_MOUSEBUTTONS:
202 // Signalize that we have movement
203 movement = 1;
205 // And that the window has changed
206 data->window->canvas->winHasChanged = TRUE;
208 if ( Message->imsg->Code == SELECTDOWN )
210 if ( cMouseX >= ox || cMouseX < ox + areaWidth || cMouseY >= oy || cMouseY < oy + areaWidth )
212 // Register the click!
213 if ( !MouseButtonL ) MouseHasMoved = TRUE;
214 MouseButtonL = TRUE;
215 // Paintbrush tool filled
216 if ( globalCurrentTool == LUNA_TOOL_BRUSH ) brushTool.RecordContour = TRUE;
220 // Inactivizers happen everywhere
221 if ( Message->imsg->Code == SELECTUP )
223 MouseHasMoved = TRUE;
224 MouseButtonL = FALSE;
225 if ( globalCurrentTool == LUNA_TOOL_BRUSH ) brushTool.RecordContour = FALSE;
226 globalActiveWindow->layersChg = TRUE;
227 MUI_Redraw ( WidgetLayers, MADF_DRAWUPDATE );
229 break;
233 return 0;
236 IPTR MUIM_RGB_Setup ( Class *CLASS, Object *self, Msg message )
238 AskMinMaxTimes = 0;
239 isScrolling = FALSE;
240 isZooming = FALSE;
241 MUI_RequestIDCMP( self, IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_RAWKEY );
242 return DoSuperMethodA ( CLASS, self, message );
245 IPTR MUIM_RGB_Cleanup ( Class *CLASS, Object *self, Msg message )
247 MUI_RejectIDCMP( self, IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_RAWKEY );
248 return DoSuperMethodA ( CLASS, self, message );
251 IPTR MUIM_RGB_ScrollingNotify ( )
253 isScrolling = TRUE;
254 return ( IPTR )NULL;
257 IPTR MUIM_RGB_CanvasActivate ( Class *CLASS, Object *self, Msg message )
259 struct RGBitmapData *data = INST_DATA ( CLASS, self );
261 // We can use keyboard shortcuts
262 keyboardEnabled = TRUE;
264 // Quicky update these two globals
265 globalActiveWindow = data->window;
266 globalActiveCanvas = data->window->canvas;
268 // Yeah =)
269 AskMinMaxTimes = 0;
271 // Set this
272 Update_AnimValues ( );
274 // Set window is unactive to force an up
275 data->window->isActive = TRUE;
277 // Redraw first time
278 MUI_Redraw ( WidgetLayers, MADF_DRAWUPDATE );
280 return ( IPTR )NULL;
283 IPTR MUIM_RGB_CanvasDeactivate ( Class *CLASS, Object *self, Msg message )
285 if ( globalActiveWindow != NULL && !fullscreenEditing )
287 struct RGBitmapData *data = INST_DATA ( CLASS, self );
288 data->window->isActive = FALSE;
290 return ( IPTR )NULL;
293 IPTR MUIM_RGB_ZoomIn ( )
295 if ( globalActiveCanvas->zoom + 1 <= 32 && !isZooming )
297 isZooming = TRUE;
298 AskMinMaxTimes = 2;
300 // Remove any previous tool preview
301 removePrevToolPreview ( );
303 // Move scrollbars
304 int ox = globalActiveCanvas->offsetx;
305 int oy = globalActiveCanvas->offsety;
307 // Set new zoom
308 globalActiveCanvas->zoom++;
310 // Snap to zoom
311 globalActiveCanvas->offsetx = ( ox * 2 );
312 globalActiveCanvas->offsety = ( oy * 2 );
313 constrainOffset ( globalActiveCanvas );
315 // Update GUI
316 winHasChanged ( );
317 isZooming = FALSE;
319 return ( IPTR )NULL;
322 IPTR MUIM_RGB_ZoomOut ( )
324 if ( globalActiveCanvas->zoom - 1 >= 1 && !isZooming )
326 isZooming = TRUE;
327 AskMinMaxTimes = 2;
329 // Remove any previous tool preview
330 removePrevToolPreview ( );
332 // Set new zoom
333 globalActiveCanvas->zoom--;
335 // Move scrollbars
336 globalActiveCanvas->offsetx = globalActiveCanvas->offsetx * 0.5;
337 globalActiveCanvas->offsety = globalActiveCanvas->offsety * 0.5;
338 constrainOffset ( globalActiveCanvas );
340 // Update GUI
341 winHasChanged ( );
342 isZooming = FALSE;
344 return ( IPTR )NULL;
347 IPTR MUIM_RGB_ShowAll ( )
349 // Remove any previous tool preview
350 isZooming = TRUE;
351 removePrevToolPreview ( );
352 AskMinMaxTimes = 2;
353 globalActiveCanvas->zoom = 1;
354 globalActiveCanvas->offsetx = 0;
355 globalActiveCanvas->offsety = 0;
356 winHasChanged ( );
357 isZooming = FALSE;
358 return ( IPTR )NULL;
361 IPTR MUIM_RGB_AskMinMax ( Class *CLASS, Object *self, Msg message )
363 DoSuperMethodA ( CLASS, self, message );
364 struct RGBitmapData *data = INST_DATA ( CLASS, self );
365 struct MUIP_AskMinMax *Message = ( struct MUIP_AskMinMax *)message;
367 // This one is needed when askminmax is asked with reopening windows that
368 // have been _hidden_ (not disposed), like when going into fullscreen mode
369 if ( !globalActiveWindow )
371 globalActiveWindow = data->window;
372 globalActiveCanvas = data->window->canvas;
375 int calcwidth = data->window->canvas->width * data->window->canvas->zoom;
376 int calcheight = data->window->canvas->height * data->window->canvas->zoom;
378 int tWidth = _getAreaWidth ( ),
379 tHeight = _getAreaHeight ( ),
380 minWidth = calcwidth,
381 minHeight = calcheight;
383 if ( minWidth > tWidth ) minWidth = tWidth;
384 if ( minHeight > tHeight ) minHeight = tHeight;
386 if ( AskMinMaxTimes > 0 )
388 // Dunno why I need to add the lunaPubScreen size or run this the second
389 // time askminmax is executed
390 Message->MinMaxInfo->MinWidth += minWidth;
391 Message->MinMaxInfo->MinHeight += minHeight;
392 AskMinMaxTimes--;
395 Message->MinMaxInfo->DefWidth += calcwidth;
396 Message->MinMaxInfo->DefHeight += calcheight;
397 Message->MinMaxInfo->MaxWidth += lunaPubScreen->Width;
398 Message->MinMaxInfo->MaxHeight += lunaPubScreen->Height;
400 return ( IPTR )NULL;
403 IPTR MUIM_RGB_CloseCanvasWin ( Class *CLASS, Object *self, Msg message )
405 if ( !fullscreenEditing )
407 removeActiveWindow ( CLASS, self );
408 layerRenderBlank ( );
410 return ( IPTR )NULL;
414 void checkKeyboardShortcuts ( UWORD valu )
416 switch ( valu )
418 case RAWKEY_A:
419 if ( brushTool.antialias == FALSE )
421 DoMethod ( antiOffImage, MUIM_CallHook, &brushOptions_hook, SET_ANTIALIAS );
423 else
425 DoMethod ( antiOffImage, MUIM_CallHook, &brushOptions_hook, SET_ANTIALIASOFF );
427 makeToolBrush ( );
428 break;
429 case RAWKEY_SPACE:
431 int VAL = ( int )XGET( tbxCyc_PaletteSnap, MUIA_Cycle_Active );
432 if ( VAL == 0 )
433 set ( tbxCyc_PaletteSnap, MUIA_Cycle_Active, 1 );
434 else set ( tbxCyc_PaletteSnap, MUIA_Cycle_Active, 0 );
436 break;
437 case RAWKEY_F:
438 globalCurrentTool = LUNA_TOOL_FILL;
439 setToolbarActive ( );
440 break;
441 case RAWKEY_D:
442 DoMethod ( paletteRect, MUIM_Luna_SetTool_Draw );
443 break;
444 case RAWKEY_L:
445 DoMethod ( paletteRect, MUIM_Luna_SetTool_Line );
446 break;
447 case RAWKEY_E:
448 DoMethod ( paletteRect, MUIM_Luna_SetTool_Circle );
449 break;
450 case RAWKEY_R:
451 DoMethod ( paletteRect, MUIM_Luna_SetTool_Rectangle );
452 break;
453 case RAWKEY_O:
454 DoMethod ( paletteRect, MUIM_Luna_SetTool_Colorpicker );
455 break;
456 case RAWKEY_B:
457 DoMethod ( paletteRect, MUIM_Luna_SetTool_ClipBrush );
458 break;
459 case RAWKEY_G:
461 ULONG curr = XGET ( tbxCycGrid, MUIA_Cycle_Active );
462 if ( curr == 0 )
463 set ( tbxCycGrid, MUIA_Cycle_Active, 1 );
464 else
465 set ( tbxCycGrid, MUIA_Cycle_Active, 0 );
467 break;
468 case RAWKEY_J:
469 if ( !globalActiveCanvas ) return;
470 swapCanvasBuffers ( globalActiveCanvas );
471 globalActiveWindow->rRectW = 0;
472 globalActiveWindow->rRectX = 0;
473 globalActiveWindow->rRectH = 0;
474 globalActiveWindow->rRectY = 0;
475 globalActiveCanvas->winHasChanged = TRUE;
476 globalActiveWindow->layersChg = TRUE;
477 MUI_Redraw ( globalActiveWindow->area, MADF_DRAWUPDATE );
478 break;
479 case RAWKEY_J | RAWKEY_RSHIFT:
480 if ( !globalActiveCanvas ) return;
481 copyToSwap ( globalActiveCanvas );
482 break;
483 case RAWKEY_Y:
484 flipBrushVert ( );
485 break;
486 case RAWKEY_X:
487 flipBrushHoriz ( );
488 break;
489 case RAWKEY_Z:
490 rotateBrush90 ( );
491 break;
492 case RAWKEY_PERIOD:
493 nextPaletteColor ( );
494 break;
495 case RAWKEY_COMMA:
496 prevPaletteColor ( );
497 break;
498 case RAWKEY_F1: set ( tbxCycPaintMode, MUIA_Cycle_Active, 0 ); break;
499 case RAWKEY_F2: set ( tbxCycPaintMode, MUIA_Cycle_Active, 1 ); break;
500 case RAWKEY_F3: set ( tbxCycPaintMode, MUIA_Cycle_Active, 6 ); break;
501 case RAWKEY_F4: set ( tbxCycPaintMode, MUIA_Cycle_Active, 4 ); break;
502 case RAWKEY_F5: set ( tbxCycPaintMode, MUIA_Cycle_Active, 5 ); break;
503 case RAWKEY_F6: set ( tbxCycPaintMode, MUIA_Cycle_Active, 7 ); break;
504 case RAWKEY_F7: set ( tbxCycPaintMode, MUIA_Cycle_Active, 8 ); break;
505 case RAWKEY_F8: set ( tbxCycPaintMode, MUIA_Cycle_Active, 2 ); break;
506 case RAWKEY_F9: set ( tbxCycPaintMode, MUIA_Cycle_Active, 3 ); break;
508 // Toggle fullscreen mode
509 case RAWKEY_F11:
510 if ( !globalActiveCanvas ) return;
511 if ( !fullscreenEditing )
513 if ( !globalActiveWindow ) return;
514 showFullscreenWindow ( globalActiveCanvas );
516 else hideFullscreenWindow ( );
517 break;
519 // Toggle toolbox
520 case RAWKEY_F12:
522 // Don't hide the toolbox if we're not in fullscreen and we're not having a canvas window
523 if ( GlobalPrefs.ScreenmodeType == 0 && !fullscreenEditing && !globalActiveWindow ) break;
525 BOOL boxopen = XGET ( toolbox, MUIA_Window_Open );
526 if ( boxopen ) set ( toolbox, MUIA_Window_Open, FALSE );
527 else set ( toolbox, MUIA_Window_Open, TRUE );
529 break;
531 case RAWKEY_UP: moveScrollbarUp ( ); break;
532 case RAWKEY_DOWN: moveScrollbarDown ( ); break;
533 case RAWKEY_LEFT: moveScrollbarLeft ( ); break;
534 case RAWKEY_RIGHT: moveScrollbarRight ( ); break;
536 // Opacity values
537 case RAWKEY_KP_1: set ( tbxSlider_Brushopacity, MUIA_Numeric_Value, 5 ); break;
538 case RAWKEY_KP_2: set ( tbxSlider_Brushopacity, MUIA_Numeric_Value, 10 ); break;
539 case RAWKEY_KP_3: set ( tbxSlider_Brushopacity, MUIA_Numeric_Value, 30 ); break;
540 case RAWKEY_KP_4: set ( tbxSlider_Brushopacity, MUIA_Numeric_Value, 60 ); break;
541 case RAWKEY_KP_5: set ( tbxSlider_Brushopacity, MUIA_Numeric_Value, 128 ); break;
542 case RAWKEY_KP_6: set ( tbxSlider_Brushopacity, MUIA_Numeric_Value, 255 ); break;
544 // Brush sizes
545 case RAWKEY_KP_PLUS:
547 int bsz = XGET ( tbxSlider_Brushdiameter, MUIA_Numeric_Value );
548 set ( tbxSlider_Brushdiameter, MUIA_Numeric_Value, bsz + 2 );
549 break;
551 case RAWKEY_MINUS:
553 int bsz = XGET ( tbxSlider_Brushdiameter, MUIA_Numeric_Value );
554 set ( tbxSlider_Brushdiameter, MUIA_Numeric_Value, bsz - 2 );
555 break;
557 case RAWKEY_KP_DECIMAL: set ( tbxSlider_Brushdiameter, MUIA_Numeric_Value, 1 ); break;
558 case RAWKEY_KP_ENTER: set ( tbxSlider_Brushdiameter, MUIA_Numeric_Value, 100 ); break;
560 default: break;
562 lastKeyPressed = valu;
565 void moveScrollbarUp ( )
567 if ( globalActiveWindow == NULL ) return;
568 int pos = XGET ( globalActiveWindow->scrollV, MUIA_Prop_First );
569 int dist = globalActiveCanvas->zoom * 10;
570 set ( globalActiveWindow->scrollV, MUIA_Prop_First, pos - dist );
573 void moveScrollbarDown ( )
575 if ( globalActiveWindow == NULL ) return;
576 int pos = XGET ( globalActiveWindow->scrollV, MUIA_Prop_First );
577 int dist = globalActiveCanvas->zoom * 10;
578 set ( globalActiveWindow->scrollV, MUIA_Prop_First, pos + dist );
581 void moveScrollbarLeft ( )
583 if ( globalActiveWindow == NULL ) return;
584 int pos = XGET ( globalActiveWindow->scrollH, MUIA_Prop_First );
585 int dist = globalActiveCanvas->zoom * 10;
586 set ( globalActiveWindow->scrollH, MUIA_Prop_First, pos - dist );
589 void moveScrollbarRight ( )
591 if ( globalActiveWindow == NULL ) return;
592 int pos = XGET ( globalActiveWindow->scrollH, MUIA_Prop_First );
593 int dist = globalActiveCanvas->zoom * 10;
594 set ( globalActiveWindow->scrollH, MUIA_Prop_First, pos + dist );
597 void constrainOffset ( struct oCanvas *canvas )
599 // Get some vars
600 int zoom = canvas->zoom;
602 int vWidth = _getAreaWidth ( ),
603 vHeight = _getAreaHeight ( );
605 vWidth = ( double )vWidth / zoom;
606 vHeight = ( double )vHeight / zoom;
608 int cWidth = canvas->width;
609 int cHeight = canvas->height;
611 int ox = ( double )canvas->offsetx / zoom;
612 int oy = ( double )canvas->offsety / zoom;
614 // Bounds
615 if ( ox < 0 ) canvas->offsetx = 0;
616 else if ( ox + vWidth >= cWidth )
617 canvas->offsetx = ( cWidth - vWidth ) * zoom;
618 if ( oy < 0 ) canvas->offsety = 0;
619 else if ( oy + vHeight >= cHeight )
620 canvas->offsety = ( cHeight - vHeight ) * zoom;
622 // Snap to zoom
623 canvas->offsetx = ( int )( ( double )canvas->offsetx / zoom ) * zoom;
624 canvas->offsety = ( int )( ( double )canvas->offsety / zoom ) * zoom;
627 void snapToBounds ( int *x, int *y )
629 // Get some vars
630 int zoom = globalActiveCanvas->zoom;
632 int vWidth = _getAreaWidth ( ),
633 vHeight = _getAreaHeight ( );
635 int cWidth = globalActiveCanvas->width * zoom;
636 int cHeight = globalActiveCanvas->height * zoom;
638 // Adapt x/y in bounds
639 if ( *x < 0 ) *x = 0;
640 else if ( *x + vWidth >= cWidth )
641 *x = ( int )( ( cWidth - vWidth ) / zoom ) * zoom;
642 if ( *y < 0 ) *y = 0;
643 else if ( *y + vHeight >= cHeight )
644 *y = ( int )( ( cHeight - vHeight ) / zoom ) * zoom;
647 void winHasChanged ( )
649 globalActiveCanvas->winHasChanged = TRUE;
650 DoMethod ( globalActiveWindow->area, MUIM_Draw );
653 IPTR _RGBitmapRedraw ( Class *CLASS, Object *self )
655 // Get stored data
656 struct RGBitmapData *data = INST_DATA ( CLASS, self );
658 if ( globalActiveCanvas == data->window->canvas )
660 // Get image dimensions multiplied by zoom
661 ULONG imageWidth = data->window->canvas->width * data->window->canvas->zoom;
662 ULONG imageHeight = data->window->canvas->height * data->window->canvas->zoom;
664 // Check if the dimensions of the visible width has changed
665 ULONG ZuneWidth = XGET ( data->window->area, MUIA_Width );
666 ULONG ZuneHeight = XGET ( data->window->area, MUIA_Height );
667 if ( data->zuneAreaWidth != ZuneWidth || data->zuneAreaHeight != ZuneHeight )
668 data->window->canvas->winHasChanged = TRUE;
670 // Get top and left edge of area
671 data->zuneAreaTop = XGET ( data->window->area, MUIA_TopEdge );
672 data->zuneAreaLeft = XGET ( data->window->area, MUIA_LeftEdge );
673 data->zuneAreaWidth = ZuneWidth;
674 data->zuneAreaHeight = ZuneHeight;
675 data->rgbAreaTop = _getAreaOffsetY ( ) + data->zuneAreaTop;
676 data->rgbAreaLeft = _getAreaOffsetX ( ) + data->zuneAreaLeft;
678 // Update known container size
679 // This needs cleaning up
680 int cvisWidth = _getAreaWidth ( ),
681 cvisHeight = _getAreaHeight ( );
682 data->window->contWidth = cvisWidth;
683 data->window->contHeight = cvisHeight;
684 data->window->canvas->visibleWidth = cvisWidth;
685 data->window->canvas->visibleHeight = cvisHeight;
687 // we're only using a maximum area of the container for
688 // the drawing itself
689 if ( cvisWidth > imageWidth ) cvisWidth = imageWidth;
690 if ( cvisHeight > imageHeight ) cvisHeight = imageHeight;
692 // Update window edge coordinates (do we need this? find out)
693 data->window->canvas->winEdgeWidth = _getAreaLeft ( );
694 data->window->canvas->winEdgeHeight = _getAreaTop ( );
697 // Update scrollbars if we're changing zoom
698 if (
699 globalActiveCanvas->zoom != data->currentzoom ||
700 data->window->canvas->winHasChanged
703 // Set scrollbars
704 set ( data->window->scrollH, MUIA_Prop_Visible, ( IPTR )cvisWidth );
705 set ( data->window->scrollV, MUIA_Prop_Visible, ( IPTR )cvisHeight );
706 set ( data->window->scrollH, MUIA_Prop_Entries, ( IPTR )imageWidth );
707 set ( data->window->scrollV, MUIA_Prop_Entries, ( IPTR )imageHeight );
708 set ( data->window->scrollH, MUIA_Prop_First, ( IPTR )globalActiveCanvas->offsetx );
709 set ( data->window->scrollV, MUIA_Prop_First, ( IPTR )globalActiveCanvas->offsety );
711 // Set dimensions
712 data->currentzoom = globalActiveCanvas->zoom;
713 data->rgbAreaWidth = cvisWidth;
714 data->rgbAreaHeight = cvisHeight;
716 // In case triggered by zoom
717 data->window->canvas->winHasChanged = TRUE;
720 // Update the screen buffer
721 if ( data->window->canvas->winHasChanged )
723 int Tool = globalCurrentTool; // <- disables drawing tool preview in rendering func
724 globalCurrentTool = -1; //
726 // Accelerated redraw
727 if ( data->window->rRectW || data->window->rRectH )
729 struct oCanvas *canvas = data->window->canvas;
730 int offsetx = ( canvas->offsetx + data->window->rRectX ) / canvas->zoom;
731 int offsety = ( canvas->offsety + data->window->rRectY ) / canvas->zoom;
732 int width = ( double )data->window->rRectW / canvas->zoom;
733 int height = ( double )data->window->rRectH / canvas->zoom;
735 D(bug("1a. Redrawing accelerated %dx%d\n", width, height));
737 blitAreaRect (
738 offsetx, offsety,
739 width, height,
740 canvas, _rp ( data->window->area )
743 // Reset accelerator parameters
744 data->window->rRectX = 0;
745 data->window->rRectY = 0;
746 data->window->rRectW = 0;
747 data->window->rRectH = 0;
749 D(bug("1b. Redraw complete\n"));
751 // Slow redraw (with zoom etc)
752 else
754 FillPixelArray (
755 _rp ( data->window->area ),
756 data->zuneAreaLeft, data->zuneAreaTop,
757 data->zuneAreaWidth,
758 data->zuneAreaHeight,
759 0x333333
761 D(bug("2a. Redrawing anew %dx%d\n", cvisWidth, cvisHeight));
762 if ( redrawScreenbuffer ( data->window->canvas ) )
764 WritePixelArray (
765 data->window->canvas->screenbuffer,
766 0, 0, data->window->canvas->scrStorageWidth * 4, _rp ( data->window->area ),
767 data->rgbAreaLeft, data->rgbAreaTop, cvisWidth, cvisHeight, RECTFMT_RAW
770 D(bug("2b. Redraw complete\n"));
771 UpdateCanvasInfo ( data->window );
772 Update_AnimValues ( );
774 data->window->canvas->winHasChanged = FALSE;
776 globalCurrentTool = Tool; // Resets tool setting
778 else
780 if ( data->window->canvas->screenstorage != NULL )
782 // Write all data to the rastport!
783 FillPixelArray (
784 _rp ( data->window->area ),
785 data->zuneAreaLeft, data->zuneAreaTop,
786 data->zuneAreaWidth,
787 data->zuneAreaHeight,
788 0x333333
790 WritePixelArray (
791 data->window->canvas->screenstorage,
792 0, 0, data->window->canvas->scrStorageWidth * 4, _rp ( data->window->area ),
793 data->rgbAreaLeft, data->rgbAreaTop, cvisWidth, cvisHeight, RECTFMT_RAW
797 if ( globalActiveWindow->layersChg ) MUI_Redraw ( WidgetLayers, MADF_DRAWUPDATE );
799 // For some reason, we're updatated and not actived
800 else
802 if ( data->window->canvas->screenstorage )
804 // Write all data to the rastport!
805 WritePixelArray (
806 data->window->canvas->screenstorage,
807 0, 0, data->window->canvas->scrStorageWidth * 4,
808 _rp ( data->window->area ),
809 data->rgbAreaLeft, data->rgbAreaTop, data->rgbAreaWidth, data->rgbAreaHeight, RECTFMT_RAW
814 return ( IPTR )NULL;
817 void SnapOffsetToZoom ( struct oCanvas *canv )
819 if ( canv == NULL ) canv = globalActiveCanvas;
820 // Contstrain offset to zoom
821 int *ofx = &canv->offsetx, *ofy = &canv->offsety, zoom = canv->zoom;
822 *ofx = ( int )( *ofx / zoom ) * zoom;
823 *ofy = ( int )( *ofy / zoom ) * zoom;
826 void UpdateCanvasInfo ( struct WindowList *win )
828 unsigned char frameText[ 32 ];
829 unsigned char layerText[ 32 ];
830 int frame = ( int )( win->canvas->currentFrame + 1 );
831 int frams = ( int )win->canvas->totalFrames;
832 int layer = ( int )( win->canvas->currentLayer + 1 );
833 int layrs = ( int )win->canvas->totalLayers;
834 sprintf ( ( unsigned char *)&frameText, _(MSG_CANVAS_FRAME), frame, frams );
835 set ( win->txtFrameInf, MUIA_Text_Contents, ( STRPTR )&frameText );
836 sprintf ( ( unsigned char *)&layerText, _(MSG_CANVAS_LAYER), layer, layrs );
837 set ( win->txtLayerInf, MUIA_Text_Contents, ( STRPTR )&layerText );
839 // Update zoom display
840 STRPTR zlevel = AllocVec ( 20, MEMF_CLEAR );
841 sprintf ( zlevel, _(MSG_CANVAS_ZOOM), ( int )win->canvas->zoom );
842 set ( win->txtZoomLevel, MUIA_Text_Contents, ( IPTR )zlevel );
843 FreeVec ( zlevel );
846 IPTR ScrollCanvas ( int x, int y )
848 // Ajust to not collide with canvas bounds
849 snapToBounds ( &x, &y );
851 // Remove any prevous toolpreview
852 removePrevToolPreview ( );
854 // Get coordinates
855 ULONG areaWidth = _getAreaWidth ( );
856 ULONG areaHeight = _getAreaHeight ( );
857 ULONG areaLeft = _getAreaLeft ( ) + _getAreaOffsetX ( );
858 ULONG areaTop = _getAreaTop ( ) + _getAreaOffsetY ( );
860 // find diff and align to zoom
861 int diffx = x - ( int )globalActiveCanvas->offsetx;
862 int diffy = y - ( int )globalActiveCanvas->offsety;
863 int hght = areaHeight - abs ( diffy );
864 int wdth = areaWidth - abs ( diffx );
866 // Scroll storage buffer
867 if ( globalActiveCanvas->screenstorage )
869 removePrevToolPreview ( );
870 scrollScreenStorage ( globalActiveCanvas, diffx, diffy );
871 WritePixelArray (
872 globalActiveCanvas->screenstorage,
873 0, 0,
874 globalActiveCanvas->scrStorageWidth * 4,
875 _rp ( globalActiveWindow->area ),
876 areaLeft, areaTop, globalActiveCanvas->scrStorageWidth, globalActiveCanvas->scrStorageHeight,
877 RECTFMT_RAW
881 // Draw emptied areas on y
882 if ( abs ( diffy ) > 0 )
884 // If scrolling inside viewable area
885 if ( hght > 0 )
887 globalActiveWindow->rRectW = areaWidth;
888 globalActiveWindow->rRectX = 0;
889 globalActiveWindow->rRectH = abs ( diffy ) ? abs ( diffy ) : areaHeight;
890 globalActiveWindow->rRectY = ( diffy > 0 ) ? ( areaHeight - diffy ) : 0;
892 // If jumping a page
893 else
895 globalActiveWindow->rRectW = 0;
896 globalActiveWindow->rRectX = 0;
897 globalActiveWindow->rRectH = 0;
898 globalActiveWindow->rRectY = 0;
900 globalActiveCanvas->offsety = y;
901 globalActiveCanvas->winHasChanged = TRUE;
902 MUI_Redraw ( globalActiveWindow->area, MADF_DRAWUPDATE );
904 // Draw emptied areas on x
905 if ( abs ( diffx ) > 0 )
907 // If scrolling inside viewable area
908 if ( wdth > 0 )
910 globalActiveWindow->rRectW = abs ( diffx ) ? abs ( diffx ) : areaWidth;
911 globalActiveWindow->rRectX = ( diffx > 0 ) ? ( areaWidth - diffx ) : 0;
912 globalActiveWindow->rRectH = areaHeight;
913 globalActiveWindow->rRectY = 0;
915 // Jumping a page
916 else
918 globalActiveWindow->rRectW = 0;
919 globalActiveWindow->rRectX = 0;
920 globalActiveWindow->rRectH = 0;
921 globalActiveWindow->rRectY = 0;
924 globalActiveCanvas->offsetx = x;
925 globalActiveCanvas->winHasChanged = TRUE;
926 MUI_Redraw ( globalActiveWindow->area, MADF_DRAWUPDATE );
929 return ( IPTR )NULL;
932 void getMouseCoordinates ( )
934 if ( !globalActiveCanvas || !globalActiveWindow ) return;
936 int ox = globalActiveCanvas->offsetx;
937 int oy = globalActiveCanvas->offsety;
939 eMouseX = (
940 ( int )lunaPubScreen->MouseX -
941 XGET ( globalActiveWindow->win, MUIA_Window_LeftEdge ) - _getAreaOffsetX ( ) - _getAreaLeft ( )
943 eMouseY = (
944 ( int )lunaPubScreen->MouseY -
945 XGET ( globalActiveWindow->win, MUIA_Window_TopEdge ) - _getAreaOffsetY ( ) - _getAreaTop ( )
948 cMouseX = ( eMouseX + ox ) / globalActiveCanvas->zoom;
949 cMouseY = ( eMouseY + oy ) / globalActiveCanvas->zoom;
951 if ( globalGrid )
953 cMouseX = ( int )( cMouseX / globalCurrentGrid ) * globalCurrentGrid;
954 cMouseY = ( int )( cMouseY / globalCurrentGrid ) * globalCurrentGrid;
957 // Unantialiased coords..
958 if ( !brushTool.antialias )
960 cMouseX = ( int )cMouseX;
961 cMouseY = ( int )cMouseY;
964 if ( !MouseButtonL && !MouseButtonR ) dMouseX = cMouseX, dMouseY = cMouseY;
967 void addCanvaswindow (
968 unsigned int width, unsigned int height,
969 unsigned int layers, unsigned int frames,
970 BOOL generateCanvas
973 struct WindowList *temp = canvases; // Put current in temp
974 canvases = AllocVec ( sizeof ( WindowList ), MEMF_CLEAR );
976 struct MUI_CustomClass *mcc =
977 MUI_CreateCustomClass (
978 NULL, MUIC_Group, NULL,
979 sizeof ( struct RGBitmapData ),
980 RGBitmapDispatcher
983 canvases->win = MUI_NewObject ( MUIC_Window,
984 MUIA_Window_Title, __(MSG_CANVAS_UNNAMED),
985 MUIA_Window_SizeGadget, TRUE,
986 MUIA_Window_Screen, ( IPTR )lunaPubScreen,
987 MUIA_Window_ID, MAKE_ID('L','P','W','C'),
988 MUIA_Window_MouseObject, ( IPTR )canvases->mouse,
989 MUIA_Window_ScreenTitle, ( IPTR )VERSION,
990 MUIA_Window_UseRightBorderScroller, TRUE,
991 MUIA_Window_UseBottomBorderScroller, TRUE,
992 MUIA_Window_IsSubWindow, TRUE,
993 WindowContents, ( IPTR )VGroup,
994 InnerSpacing( 0, 0 ),
995 MUIA_Group_HorizSpacing, 0,
996 MUIA_Group_VertSpacing, 0,
997 Child, ( IPTR )VGroup,
998 InnerSpacing( 0, 0 ),
999 MUIA_Group_HorizSpacing, 0,
1000 MUIA_Group_VertSpacing, 0,
1001 Child, ( IPTR )( canvases->container = VGroup,
1002 InnerSpacing( 0, 0 ),
1003 MUIA_Group_HorizSpacing, 0,
1004 MUIA_Group_VertSpacing, 0,
1005 Child, ( IPTR )( canvases->area = NewObject(
1006 mcc->mcc_Class, NULL,
1007 MUIA_FillArea, FALSE,
1008 MUIA_Frame, MUIV_Frame_None,
1009 InnerSpacing( 0, 0 ),
1010 TAG_DONE
1011 ) ),
1012 End ),
1013 Child, ( IPTR )HGroup,
1014 MUIA_Group_SameHeight, TRUE,
1015 MUIA_Frame, MUIV_Frame_Group,
1016 InnerSpacing ( 4, 4 ),
1017 MUIA_Background, MUII_FILL,
1018 MUIA_Group_Child, ( IPTR )HGroup,
1019 MUIA_Frame, MUIV_Frame_None,
1020 InnerSpacing ( 3, 3 ),
1021 MUIA_Weight, 100,
1022 Child, ( IPTR )( canvases->txtLayerInf = TextObject,
1023 MUIA_Text_Contents, _(MSG_CANVAS_LAYER2),
1024 End ),
1025 Child, ( IPTR )( canvases->txtFrameInf = TextObject,
1026 MUIA_Text_Contents, _(MSG_CANVAS_FRAME2),
1027 End ),
1028 Child, ( IPTR )( canvases->txtZoomLevel = TextObject,
1029 MUIA_Text_Contents, _(MSG_CANVAS_ZOOM2),
1030 End ),
1031 Child, ( IPTR )( canvases->txtCoordX = TextObject,
1032 MUIA_Text_Contents, "X: 0 " ,
1033 End ),
1034 Child, ( IPTR )( canvases->txtCoordY = TextObject,
1035 MUIA_Text_Contents, "Y: 0 ",
1036 End ),
1037 Child, ( IPTR )RectangleObject, MUIA_Weight, 20, End,
1038 End,
1039 Child, ( IPTR )HGroup,
1040 MUIA_InnerTop, 0,
1041 MUIA_InnerLeft, 0,
1042 MUIA_InnerRight, 0,
1043 MUIA_InnerBottom, 0,
1044 MUIA_Weight, 40,
1045 Child, ( IPTR )( canvases->btnZoom = SimpleButton ( ( IPTR )"+" ) ),
1046 Child, ( IPTR )( canvases->btnUnZoom = SimpleButton ( ( IPTR )"-" ) ),
1047 Child, ( IPTR )( canvases->btnShowAll = SimpleButton ( ( IPTR )"1:1" ) ),
1048 End,
1049 End,
1050 End,
1051 Child, ( IPTR )( canvases->scrollH = ScrollbarObject,
1052 MUIA_Prop_UseWinBorder, MUIV_Prop_UseWinBorder_Bottom,
1053 End ),
1054 Child, ( IPTR )( canvases->scrollV = ScrollbarObject,
1055 MUIA_Prop_UseWinBorder, MUIV_Prop_UseWinBorder_Right,
1056 End ),
1057 End,
1058 TAG_END );
1060 // Some values in the area object
1061 struct RGBitmapData *areaData = INST_DATA ( mcc->mcc_Class, canvases->area );
1062 areaData->window = canvases;
1063 areaData->mousepressed = FALSE;
1064 canvases->id = globalWindowIncrement;
1065 canvases->layersChg = TRUE; // initially, say yes layers changed
1066 canvases->prevBlit = ( struct RectStruct ){ 0, 0, 0, 0 };
1067 canvases->filename = NULL; // set the filename to null *obviously*
1068 canvases->rRectX = 0;
1069 canvases->rRectY = 0;
1070 canvases->rRectW = 0;
1071 canvases->rRectH = 0;
1072 canvases->contWidth = 0;
1073 canvases->contHeight = 0;
1075 // Add project func to hook
1076 canvases->projHook.h_Entry = ( HOOKFUNC )projFunc;
1078 // Setup canvas
1080 canvases->canvas = Init_Canvas ( width, height, layers, frames, generateCanvas );
1081 canvases->nextwin = temp;
1083 if ( canvases->canvas->buffer != NULL )
1084 setActiveBuffer ( canvases->canvas );
1086 // Add the canvas window to the application gui
1087 DoMethod ( PaintApp, OM_ADDMEMBER, ( IPTR )canvases->win );
1089 // Generate window object and add it to the application gui
1090 CreateProjectWindow ( canvases );
1092 // Add some methods
1093 DoMethod (
1094 canvases->btnZoom, MUIM_Notify, MUIA_Pressed, FALSE,
1095 ( IPTR )canvases->area, 1, MUIM_Luna_ZoomIn
1097 DoMethod (
1098 canvases->btnUnZoom, MUIM_Notify, MUIA_Pressed, FALSE,
1099 ( IPTR )canvases->area, 1, MUIM_Luna_ZoomOut
1101 DoMethod (
1102 canvases->btnShowAll, MUIM_Notify, MUIA_Pressed, FALSE,
1103 ( IPTR )canvases->area, 1, MUIM_Luna_ShowAll
1105 DoMethod (
1106 canvases->win, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
1107 ( IPTR )canvases->area, 1, MUIM_Luna_CloseCanvasWin
1110 DoMethod (
1111 canvases->win, MUIM_Notify, MUIA_Window_Activate, TRUE,
1112 ( IPTR )canvases->area, 1, MUIM_Luna_CanvasActivate
1115 DoMethod (
1116 canvases->win, MUIM_Notify, MUIA_Window_Activate, FALSE,
1117 ( IPTR )canvases->area, 1, MUIM_Luna_CanvasDeactivate
1120 DoMethod (
1121 canvases->scrollV, MUIM_Notify, MUIA_Prop_First, MUIV_EveryTime,
1122 ( IPTR )canvases->area, 1, MUIM_Luna_Canvas_ScrollingNotify
1125 DoMethod (
1126 canvases->scrollH, MUIM_Notify, MUIA_Prop_First, MUIV_EveryTime,
1127 ( IPTR )canvases->area, 1, MUIM_Luna_Canvas_ScrollingNotify
1130 DoMethod ( canvases->win, MUIM_Notify, MUIA_Window_Open, TRUE,
1131 canvases->win, 2, MUIM_CallHook, &EnableKeyboard_hook );
1133 // Set global thingies
1134 globalActiveWindow = canvases;
1135 globalActiveCanvas = canvases->canvas;
1137 globalWindowIncrement++;
1140 void showFullscreenWindow ( struct oCanvas *canvas )
1142 // Prevent tool preview
1143 int Tool = globalCurrentTool;
1144 globalCurrentTool = -1;
1146 // Set some vars, we need no interference
1147 fullscreenEditing = TRUE;
1148 keyboardEnabled = TRUE;
1150 // Hide all other canvas windows
1151 struct WindowList *l = canvases;
1154 set ( l->win, MUIA_Window_Open, FALSE );
1156 while ( ( l = l->nextwin ) );
1158 if ( !windowFullscreen )
1160 windowFullscreen = WindowObject,
1161 MUIA_Window_Title, ( IPTR )NULL,
1162 MUIA_Window_SizeGadget, FALSE,
1163 MUIA_Window_DepthGadget, FALSE,
1164 MUIA_Window_CloseGadget, FALSE,
1165 MUIA_Window_TopEdge, 0,
1166 MUIA_Window_LeftEdge, 0,
1167 MUIA_Window_DragBar, FALSE,
1168 MUIA_Window_Screen, ( IPTR ) lunaPubScreen,
1169 MUIA_Window_MouseObject, ( IPTR ) canvases->mouse,
1170 MUIA_Window_ScreenTitle, ( IPTR ) VERSION,
1171 MUIA_Window_UseRightBorderScroller, FALSE,
1172 MUIA_Window_UseBottomBorderScroller, FALSE,
1173 MUIA_Window_IsSubWindow, FALSE,
1174 MUIA_Window_Backdrop, TRUE,
1175 MUIA_Window_Borderless, TRUE,
1176 WindowContents, ( IPTR )( fullscreenGroup = VGroup,
1177 InnerSpacing ( 0, 0 ),
1178 MUIA_Group_HorizSpacing, 0,
1179 MUIA_Group_VertSpacing, 0,
1180 MUIA_Background, ( IPTR )"5:PROGDIR:data/backdrop.png",
1181 End ),
1182 End;
1183 DoMethod ( PaintApp, OM_ADDMEMBER, ( IPTR )windowFullscreen );
1186 DoMethod ( globalActiveWindow->container, MUIM_Group_InitChange );
1187 DoMethod ( globalActiveWindow->container, OM_REMMEMBER, ( IPTR )globalActiveWindow->area );
1188 DoMethod ( globalActiveWindow->container, MUIM_Group_ExitChange );
1190 DoMethod ( fullscreenGroup, MUIM_Group_InitChange );
1191 DoMethod ( fullscreenGroup, OM_ADDMEMBER, ( IPTR )globalActiveWindow->area );
1192 DoMethod ( fullscreenGroup, MUIM_Group_ExitChange );
1194 set ( windowFullscreen, MUIA_Window_Open, TRUE );
1196 // Ideal width/height
1197 WORD width = lunaPubScreen->Width;
1198 WORD height = lunaPubScreen->Height;
1199 struct Window *win = ( struct Window *)XGET ( windowFullscreen, MUIA_Window_Window );
1200 ChangeWindowBox( win, 0, 0, width, height );
1202 globalCurrentTool = Tool;
1205 void hideFullscreenWindow ( )
1207 // Prevent tool preview
1208 int Tool = globalCurrentTool;
1209 globalCurrentTool = -1;
1211 // Let us hide the fullscreen window
1212 set ( windowFullscreen, MUIA_Window_Open, FALSE );
1214 // Remove from fullscreen window and add to container
1215 DoMethod ( fullscreenGroup, MUIM_Group_InitChange );
1216 DoMethod ( fullscreenGroup, OM_REMMEMBER, ( IPTR )globalActiveWindow->area );
1217 DoMethod ( fullscreenGroup, MUIM_Group_ExitChange );
1218 DoMethod ( globalActiveWindow->container, MUIM_Group_InitChange );
1219 DoMethod ( globalActiveWindow->container, OM_ADDMEMBER, ( IPTR )globalActiveWindow->area );
1220 DoMethod ( globalActiveWindow->container, MUIM_Group_ExitChange );
1223 // Show all other canvas windows
1224 struct WindowList *l = canvases;
1225 while ( l != NULL )
1227 set ( l->win, MUIA_Window_Open, TRUE );
1228 l = l->nextwin;
1231 // Last part
1232 fullscreenEditing = FALSE;
1234 // Ideal width/height
1235 WORD width = 640;
1236 WORD height = 480;
1237 struct Window *win = ( struct Window *)XGET ( globalActiveWindow->win, MUIA_Window_Window );
1238 ChangeWindowBox( win, 0, 0, width, height );
1240 globalCurrentTool = Tool;
1243 Object *getCanvaswindowById ( unsigned int id )
1245 struct WindowList *tmp = canvases;
1247 while ( tmp != NULL )
1249 if ( tmp->id == id )
1250 return tmp->win;
1251 tmp = tmp->nextwin;
1253 return NULL;
1256 struct WindowList *getCanvasDataById ( unsigned int id )
1258 struct WindowList *tmp = canvases;
1260 while ( tmp != NULL )
1262 if ( tmp->id == id )
1263 return tmp;
1264 tmp = tmp->nextwin;
1266 return NULL;
1269 void deleteCanvaswindows ( )
1271 struct WindowList *tmp = NULL;
1273 while ( canvases != NULL )
1275 tmp = canvases->nextwin;
1276 set ( canvases->win, MUIA_Window_Open, FALSE );
1278 DoMethod ( PaintApp, OM_REMMEMBER, ( IPTR )canvases->win );
1279 if ( canvases->win != NULL ) DoMethod ( PaintApp, OM_REMMEMBER, ( IPTR )canvases->win );
1281 Destroy_Canvas ( canvases->canvas );
1282 DestroyProjectWindow ( canvases );
1284 if ( canvases->filename != NULL )
1285 FreeVec ( canvases->filename );
1286 if ( canvases != NULL )
1287 FreeVec ( canvases );
1289 canvases = tmp;
1293 IPTR removeActiveWindow ( Class *CLASS, Object *self )
1295 struct RGBitmapData *data = INST_DATA ( CLASS, self );
1296 set ( data->window->win, MUIA_Window_Open, FALSE );
1297 DoMethod ( PaintApp, OM_REMMEMBER, ( IPTR )data->window->win );
1299 struct WindowList *tmp = NULL;
1300 struct WindowList *ptr = canvases;
1301 struct WindowList *prev = NULL;
1303 while ( ptr != NULL )
1305 tmp = ptr->nextwin;
1307 if ( ptr == globalActiveWindow )
1309 // Free memory
1310 Destroy_Canvas ( ptr->canvas );
1311 DestroyProjectWindow ( ptr );
1312 if ( ptr->filename != NULL )
1313 FreeVec ( ptr->filename );
1314 if ( ptr != NULL )
1315 FreeVec ( ptr );
1317 // Disconnect ptr from canvases chain
1318 if ( prev == NULL )
1320 canvases = tmp;
1321 break;
1323 prev->nextwin = tmp;
1324 ptr = tmp;
1326 prev = ptr;
1327 ptr = tmp;
1330 globalActiveWindow = canvases;
1331 globalActiveCanvas = NULL;
1333 //TODO: Lets reuse hidden windows in the future
1334 data->window->win = NULL;
1335 return ( IPTR )NULL;
1338 void blitAreaRect (
1339 int x, int y, int w, int h,
1340 struct oCanvas* canvas, struct RastPort *rp
1343 // Get zoom - bork bork
1344 int zoom = canvas->zoom;
1346 // Look for conflict with pixel coordinates and canvas dimensions
1347 // was 0 instead of offset on the two next lines
1349 int testofx = canvas->offsetx / zoom;
1350 int testofy = canvas->offsety / zoom;
1351 if ( x < testofx ){ w -= testofx - x; x = testofx; }
1352 if ( y < testofy ){ h -= testofy - y; y = testofy; }
1353 if ( x >= ( int )canvas->width ) w = 0; // terminates func
1354 if ( y >= ( int )canvas->height ) h = 0; // terminates func
1355 if ( x + w >= ( int )canvas->width ) w = ( int )canvas->width - x;
1356 if ( y + h >= ( int )canvas->height ) h = ( int )canvas->height - y;
1358 // Look for conflict with onscreen coordinates and widget
1359 // dimentions
1361 double sx = ( x * zoom ) - ( ( canvas->offsetx / zoom ) * zoom );
1362 double sy = ( y * zoom ) - ( ( canvas->offsety / zoom ) * zoom );
1363 double sw = w * zoom;
1364 double sh = h * zoom;
1365 if ( sx < 0 ){ sw += sx; sx = 0; }
1366 if ( sy < 0 ){ sh += sy; sy = 0; }
1367 if ( sx >= canvas->visibleWidth ) sw = 0;
1368 if ( sy >= canvas->visibleHeight ) sh = 0;
1369 if ( sx + sw > canvas->visibleWidth ) sw = canvas->visibleWidth - sx;
1370 if ( sy + sh > canvas->visibleHeight ) sh = canvas->visibleHeight - sy;
1372 // TODO: Check for tool preview size and add to update area
1373 // dimensions!
1375 if ( sw > 0 && sh > 0 )
1377 // Update screenbuffer
1378 if ( redrawScreenbufferRect ( canvas, x, y, w, h, FALSE ) )
1380 WritePixelArray (
1381 canvas->screenbuffer, 0, 0, canvas->visibleWidth * 4, rp,
1382 ( int )sx + _getAreaOffsetX ( ) + _getAreaLeft ( ),
1383 ( int )sy + _getAreaOffsetY ( ) + _getAreaTop ( ),
1384 ( int )sw, ( int )sh, RECTFMT_RAW
1390 void importImageRAW ( unsigned int w, unsigned int h, unsigned long long int *buffer )
1392 // We have a filename!!
1393 char *filename = getFilename ( );
1394 if ( filename != NULL )
1396 if ( getFilesize ( filename ) == 8 * w * h )
1398 // The aros way!
1399 BPTR myfile;
1400 if ( ( myfile = Open ( filename, MODE_OLDFILE ) ) != BNULL )
1402 Read ( myfile, buffer, 8 * w * h );
1403 Close ( myfile );
1404 MUI_Redraw ( globalActiveWindow->area, MADF_DRAWUPDATE );
1407 FreeVec ( filename );
1411 BOOL loadDatatypeImage ( )
1413 char *filename = getFilename ( );
1414 BOOL result = FALSE;
1416 if ( filename != NULL )
1418 unsigned int size = getFilesize ( filename );
1420 if ( size > 0 )
1423 Object *myDtObj = NewDTObject (
1424 ( APTR )filename,
1425 DTA_GroupID, GID_PICTURE,
1426 PDTA_Remap, TRUE,
1427 PDTA_DestMode, PMODE_V43,
1428 PDTA_Screen, ( IPTR )lunaPubScreen,
1429 TAG_END
1432 if ( myDtObj != NULL )
1435 struct BitMapHeader *bHead = NULL;
1436 struct pdtBlitPixelArray message;
1438 GetDTAttrs ( myDtObj, PDTA_BitMapHeader, &bHead, TAG_END );
1440 // Do some memtests before you commence
1441 BOOL proceed = TRUE;
1443 unsigned long long int *memtest =
1444 AllocVec ( bHead->bmh_Width * bHead->bmh_Height * 8 * 3, MEMF_ANY );
1445 if ( memtest == NULL )
1446 proceed = FALSE;
1447 else FreeVec ( memtest );
1449 unsigned int *bitmap = AllocVec ( bHead->bmh_Width * bHead->bmh_Height * 4, MEMF_ANY );
1450 if ( bitmap == NULL )
1451 proceed = FALSE;
1453 // We are proceeding!
1454 if ( proceed )
1456 message.MethodID = PDTM_READPIXELARRAY;
1457 message.pbpa_PixelData = bitmap;
1458 message.pbpa_PixelFormat = PBPAFMT_RGBA;
1459 message.pbpa_PixelArrayMod = bHead->bmh_Width * 4;
1460 message.pbpa_Left = 0;
1461 message.pbpa_Top = 0;
1462 message.pbpa_Width = bHead->bmh_Width;
1463 message.pbpa_Height = bHead->bmh_Height;
1465 DoMethodA ( myDtObj, ( Msg )&message );
1467 addCanvaswindow (
1468 bHead->bmh_Width, bHead->bmh_Height, 1, 1, TRUE
1471 int y = 0; for ( ; y < bHead->bmh_Height; y++ )
1473 int pixy = y * bHead->bmh_Width;
1474 int x = 0; for ( ; x < bHead->bmh_Width; x++ )
1476 unsigned long long int r = 0ULL, g = 0ULL, b = 0ULL, a = 0ULL;
1478 unsigned int p = bitmap[ pixy + x ];
1480 r = ( ( p << 24 ) >> 24 ) * 256;
1481 g = ( ( p << 16 ) >> 24 ) * 256;
1482 b = ( ( p << 8 ) >> 24 ) * 256;
1483 if ( bHead->bmh_Depth == 24 )
1484 a = 65535;
1485 else
1486 a = ( p >> 24 ) * 256;
1488 globalActiveCanvas->activebuffer[ pixy + x ] =
1489 ( r << 48 ) | ( g << 32 ) | ( b << 16 ) | a;
1493 FreeVec ( bitmap );
1494 DisposeDTObject ( myDtObj );
1495 set ( globalActiveWindow->win, MUIA_Window_Title, ( STRPTR )filename );
1496 set ( globalActiveWindow->projName, MUIA_String_Contents, ( STRPTR )filename );
1497 result = TRUE;
1499 else printf ( "Not enough memory.\n" );
1503 FreeVec ( filename );
1505 return result;
1508 void removePrevToolPreview ( )
1510 if ( globalActiveWindow->prevBlit.w > 0 && globalActiveWindow->prevBlit.h > 0 )
1512 int Tool = globalCurrentTool;
1513 globalCurrentTool = -1;
1515 // Blit over prev pos
1516 blitAreaRect (
1517 globalActiveWindow->prevBlit.x, globalActiveWindow->prevBlit.y,
1518 globalActiveWindow->prevBlit.w, globalActiveWindow->prevBlit.h,
1519 globalActiveCanvas, _rp ( globalActiveWindow->area )
1522 globalCurrentTool = Tool;
1524 // Clear prevblit coords
1525 globalActiveWindow->prevBlit.x = 0;
1526 globalActiveWindow->prevBlit.y = 0;
1527 globalActiveWindow->prevBlit.w = 0;
1528 globalActiveWindow->prevBlit.h = 0;
1532 void callToolPreview ( )
1534 if ( globalActiveWindow == NULL )
1535 return;
1537 // Some vars to be used
1538 int x = 0, y = 0, w = 1, h = 1; double offx = 0.0, offy = 0.0;
1540 switch ( globalCurrentTool )
1542 case LUNA_TOOL_FILL:
1543 case LUNA_TOOL_COLORPICKER:
1545 x = cMouseX;
1546 y = cMouseY;
1547 w = 1;
1548 h = 1;
1550 break;
1552 case LUNA_TOOL_BRUSH:
1554 offx = ( double )brushTool.width / 2;
1555 offy = ( double )brushTool.height / 2;
1556 x = cMouseX - offx;
1557 y = cMouseY - offy;
1558 w = brushTool.width;
1559 h = brushTool.height;
1560 break;
1562 case LUNA_TOOL_LINE:
1564 if ( lineTool.mode == 0 )
1566 offx = ( double )brushTool.width / 2;
1567 offy = ( double )brushTool.height / 2;
1568 x = cMouseX - offx;
1569 y = cMouseY - offy;
1570 w = brushTool.width;
1571 h = brushTool.height;
1573 else if ( lineTool.mode == 1 )
1575 x = lineTool.ox;
1576 y = lineTool.oy;
1577 w = lineTool.w;
1578 h = lineTool.h;
1580 break;
1582 case LUNA_TOOL_RECTANGLE:
1584 if ( rectangleTool.mode == 0 )
1586 offx = ( double )brushTool.width / 2;
1587 offy = ( double )brushTool.height / 2;
1588 x = cMouseX - offx;
1589 y = cMouseY - offy;
1590 w = brushTool.width;
1591 h = brushTool.height;
1593 else if ( rectangleTool.mode == 1 )
1595 x = rectangleTool.ox;
1596 y = rectangleTool.oy;
1597 w = rectangleTool.w;
1598 h = rectangleTool.h;
1600 break;
1602 case LUNA_TOOL_CIRCLE:
1604 if ( circleTool.mode == 0 )
1606 offx = ( double )brushTool.width / 2;
1607 offy = ( double )brushTool.height / 2;
1608 x = cMouseX - offx;
1609 y = cMouseY - offy;
1610 w = brushTool.width;
1611 h = brushTool.height;
1613 else if ( circleTool.mode == 1 )
1615 x = circleTool.ox;
1616 y = circleTool.oy;
1617 w = circleTool.bufwidth;
1618 h = circleTool.bufheight;
1620 break;
1622 case LUNA_TOOL_CLIPBRUSH:
1624 if ( clipbrushTool.mode == 0 )
1626 x = cMouseX;
1627 y = cMouseY;
1628 w = 1;
1629 h = 1;
1631 else if ( clipbrushTool.mode == 1 )
1633 x = clipbrushTool.ox;
1634 y = clipbrushTool.oy;
1635 w = clipbrushTool.w;
1636 h = clipbrushTool.h;
1638 break;
1640 default: break;
1643 if ( !w || !h ) return;
1644 blitToolPreview ( x - 1, y - 1, w + 2, h + 2 );
1647 void blitToolPreview ( int x, int y, int w, int h )
1649 removePrevToolPreview ( );
1650 blitAreaRect ( x, y, w, h, globalActiveCanvas, _rp ( globalActiveWindow->area ) );
1651 globalActiveWindow->prevBlit = ( struct RectStruct ){ x, y, w, h };
1654 ULONG _getAreaWidth ( )
1656 ULONG ideal = globalActiveCanvas->width * globalActiveCanvas->zoom;
1657 ULONG view = XGET ( globalActiveWindow->area, MUIA_Width );
1658 if ( ideal < view )
1659 return ideal;
1660 return view;
1664 ULONG _getAreaHeight ( )
1666 ULONG ideal = globalActiveCanvas->height * globalActiveCanvas->zoom;
1667 ULONG view = XGET ( globalActiveWindow->area, MUIA_Height );
1668 if ( ideal < view )
1669 return ideal;
1670 return view;
1673 ULONG _getAreaTop ( )
1675 return XGET ( globalActiveWindow->area, MUIA_TopEdge );
1678 ULONG _getAreaLeft ( )
1680 return XGET ( globalActiveWindow->area, MUIA_LeftEdge );
1683 ULONG _getAreaOffsetX ( )
1685 ULONG screenOffX = XGET ( globalActiveWindow->area, MUIA_Width );
1686 ULONG view = _getAreaWidth ( );
1687 if ( screenOffX > view )
1688 screenOffX = ( screenOffX / 2.0 ) - ( view / 2.0 );
1689 else screenOffX = 0;
1690 return screenOffX;
1693 ULONG _getAreaOffsetY ( )
1695 ULONG screenOffY = XGET ( globalActiveWindow->area, MUIA_Height );
1696 ULONG view = _getAreaHeight ( );
1697 if ( screenOffY > view )
1698 screenOffY = ( screenOffY / 2.0 ) - ( view / 2.0 );
1699 else screenOffY = 0;
1700 return screenOffY;