Removed -D__MORPHOS__ from the makefiles.
[AROS-Contrib.git] / vpdf / mcc / pageview_class.c
blobf4563a4db2f53547e1d9e76686e24701e91cc635
1 /*
3 This is a simple version of the preview class. No subtasks,
4 and no context menu. It also keeps it's copy of passed image,
5 so no need to keep if for yourself.
8 */
10 #define AROS_ALMOST_COMPATIBLE
12 #include <proto/muimaster.h>
13 #include <libraries/mui.h>
15 #include <proto/exec.h>
16 #include <proto/utility.h>
17 #include <exec/libraries.h>
18 #include <graphics/gfx.h>
19 #include <proto/alib.h>
20 #include <proto/graphics.h>
21 #include <graphics/rpattr.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <math.h>
26 #include <limits.h>
27 #include <constructor.h>
28 #include <intuition/pointerclass.h>
30 #define SYSTEM_PRIVATE
31 #include <proto/cybergraphics.h>
32 #include <cybergraphx/cybergraphics.h>
33 #undef SYSTEM_PRIVATE
35 #include <private/vapor/vapor.h>
36 #include "pageview_class.h"
37 #include "documentview_class.h"
38 #include "documentlayout_class.h"
39 #include "annotation_class.h"
41 #include "system/chunky.h"
42 #include "system/memory.h"
43 #include "system/functions.h"
45 #include "util.h"
46 #include "poppler.h"
48 typedef struct ThbImage_s
50 unsigned char *data;
51 int width;
52 int height;
53 int bpp; // can be 1 or 4
54 } ThbImage;
56 struct markernode {
57 struct MinNode n;
58 float x1, y1, x2, y2; // pdf document device coordinates
59 int ux1, uy1, ux2, uy2; // user space coordinates
60 int valid, id;
61 unsigned int color;
64 struct annotationnode {
65 struct MinNode n;
66 float x1, y1, x2, y2;
67 int ux1, uy1, ux2, uy2;
68 Object *obj;
71 struct lasso {
72 int enabled;
73 struct markernode marker;
74 struct pdfSelectionRegion *oldregion;
77 struct Data
79 ThbImage *image;
80 void *parent;
81 struct MUI_EventHandlerNode eh;
82 struct PageViewRegion region;
83 int mx, my;
84 int moveregion;
85 int offsetx, offsety;
86 int markmx, markmy;
87 int pointertype;
88 int mousedown;
89 int markAspect;
90 struct Rect32 refreshrect;
91 int layoutwidth;
92 int layoutheight;
94 void *doc;
95 int page;
96 int ready;
97 int prevwidth, prevheight;
98 int mediawidth, mediaheight;
99 int invalid;
100 int flushmethodid;
101 int information;
102 int ispreview;
103 int rotation;
105 int quiet;
107 struct lasso lasso;
108 struct MinList markerlist;
109 struct MinList annotationlist;
111 struct SignalSemaphore sema;
114 #define D(x) x
117 * MUI Standard methods
120 /// dispose
122 DEFDISP
124 GETDATA;
126 ObtainSemaphore(&data->sema);
127 if (data->image != NULL)
128 mfree(data->image->data);
129 free(data->image);
130 ReleaseSemaphore(&data->sema);
132 if (data->lasso.oldregion != NULL)
133 pdfDisposeRegionForSelection(data->doc, data->lasso.oldregion);
135 /* remove all markers and annotations (only links to annotation objects!) */
137 while(!ISLISTEMPTY(&data->markerlist))
139 struct markernode *mn = (struct markernode*)GetHead(&data->markerlist);
140 REMOVE(mn);
141 free(mn);
144 while(!ISLISTEMPTY(&data->annotationlist))
146 struct annotationnode *an = (struct annotationnode*)GetHead(&data->annotationlist);
147 REMOVE(an);
148 free(an);
151 /* dispose parent class */
153 return(DOSUPER);
156 ////
158 /// askminmax
160 static int getinformationspace(Object *obj, struct Data *data)
162 int space = 0;
163 if (data->information & MUIV_PageView_Information_Number)
164 space += _font(obj)->tf_YSize + 2;
166 return space;
169 METHOD ThbAskMinMax(struct IClass *cl,Object *obj,struct MUIP_AskMinMax *msg)
171 GETDATA;
174 let our superclass first fill in what it thinks about sizes.
175 this will e.g. add the size of frame and inner spacing.
178 DOSUPER;
181 now add the values specific to our object. note that we
182 indeed need to *add* these values, not just set them!
185 msg->MinMaxInfo->MinWidth += data->layoutwidth;
186 msg->MinMaxInfo->DefWidth += data->layoutwidth;
187 msg->MinMaxInfo->MaxWidth = MUI_MAXMAX;
189 msg->MinMaxInfo->MinHeight += data->layoutheight + getinformationspace(obj, data);
190 msg->MinMaxInfo->DefHeight += data->layoutheight + getinformationspace(obj, data);
191 msg->MinMaxInfo->MaxHeight = MUI_MAXMAX;
193 return(0);
196 ////
198 /// new
200 DEFNEW
202 obj = DoSuperNew(cl, obj, MUIA_FillArea, FALSE,
203 // MUIA_CustomBackfill, TRUE,
204 // MUIA_Background, MUII_SHADOW,
205 TAG_MORE, INITTAGS);
207 if (obj != NULL)
209 GETDATA;
211 memset(data, 0, sizeof(struct Data));
213 InitSemaphore(&data->sema);
214 NEWLIST(&data->markerlist);
215 NEWLIST(&data->annotationlist);
217 /* get properties */
219 data->refreshrect.MinX = -1;
220 data->layoutwidth = 128;
221 data->layoutheight = 128;
222 data->information = MUIV_PageView_Information_None;
224 FORTAG(INITTAGS)
226 case MUIA_PageView_Rotation:
227 data->rotation = tag->ti_Data;
228 break;
230 case MUIA_PageView_PDFDocument:
231 data->doc = (void*)tag->ti_Data;
232 break;
233 case MUIA_PageView_Page:
234 data->page = tag->ti_Data;
235 break;
236 case MUIA_PageView_MediaWidth:
237 data->mediawidth = tag->ti_Data;
238 break;
239 case MUIA_PageView_MediaHeight:
240 data->mediaheight = tag->ti_Data;
241 break;
242 case MUIA_PageView_Information:
243 data->information = tag->ti_Data;
244 break;
245 case MUIA_PageView_IsPreview:
246 data->ispreview= tag->ti_Data;
247 break;
249 NEXTTAG
253 return (ULONG)obj;
257 ////
259 /// setup
261 METHOD riSetup(struct IClass *cl, Object *obj, struct MUIP_Setup *msg)
263 GETDATA;
265 if (!(DOSUPER))
266 return(FALSE);
268 return TRUE;
271 ////
273 /// cleanup
275 METHOD riCleanup(struct IClass *cl,Object *obj,Msg msg)
277 GETDATA;
279 if (data->flushmethodid != 0)
281 DoMethod(_app(obj), MUIM_Application_UnpushMethod, NULL, data->flushmethodid, 0);
282 data->flushmethodid = 0;
285 DoMethod(obj, MUIM_PageView_Flush);
287 return(DOSUPER);
290 ////
292 /// draw
294 void kprintf(char *fmt,...);
296 static void rendermarker(struct Data *data, struct RastPort *rp, struct markernode *mn, int x0, int y0)
298 int x1 = mn->ux1, y1 = mn->uy1;
299 int x2 = mn->ux2, y2 = mn->uy2;
301 SetRPAttrs(rp, RPTAG_PenMode, FALSE, RPTAG_FgColor, 0xffff0000, TAG_DONE);
302 RectFill(rp, x0 + x1 - 2, y0 + y2 - 2, x0 + x2 + 2, y0 + y2 - 1);
303 RectFill(rp, x0 + x1 - 2, y0 + y1 + 1, x0 + x2 + 2, y0 + y1 + 2);
304 RectFill(rp, x0 + x1 - 2, y0 + y2, x0 + x1 - 1, y0 + y1);
305 RectFill(rp, x0 + x2 + 1, y0 + y2, x0 + x2 + 2, y0 + y1);
307 ProcessPixelArray(rp, x0 + x1 - 1, y0 + y2 - 1, x2 - x1, y1 - y2, POP_DARKEN, 10, NULL);
310 METHOD riDraw(struct IClass *cl,Object *obj,struct MUIP_Draw *msg)
312 unsigned int rc = DOSUPER;
313 //return rc;
314 /* If MADF_DRAWOBJECT is not set then we shoulnt draw anything */
316 if (msg->flags & (MADF_DRAWOBJECT | MADF_DRAWUPDATE))
318 GETDATA;
319 int activepage;
321 ObtainSemaphore(&data->sema);
323 if (data->parent == NULL)
324 data->parent = (void*)xget(obj, MUIA_Parent);
326 activepage = xget(data->parent, MUIA_DocumentLayout_Page);
328 if (data->image && data->image->data)
330 /* write image */
332 int width, height;
333 int x0, y0;
334 int prvwidth, prvheight;
336 ThbImage *image = data->image;
338 x0 = _mleft(obj);
339 y0 = _mtop(obj);
340 prvwidth = _mwidth(obj);
341 prvheight = _mheight(obj) - getinformationspace(obj, data);
343 /* calculate placement */
345 if (image->height < prvheight)
347 y0 += (prvheight - image->height) / 2;
348 height = image->height;
350 else
351 height = prvheight;
353 if (image->width < prvwidth)
355 x0 += (prvwidth - image->width) / 2;
356 width = image->width;
358 else
359 width = prvwidth;
361 /* store offset for eventhandler */
363 data->offsetx = x0 - _mleft(obj);
364 data->offsety = y0 - _mtop(obj);
366 /* install cliprect and draw */
368 if (data->quiet == FALSE)
370 if (0 && data->refreshrect.MinX != -1)
372 width = data->refreshrect.MaxX - data->refreshrect.MinX;
373 height = data->refreshrect.MaxY - data->refreshrect.MinY;
374 WritePixelArray(image->data, data->refreshrect.MinX, data->refreshrect.MinY, image->width * image->bpp, _rp(obj), x0 + data->refreshrect.MinX, y0 + data->refreshrect.MinY, width, height, image->bpp == 4 ? RECTFMT_ARGB : RECTFMT_GREY8);
376 else
377 WritePixelArray(image->data, 0, 0, image->width * image->bpp, _rp(obj), x0, y0, width, height, data->image->bpp == 4 ? RECTFMT_ARGB : RECTFMT_GREY8);
379 /* draw remaining area with background */
381 if ((image->width < _mwidth(obj) || image->height < _mheight(obj)))
383 int lb = x0 - _mleft(obj);
384 int rb = _mwidth(obj) - image->width - lb;
385 int tb = y0 - _mtop(obj);
386 int bb = _mheight(obj) - image->height - tb;
387 #if 1
388 if (lb > 0)
389 DoMethod(obj, MUIM_DrawBackground, _mleft(obj), _mtop(obj), lb, _mheight(obj), 0, 0, 0);
390 if (rb > 0)
391 DoMethod(obj, MUIM_DrawBackground, _mright(obj) - rb + 1, _mtop(obj), rb, _mheight(obj), 0, 0, 0);
393 lb = max(0, lb);
394 rb = max(0, rb);
396 if (tb > 0)
397 DoMethod(obj, MUIM_DrawBackground, _mleft(obj) + lb, _mtop(obj), _mwidth(obj) - lb - rb, tb, 0, 0, 0);
398 if (bb > 0)
399 DoMethod(obj, MUIM_DrawBackground, _mleft(obj) + lb, _mbottom(obj) - bb + 1, _mwidth(obj) - lb - rb, bb, 0, 0, 0);
400 #endif
403 /* render page number if requested */
405 if (data->information & MUIV_PageView_Information_Number)
407 char buff[32];
408 int informationspace = getinformationspace(obj, data);
409 int textwidth, textpos;
410 unsigned int textdim;
412 snprintf(buff, sizeof(buff), "%d", data->page);
414 textdim = DoMethod(obj, MUIM_TextDim, buff, strlen(buff), 0, 0);
415 textwidth = textdim & 0xffff;
416 textpos = _mwidth(obj) /2 - textwidth / 2;
417 DoMethod(obj, MUIM_Text, _mleft(obj) + textpos, _mbottom(obj) - informationspace, _mwidth(obj), informationspace, buff, strlen(buff), 0, 0);
421 /* draw active page marker (TODO: make it flickerfree) */
423 if (data->page == activepage)
425 SetRPAttrs(_rp(obj), RPTAG_PenMode, FALSE, RPTAG_FgColor, 0xffff0000, TAG_DONE);
426 RectFill(_rp(obj), x0, y0, x0 + width - 1, y0 + 1);
427 RectFill(_rp(obj), x0, y0 + height - 2, x0 + width - 1, y0 + height - 1);
428 RectFill(_rp(obj), x0, y0, x0 + 1, y0 + height - 1);
429 RectFill(_rp(obj), x0 + width - 2, y0, x0 + width - 1, y0 + height - 1);
432 /* draw selection markers (TODO: make it flickerfree) */
434 if (!ISLISTEMPTY(&data->markerlist))
436 struct markernode *mn;
438 ITERATELIST(mn, &data->markerlist)
440 rendermarker(data, _rp(obj), mn, x0, y0);
444 /* render lasso */
446 if (data->lasso.enabled)
448 rendermarker(data, _rp(obj), &data->lasso.marker, x0, y0);
453 else if (data->quiet == FALSE)
455 DoMethod(obj, MUIM_DrawBackground, _mleft(obj), _mtop(obj), _mwidth(obj), _mheight(obj), 0, 0, 0);
458 if (data->image == NULL || data->image->data == NULL || data->invalid /*|| data->prevwidth != _mwidth(obj) || data->prevheight != _mheight(obj)*/)
460 /* setup needrefresh param so the main app can rerender page */
461 //data->prevwidth = _mwidth(obj);
462 //data->prevheight = _mheight(obj);
463 data->invalid = FALSE;
464 SetAttrs(_parent(obj), MUIA_Group_Forward, FALSE, MUIA_PageView_NeedRefresh, data->page, TAG_DONE);
467 ReleaseSemaphore(&data->sema);
470 return rc;
473 ////
475 /// render selection region
477 static void renderselectionregion(Object *obj, struct Data *data, struct pdfSelectionRegion *selection)
479 if (selection != NULL && data->image != NULL && data->image->data != NULL)
481 int i;
482 for(i=0; i<selection->numrects; i++)
484 int px, py;
485 int pw, ph;
487 int x, y;
488 struct pdfSelectionRectangle *rect = &selection->rectangles[i];
490 if (1)
491 for(y=rect->y1 * data->image->height; y<=rect->y2 * data->image->height; y++)
493 if (data->image->bpp == 4)
495 unsigned int *img = (unsigned int*)data->image->data;
496 int width = data->image->width;
498 for(x=rect->x1 * data->image->width; x<=rect->x2 * data->image->width; x++)
500 if (x >= 0 && y >= 0 && x < data->image->width && y < data->image->height)
501 img[x + width * y] = 0x00ffffff ^ img[x + width * y];
504 else if (data->image->bpp == 1)
506 unsigned char *img = (unsigned char*)data->image->data;
507 int width = data->image->width;
509 for(x=rect->x1 * data->image->width; x<=rect->x2 * data->image->width; x++)
511 if (x >= 0 && y >= 0 && x < data->image->width && y < data->image->height)
512 img[x + width * y] = 0xff ^ img[x + width * y];
520 ////
522 /// updatemarkers (resize to device coords)
524 static void updatemarkers(Object *obj, struct Data *data, int all)
526 struct markernode *mn;
527 struct annotationnode *an;
528 //pdfLock(data->doc);
530 if (data->image != NULL && data->image->data != NULL)
533 ITERATELIST(mn, &data->markerlist)
535 //pdfConvertDeviceToUser(data->doc, data->page, mn->x1, mn->y1, &mn->ux1, &mn->uy1);
536 //pdfConvertDeviceToUser(data->doc, data->page, mn->x2, mn->y2, &mn->ux2, &mn->uy2);
538 float ox1 = mn->x1 - 0.5f, oy1 = mn->y1 - 0.5f;
539 float ox2 = mn->x2 - 0.5f, oy2 = mn->y2 - 0.5f;
540 float x1, x2, y1, y2;
541 float t;
543 if (data->rotation == 0)
545 x1 = ox1; y1 = oy1;
546 x2 = ox2; y2 = oy2;
548 else if (data->rotation == 1)
550 x1 = -oy1; y1 = ox1;
551 x2 = -oy2; y2 = ox2;
553 else if (data->rotation == 2)
555 x1 = -ox1; y1 = -oy1;
556 x2 = -ox2; y2 = -oy2;
558 else /*(data->rotation == 3)*/
560 x1 = oy1; y1 = -ox1;
561 x2 = oy2; y2 = -ox2;
564 if (x1 > x2) /*can happen after rotation */
566 t = x1;
567 x1 = x2;
568 x2 = t;
570 if (y1 < y2)
572 t = y1;
573 y1 = y2;
574 y2 = t;
577 x1 += 0.5f; y1 += 0.5f;
578 x2 += 0.5f; y2 += 0.5f;
580 mn->ux1 = x1 * data->image->width;
581 mn->uy1 = y1 * data->image->height;
582 mn->ux2 = x2 * data->image->width;
583 mn->uy2 = y2 * data->image->height;
584 mn->valid = TRUE;
587 ITERATELIST(an, &data->annotationlist)
589 //pdfConvertDeviceToUser(data->doc, data->page, mn->x1, mn->y1, &mn->ux1, &mn->uy1);
590 //pdfConvertDeviceToUser(data->doc, data->page, mn->x2, mn->y2, &mn->ux2, &mn->uy2);
592 float ox1 = an->x1 - 0.5f, oy1 = an->y1 - 0.5f;
593 float ox2 = an->x2 - 0.5f, oy2 = an->y2 - 0.5f;
594 float x1, x2, y1, y2;
595 float t;
597 if (data->rotation == 0)
599 x1 = ox1; y1 = oy1;
600 x2 = ox2; y2 = oy2;
602 else if (data->rotation == 1)
604 x1 = -oy1; y1 = ox1;
605 x2 = -oy2; y2 = ox2;
607 else if (data->rotation == 2)
609 x1 = -ox1; y1 = -oy1;
610 x2 = -ox2; y2 = -oy2;
612 else /*(data->rotation == 3)*/
614 x1 = oy1; y1 = -ox1;
615 x2 = oy2; y2 = -ox2;
618 if (x1 > x2) /*can happen after rotation */
620 t = x1;
621 x1 = x2;
622 x2 = t;
624 if (y1 < y2)
626 t = y1;
627 y1 = y2;
628 y2 = t;
631 x1 += 0.5f; y1 += 0.5f;
632 x2 += 0.5f; y2 += 0.5f;
634 an->ux1 = x1 * data->image->width;
635 an->uy1 = y1 * data->image->height;
636 an->ux2 = x2 * data->image->width;
637 an->uy2 = y2 * data->image->height;
640 SetAttrs(an->obj, MUIA_Annotation_PosX, an->ux1, MUIA_Annotation_PosY, an->uy1, TAG_DONE);
643 /* lasso. ignore page rotation as it can't change when marker is enabled */
646 struct markernode *mn = &data->lasso.marker;
647 //pdfConvertDeviceToUser(data->doc, data->page, mn->x1, mn->y1, &mn->ux1, &mn->uy1);
648 //pdfConvertDeviceToUser(data->doc, data->page, mn->x2, mn->y2, &mn->ux2, &mn->uy2);
650 float ox1 = mn->x1 - 0.5f, oy1 = mn->y1 - 0.5f;
651 float ox2 = mn->x2 - 0.5f, oy2 = mn->y2 - 0.5f;
652 float x1, x2, y1, y2;
653 float t;
655 x1 = ox1; y1 = oy1;
656 x2 = ox2; y2 = oy2;
658 if (x1 > x2) /*can happen for lasso */
660 t = x1;
661 x1 = x2;
662 x2 = t;
664 if (y1 < y2)
666 t = y1;
667 y1 = y2;
668 y2 = t;
671 x1 += 0.5f; y1 += 0.5f;
672 x2 += 0.5f; y2 += 0.5f;
674 mn->ux1 = x1 * data->image->width;
675 mn->uy1 = y1 * data->image->height;
676 mn->ux2 = x2 * data->image->width;
677 mn->uy2 = y2 * data->image->height;
678 mn->valid = TRUE;
682 //pdfRelease(data->doc);
685 ////
687 /// set
689 DEFSET
691 GETDATA;
693 FORTAG(INITTAGS)
696 case MUIA_PageView_LayoutWidth:
697 data->layoutwidth = tag->ti_Data;
698 data->invalid = TRUE;
699 break;
701 case MUIA_PageView_LayoutHeight:
702 data->layoutheight = tag->ti_Data;
703 data->invalid = TRUE;
704 break;
706 case MUIA_PageView_Page:
707 data->page = tag->ti_Data;
708 break;
710 case MUIA_PageView_PDFReady:
711 data->ready = tag->ti_Data;
712 break;
714 case MUIA_PageView_Quiet:
715 data->quiet = tag->ti_Data;
716 break;
718 case MUIA_PageView_PDFBitmap:
720 /* delete old image if present and create new. can NOT refresh display! */
722 ObtainSemaphore(&data->sema);
724 if (tag->ti_Data == NULL)
726 if (data->image != NULL)
728 mfree(data->image->data);
729 data->image->data = NULL;
732 else
734 if (data->image == NULL)
736 struct pdfBitmap *bm = (struct pdfBitmap*)tag->ti_Data;
738 data->image = calloc(1, sizeof(ThbImage));
740 data->region.x1 = 0;
741 data->region.y1 = 0;
742 data->region.x2 = bm->width - 1;
743 data->region.y2 = bm->height - 1;
746 if (data->image != NULL)
748 struct pdfBitmap *bm = (struct pdfBitmap*)tag->ti_Data;
749 int isgrayscale = TRUE;
750 int x, y;
752 for(y=0; y<bm->height; y++)
754 unsigned char *src = bm->data + bm->stride * y;
755 unsigned int rowdiff = 0;
756 for(x=bm->width; x>0; x--)
758 int r = src[1];
759 int g = src[2];
760 int b = src[3];
761 int different = (r | g | b) - (r & g & b); // hopefuly this works and is faster than two conditions
762 // when equal both terms should be equal so diff == 0
763 // also, when different it will always be > 0
765 rowdiff += different;
766 src += 4;
769 if (rowdiff != 0)
771 isgrayscale = FALSE;
772 break;
776 D(kprintf("image is grayscale:%d\n", isgrayscale));
778 data->image->width = bm->width;
779 data->image->height = bm->height;
780 data->image->bpp = isgrayscale ? 1 : 4;
781 data->image->data = mmalloc(bm->width * bm->height * data->image->bpp);
782 if (data->image->data != NULL)
784 int i, j;
785 for(i=0; i<bm->height; i++)
787 unsigned char *src = bm->data + bm->stride * i;
788 if (isgrayscale == FALSE)
789 memcpy((unsigned int*)data->image->data + i * bm->width, src, bm->width * 4);
790 else
792 unsigned char *dst = data->image->data + data->image->width * i;
793 for(j=bm->width; j>0; j--)
795 *dst++ = src[1];
796 src += 4;
803 updatemarkers(obj, data, TRUE);
804 renderselectionregion(obj, data, data->lasso.oldregion);
807 ReleaseSemaphore(&data->sema);
809 break;
811 case MUIA_PageView_Rotation:
813 data->rotation = tag->ti_Data;
814 data->invalid = TRUE;
815 break;
818 NEXTTAG;
820 return(DOSUPER);
823 ////
825 /// get
827 DEFGET
829 GETDATA;
831 switch (msg->opg_AttrID)
833 case MUIA_PageView_Width:
834 *(msg->opg_Storage) = (ULONG)(data->image ? data->image->width : 0);
835 return TRUE;
837 case MUIA_PageView_Height:
838 *(msg->opg_Storage) = (ULONG)(data->image ? data->image->height : 0);
839 return TRUE;
841 case MUIA_PageView_LayoutWidth:
842 *(msg->opg_Storage) = (ULONG)(data->layoutwidth);
843 return TRUE;
845 case MUIA_PageView_LayoutHeight:
846 *(msg->opg_Storage) = (ULONG)(data->layoutheight);
847 return TRUE;
849 case MUIA_PageView_Region:
850 *(msg->opg_Storage) = (ULONG)&data->region;
851 return TRUE;
853 case MUIA_PageView_Page:
854 *(msg->opg_Storage) = (ULONG)data->page;
855 return TRUE;
857 case MUIA_PageView_MediaWidth:
858 *(msg->opg_Storage) = (ULONG)data->mediawidth;
859 return TRUE;
861 case MUIA_PageView_MediaHeight:
862 *(msg->opg_Storage) = (ULONG)data->mediaheight;
863 return TRUE;
865 case MUIA_PageView_RedirectPage:
866 return TRUE;
868 case MUIA_PageView_NeedRefresh:
869 return TRUE;
871 case MUIA_PageView_RenderWidth:
872 *(msg->opg_Storage) = xget(obj, MUIA_Width);
873 return TRUE;
875 case MUIA_PageView_RenderHeight:
876 *(msg->opg_Storage) = xget(obj, MUIA_Height) - getinformationspace(obj, data);
877 return TRUE;
879 case MUIA_PageView_Rotation:
880 *(msg->opg_Storage) = data->rotation;
881 return TRUE;
885 return(DOSUPER);
888 ////
890 /// update
892 DEFMMETHOD(PageView_Update)
894 GETDATA;
896 data->refreshrect.MinX = msg->x;
897 data->refreshrect.MaxX = msg->x + msg->width;
898 data->refreshrect.MinY = msg->y;
899 data->refreshrect.MaxY = msg->y + msg->height;
901 MUI_Redraw(obj, MADF_DRAWUPDATE);
903 data->refreshrect.MinX = -1;
904 return 0;
907 ////
909 /// handleevent
911 METHOD riHandleEvent(struct IClass *cl,Object *obj,struct MUIP_HandleEvent *msg)
913 #define _between(a,x,b) ((x)>=(a) && (x)<=(b))
914 #define _isinobject(obj,x,y) (_between(vl,(x),vl+vw) && _between(vt,(y),vt+vh))
915 #define _isinimage(obj,x,y) (_between(vl + data->offsetx, (x), vl + vw - data->offsetx) && _between(vt + data->offsety,(y), vt + vh - data->offsety))
917 GETDATA;
918 int vl = _mleft(obj);
919 int vt = _mtop(obj);
920 int vw = _mwidth(obj);
921 int vh = _mheight(obj);
923 if (msg->imsg != NULL && _isinobject(obj, msg->imsg->MouseX, msg->imsg->MouseY)/* || data->eh.ehn_Events & IDCMP_MOUSEMOVE*/)
925 if (msg->imsg != NULL)
927 switch (msg->imsg->Class)
929 case IDCMP_MOUSEBUTTONS:
931 int mx = max(0, msg->imsg->MouseX - _left(obj) - data->offsetx);
932 int my = max(0, msg->imsg->MouseY - _top(obj) - data->offsety);
934 if (msg->imsg->Code == SELECTDOWN)
936 if (_isinimage(obj, msg->imsg->MouseX, msg->imsg->MouseY))
938 data->mousedown = TRUE;
939 if (data->ispreview == FALSE && data->lasso.enabled == FALSE && xget(objFindContainerByAttribute(obj, MUIA_DocumentView_DragAction), MUIA_DocumentView_DragAction) == MUIV_DocumentView_DragAction_Mark) /* first coord */
941 /* clear selection on all previous pages */
943 DoMethod(objFindContainerByAttribute(obj, MUIA_DocumentView_DragAction), MUIM_DocumentView_ClearSelection);
945 data->lasso.marker.x1 = data->lasso.marker.x2 = (float)mx / data->image->width;
946 data->lasso.marker.y1 = data->lasso.marker.y2 = (float)my / data->image->height;
947 data->lasso.enabled = TRUE;
951 else if (msg->imsg->Code == SELECTUP)
953 if (data->lasso.enabled)
955 data->lasso.enabled = FALSE;
957 else if (data->ready && !data->ispreview)
959 double x = mx;
960 double y = my;
961 void *link = pdfFindLink(data->doc, data->page, x, y);
962 if (link != NULL)
964 int page = pdfGetActionPageFromLink(data->doc, link);
965 //printf("find page:%d\n", page);
966 //char *url = linkGetActionURL(link);
967 if (page > 0)
968 set(_parent(obj), MUIA_PageView_RedirectPage, page);
971 /* lookup annotation and toggle */
972 if (!ISLISTEMPTY(&data->annotationlist))
974 struct annotationnode *an;
975 ITERATELIST(an, &data->annotationlist)
977 //printf("checking %d, %d vs %d,%d %d,%d\n", mx, my, an->ux1, an->uy1, an->ux2, an->uy2);
978 if (_between(an->ux1, mx, an->ux2) && _between(an->uy2, my, an->uy1))
980 DoMethod(an->obj, MUIM_Annotation_Toggle);
981 break;
987 else if (data->ispreview && data->mousedown) /* for page preview, like in outlines */
989 set(_parent(obj), MUIA_PageView_RedirectPage, data->page);
992 data->mousedown = TRUE;
994 break;
997 case IDCMP_MOUSEMOVE:
999 int mx = max(0, msg->imsg->MouseX - _left(obj) - data->offsetx);
1000 int my = max(0, msg->imsg->MouseY - _top(obj) - data->offsety);
1002 if (data->lasso.enabled)
1004 struct pdfSelectionRegion *selection;
1006 data->lasso.marker.x2 = min(1.0, (float)mx / data->image->width);
1007 data->lasso.marker.y2 = min(1.0, (float)my / data->image->height);
1009 /* fetch selection from pdf document */
1011 if (data->lasso.oldregion != NULL)
1013 renderselectionregion(obj, data, data->lasso.oldregion);
1014 pdfDisposeRegionForSelection(data->doc, data->lasso.oldregion);
1017 selection = pdfBuildRegionForSelection(data->doc, data->page, data->lasso.marker.x1, data->lasso.marker.y1, data->lasso.marker.x2, data->lasso.marker.y2, NULL);
1018 if (selection != NULL)
1020 renderselectionregion(obj, data, selection);
1021 data->lasso.oldregion = selection;
1024 updatemarkers(obj, data, TRUE);
1025 MUI_Redraw(obj, MADF_DRAWUPDATE);
1026 return MUI_EventHandlerRC_Eat;
1028 #if 0
1029 /* find area over which we are and setup appropriate pointer */
1030 if (data->hasregion && data->moveregion == 0)
1032 int handle = rectFindClosestHandle(data, &data->region, mx, my, 0);
1033 int cursormapping[9] = {
1034 POINTERTYPE_DIAGONALRESIZE2,
1035 POINTERTYPE_DIAGONALRESIZE1,
1036 POINTERTYPE_DIAGONALRESIZE2,
1037 POINTERTYPE_DIAGONALRESIZE1,
1038 POINTERTYPE_VERTICALRESIZE,
1039 POINTERTYPE_HORIZONTALRESIZE,
1040 POINTERTYPE_VERTICALRESIZE,
1041 POINTERTYPE_HORIZONTALRESIZE,
1042 POINTERTYPE_MOVE};
1044 if (_isinimage(obj, msg->imsg->MouseX, msg->imsg->MouseY))
1046 if (data->pointertype != cursormapping[handle - 1])
1047 SetWindowPointer(_window(obj), WA_PointerType, data->pointertype = cursormapping[handle - 1], TAG_DONE);
1049 else
1050 SetWindowPointer(_window(obj), WA_PointerType, data->pointertype = POINTERTYPE_NORMAL, TAG_DONE);
1052 else if (data->hasregion)
1054 rectSetCorner(data, &data->region, data->moveregion, mx, my, 0);
1055 set(obj, MUIA_PageView_Region, (ULONG)&data->region);
1057 else if (!data->hasregion && data->ready)
1059 double x = mx;
1060 double y = my;
1061 void *link = NULL;
1063 //link = pdfFindLink(data->doc, data->page, x, y);
1065 if (link != NULL)
1067 //char *description = linkGetDescription(link);
1069 else
1071 //kprintf("mouse:%d,%d\n", (int)x, (int)y);
1074 #endif
1075 break;
1081 return(DOSUPER);
1084 ////
1086 /// backfill
1088 DEFMMETHOD(Backfill)
1090 //printf("%d, %d, %d, %d\n", msg->left, msg->top, msg->right, msg->bottom);
1091 return 0;//DOSUPER;
1094 ////
1096 /// hide
1098 DEFMMETHOD(Hide)
1100 GETDATA;
1102 /* hide is a bit tricky in virtgroups. it is called while scrolling so
1103 we just push the method and if show is called right after it then flush
1104 is canceled.*/
1106 #if defined(__AROS__)
1107 // FIXME: implement MUIV_PushMethod_Delay in Zune/AROS
1108 data->flushmethodid = DoMethod(_app(obj), MUIM_Application_PushMethod, obj, 1, MUIM_PageView_Flush);
1109 #else
1110 data->flushmethodid = DoMethod(_app(obj), MUIM_Application_PushMethod, obj, 1 | MUIV_PushMethod_Delay(150), MUIM_PageView_Flush);
1111 #endif
1112 D(kprintf("cleanup:%d\n", data->page));
1113 return DOSUPER;
1116 ////
1118 /// show
1120 DEFMMETHOD(Show)
1122 GETDATA;
1124 if (data->flushmethodid != 0)
1126 DoMethod(_app(obj), MUIM_Application_UnpushMethod, NULL, data->flushmethodid, 0);
1127 data->flushmethodid = 0;
1130 if ((1) && data->eh.ehn_Object == NULL)
1132 data->eh.ehn_Object = obj;
1133 data->eh.ehn_Class = cl;
1134 data->eh.ehn_Events = IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE;
1135 data->eh.ehn_Priority = 100;
1136 data->eh.ehn_Flags = MUI_EHF_GUIMODE;
1138 DoMethod(_win(obj), MUIM_Window_AddEventHandler, &data->eh);
1141 return DOSUPER;
1144 ////
1146 /// flush
1148 DEFMMETHOD(PageView_Flush)
1150 GETDATA;
1152 ObtainSemaphore(&data->sema);
1154 if (data->image != NULL)
1156 mfree(data->image->data);
1157 data->image->data = NULL;
1160 if (data->eh.ehn_Object != NULL)
1162 DoMethod(_win(obj), MUIM_Window_RemEventHandler, &data->eh);
1163 data->eh.ehn_Object = NULL;
1166 data->flushmethodid = 0;
1167 ReleaseSemaphore(&data->sema);
1169 return 0;
1172 ////
1174 /// addmarker
1176 DEFMMETHOD(PageView_AddMarker)
1178 GETDATA;
1179 unsigned int id = 0;
1181 struct markernode *mn;
1183 if (msg->id != MUIV_PageView_AddMarker_New)
1185 int found = FALSE;
1186 ITERATELIST(mn, &data->markerlist)
1188 if (mn->id == msg->id)
1190 found = TRUE;
1191 id = msg->id;
1192 break;
1196 if (found == FALSE)
1197 mn = NULL;
1199 else
1201 mn = calloc(1, sizeof(*mn));
1204 if (mn != NULL)
1206 mn->x1 = msg->coords[0];
1207 mn->y1 = msg->coords[1];
1208 mn->x2 = msg->coords[2];
1209 mn->y2 = msg->coords[3];
1210 mn->color = msg->color;
1211 mn->id = id;
1212 ADDTAIL(&data->markerlist, mn);
1213 updatemarkers(obj, data, FALSE);
1216 return id;
1219 ////
1221 /// removemarker
1223 DEFMMETHOD(PageView_RemoveMarker)
1225 GETDATA;
1227 /* TODO: add single marker removal */
1229 while(!ISLISTEMPTY(&data->markerlist))
1231 struct markernode *mn = (struct markernode*)GetHead(&data->markerlist);
1232 REMOVE(mn);
1233 free(mn);
1236 return 0;
1239 ////
1241 /// addannotation
1243 DEFMMETHOD(PageView_AddAnnotation)
1245 GETDATA;
1247 struct annotationnode *an;
1248 an = calloc(1, sizeof(*an));
1250 if (an != NULL)
1252 an->x1 = msg->coords[0];
1253 an->y1 = msg->coords[1];
1254 an->x2 = msg->coords[2];
1255 an->y2 = msg->coords[3];
1256 an->obj = msg->obj;
1257 ADDTAIL(&data->annotationlist, an);
1258 updatemarkers(obj, data, FALSE);
1261 return an != NULL;
1264 ////
1266 /// removeannotation
1268 DEFMMETHOD(PageView_RemoveAnnotation)
1270 GETDATA;
1271 struct annotationnode *an;
1273 ITERATELIST(an, &data->annotationlist)
1275 if (an->obj == msg->obj)
1277 REMOVE(an);
1278 free(an);
1279 break;
1283 return TRUE;
1286 ////
1288 /// clearselection
1290 DEFMMETHOD(PageView_ClearSelection)
1292 GETDATA;
1294 if (data->lasso.oldregion != NULL)
1296 renderselectionregion(obj, data, data->lasso.oldregion);
1297 pdfDisposeRegionForSelection(data->doc, data->lasso.oldregion);
1299 if (data->image != NULL && data->image->data != NULL) /* also have to refresh here! */
1300 MUI_Redraw(obj, MADF_DRAWUPDATE);
1302 data->lasso.oldregion = NULL;
1303 data->lasso.marker.x2 = data->lasso.marker.x1;
1304 data->lasso.marker.y2 = data->lasso.marker.y1;
1307 return TRUE;
1310 ////
1312 /// clearselection
1314 DEFMMETHOD(PageView_GetSelection)
1316 GETDATA;
1318 if (data->lasso.oldregion == NULL)
1319 return FALSE;
1321 msg->region.x1 = data->lasso.marker.x1; msg->region.y1 = data->lasso.marker.y1;
1322 msg->region.x2 = data->lasso.marker.x2; msg->region.y2 = data->lasso.marker.y2;
1324 return TRUE;
1327 ////
1329 BEGINMTABLE
1330 case MUIM_Draw: return(riDraw(cl,obj,(APTR)msg));
1331 case MUIM_Setup: return(riSetup(cl,obj,(APTR)msg));
1332 case MUIM_Cleanup: return(riCleanup(cl,obj,(APTR)msg));
1333 case MUIM_HandleEvent: return(riHandleEvent(cl,obj,(APTR)msg));
1334 case MUIM_AskMinMax: return(ThbAskMinMax(cl,obj,(APTR)msg));
1335 DECSET
1336 DECGET
1337 DECNEW
1338 DECDISP
1339 DECMMETHOD(Hide)
1340 DECMMETHOD(Show)
1341 DECMMETHOD(Backfill)
1342 DECMMETHOD(PageView_AddMarker)
1343 DECMMETHOD(PageView_AddAnnotation)
1344 DECMMETHOD(PageView_RemoveMarker)
1345 DECMMETHOD(PageView_RemoveAnnotation)
1346 DECMMETHOD(PageView_Update)
1347 DECMMETHOD(PageView_Flush)
1348 DECMMETHOD(PageView_ClearSelection)
1349 DECMMETHOD(PageView_GetSelection)
1350 ENDMTABLE
1352 DECSUBCLASS_NC(MUIC_Area, PageViewClass)