New bitmap method SetRGBConversionFunction which can be used to
[tangerine.git] / rom / graphics / gfxfuncsupport.c
blob69904f636932ed048402a88af25004287a437d3e
1 /*
2 Copyright © 1995-2006, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 /* !!!! ONLY USE THE BELOW MACROS IF YOU ARE 100% SURE
7 THAT IT IS A HIDD BITMAP AND NOT ONE THE USER
8 HAS CREATED BY HAND !!!. You can use IS_HIDD_BM(bitmap) to test
9 if it is a HIDD bitmap
12 /****************************************************************************************/
14 #include <cybergraphx/cybergraphics.h>
15 #include <graphics/rpattr.h>
16 #include <proto/exec.h>
17 #include <proto/graphics.h>
18 #include <proto/layers.h>
19 //#include <proto/cybergraphics.h>
20 #include <proto/oop.h>
21 #include <clib/macros.h>
23 #include "graphics_intern.h"
24 #include "objcache.h"
25 #include "intregions.h"
26 #include "gfxfuncsupport.h"
28 #define DEBUG 0
29 #include <aros/debug.h>
31 /****************************************************************************************/
33 OOP_Object *get_planarbm_object(struct BitMap *bitmap, struct GfxBase *GfxBase)
35 OOP_Object *pbm_obj;
37 D(bug("get_planarbm_object()\n"));
38 pbm_obj = obtain_cache_object(SDD(GfxBase)->planarbm_cache, GfxBase);
40 if (NULL != pbm_obj)
43 D(bug("Got cache object %p, class=%s, domethod=%p, instoffset=%d\n"
44 , pbm_obj
45 , OOP_OCLASS(pbm_obj)->ClassNode.ln_Name
46 , OOP_OCLASS(pbm_obj)->DoMethod
47 , OOP_OCLASS(pbm_obj)->InstOffset
48 ));
50 if (!HIDD_PlanarBM_SetBitMap(pbm_obj, bitmap))
52 D(bug("!!! get_planarbm_object: HIDD_PlanarBM_SetBitMap FAILED !!!\n"));
53 release_cache_object(SDD(GfxBase)->planarbm_cache, pbm_obj, GfxBase);
54 pbm_obj = NULL;
58 else
60 D(bug("!!! get_planarbm_object: obtain_cache_object FAILED !!!\n"));
63 return pbm_obj;
66 /****************************************************************************************/
68 ULONG do_render_func(struct RastPort *rp
69 , Point *src
70 , struct Rectangle *rr
71 , ULONG (*render_func)(APTR, LONG, LONG, OOP_Object *, OOP_Object *, LONG, LONG, LONG, LONG, struct GfxBase *)
72 , APTR funcdata
73 , BOOL get_special_info
74 , struct GfxBase *GfxBase)
77 struct BitMap *bm = rp->BitMap;
78 struct Layer *L = rp->Layer;
79 OOP_Object *gc;
80 struct Rectangle rp_clip_rectangle;
81 BOOL have_rp_cliprectangle;
82 ULONG width, height;
83 LONG srcx, srcy;
84 LONG pixwritten = 0;
86 gc = GetDriverData(rp)->dd_GC;
88 width = rr->MaxX - rr->MinX + 1;
89 height = rr->MaxY - rr->MinY + 1;
91 if (NULL != src)
93 srcx = src->x;
94 srcy = src->y;
95 } else
97 srcx = 0;
98 srcy = 0;
101 if (NULL == L)
103 /* No layer, probably a screen, but may be a user inited bitmap */
104 OOP_Object *bm_obj;
106 bm_obj = OBTAIN_HIDD_BM(bm);
107 if (NULL == bm_obj)
108 return 0;
110 if (get_special_info)
112 RSI(funcdata)->curbm = rp->BitMap;
113 RSI(funcdata)->onscreen = TRUE;
114 RSI(funcdata)->layer_rel_srcx = srcx;
115 RSI(funcdata)->layer_rel_srcy = srcy;
118 pixwritten = render_func(funcdata
119 , srcx, srcy
120 , bm_obj, gc
121 , rr->MinX, rr->MinY
122 , rr->MaxX, rr->MaxY
123 , GfxBase
126 RELEASE_HIDD_BM(bm_obj, bm);
129 else
131 struct ClipRect *CR;
132 WORD xrel;
133 WORD yrel;
134 struct Rectangle torender, intersect;
135 OOP_Object *bm_obj;
137 LockLayerRom(L);
139 have_rp_cliprectangle = GetRPClipRectangleForLayer(rp, L, &rp_clip_rectangle, GfxBase);
141 xrel = L->bounds.MinX;
142 yrel = L->bounds.MinY;
144 torender.MinX = rr->MinX + xrel - L->Scroll_X;
145 torender.MinY = rr->MinY + yrel - L->Scroll_Y;
146 torender.MaxX = rr->MaxX + xrel - L->Scroll_X;
147 torender.MaxY = rr->MaxY + yrel - L->Scroll_Y;
150 CR = L->ClipRect;
152 for (;NULL != CR; CR = CR->Next)
154 D(bug("Cliprect (%d, %d, %d, %d), lobs=%p\n",
155 CR->bounds.MinX, CR->bounds.MinY, CR->bounds.MaxX, CR->bounds.MaxY,
156 CR->lobs));
158 /* Does this cliprect intersect with area to rectfill ? */
159 if (_AndRectRect(&CR->bounds, &torender, &intersect))
161 if (!have_rp_cliprectangle || _AndRectRect(&rp_clip_rectangle, &intersect, &intersect))
163 LONG xoffset, yoffset;
165 xoffset = intersect.MinX - torender.MinX;
166 yoffset = intersect.MinY - torender.MinY;
168 if (get_special_info) {
169 RSI(funcdata)->layer_rel_srcx = intersect.MinX - L->bounds.MinX + L->Scroll_X;
170 RSI(funcdata)->layer_rel_srcy = intersect.MinY - L->bounds.MinY + L->Scroll_Y;
173 if (NULL == CR->lobs)
175 if (get_special_info)
177 RSI(funcdata)->curbm = bm;
178 RSI(funcdata)->onscreen = TRUE;
181 bm_obj = OBTAIN_HIDD_BM(bm);
182 if(bm_obj)
184 pixwritten += render_func(funcdata
185 , srcx + xoffset
186 , srcy + yoffset
187 , bm_obj
188 , gc
189 , intersect.MinX
190 , intersect.MinY
191 , intersect.MaxX
192 , intersect.MaxY
193 , GfxBase
196 RELEASE_HIDD_BM(bm_obj, bm);
201 else
203 /* Render into offscreen cliprect bitmap */
204 if (L->Flags & LAYERSIMPLE)
205 continue;
206 else if (L->Flags & LAYERSUPER)
208 D(bug("do_render_func(): Superbitmap not handled yet\n"));
210 else
213 if (get_special_info)
215 RSI(funcdata)->curbm = CR->BitMap;
216 RSI(funcdata)->onscreen = FALSE;
219 bm_obj = OBTAIN_HIDD_BM(CR->BitMap);
220 if (bm_obj)
222 pixwritten += render_func(funcdata
223 , srcx + xoffset, srcy + yoffset
224 , bm_obj
225 , gc
226 , intersect.MinX - CR->bounds.MinX + ALIGN_OFFSET(CR->bounds.MinX)
227 , intersect.MinY - CR->bounds.MinY
228 , intersect.MaxX - CR->bounds.MinX + ALIGN_OFFSET(CR->bounds.MinX)
229 , intersect.MaxY - CR->bounds.MinY
230 , GfxBase
233 RELEASE_HIDD_BM(bm_obj, CR->BitMap);
237 } /* if (CR->lobs == NULL) */
239 } /* if it also intersects with possible rastport clip rectangle */
241 } /* if (cliprect intersects with area to render into) */
243 } /* for (each cliprect in the layer) */
245 UnlockLayerRom(L);
246 } /* if (rp->Layer) */
249 return pixwritten;
253 /****************************************************************************************/
255 ULONG do_pixel_func(struct RastPort *rp
256 , LONG x, LONG y
257 , LONG (*render_func)(APTR, OOP_Object *, OOP_Object *, LONG, LONG, struct GfxBase *)
258 , APTR funcdata
259 , struct GfxBase *GfxBase)
261 struct BitMap *bm = rp->BitMap;
262 struct Layer *L = rp->Layer;
263 OOP_Object *gc;
264 struct Rectangle rp_clip_rectangle;
265 BOOL have_rp_cliprectangle;
266 ULONG retval = -1;
268 gc = GetDriverData(rp)->dd_GC;
270 if (NULL == L)
272 OOP_Object *bm_obj;
273 ULONG width, height;
275 bm_obj = OBTAIN_HIDD_BM(bm);
276 if (NULL == bm_obj)
277 return -1;
279 OOP_GetAttr(bm_obj, aHidd_BitMap_Width, &width);
280 OOP_GetAttr(bm_obj, aHidd_BitMap_Height, &height);
282 /* Check whether we it is inside the rastport */
283 if ( x < 0
284 || x >= width
285 || y < 0
286 || y >= height)
289 RELEASE_HIDD_BM(bm_obj, bm);
290 return -1;
294 /* This is a screen */
295 retval = render_func(funcdata, bm_obj, gc, x, y, GfxBase);
297 RELEASE_HIDD_BM(bm_obj, bm);
300 else
302 struct ClipRect *CR;
303 LONG absx, absy;
304 OOP_Object *bm_obj;
306 LockLayerRom( L );
308 have_rp_cliprectangle = GetRPClipRectangleForLayer(rp, L, &rp_clip_rectangle, GfxBase);
310 CR = L->ClipRect;
312 absx = x + L->bounds.MinX - L->Scroll_X;
313 absy = y + L->bounds.MinY - L->Scroll_Y;
315 for (;NULL != CR; CR = CR->Next)
318 if ( absx >= CR->bounds.MinX
319 && absy >= CR->bounds.MinY
320 && absx <= CR->bounds.MaxX
321 && absy <= CR->bounds.MaxY )
324 if (!have_rp_cliprectangle || _IsPointInRect(&rp_clip_rectangle, absx, absy))
326 if (NULL == CR->lobs)
328 bm_obj = OBTAIN_HIDD_BM(bm);
329 if (bm_obj)
331 retval = render_func(funcdata
332 , bm_obj, gc
333 , absx, absy
334 , GfxBase
337 RELEASE_HIDD_BM(bm_obj, bm);
340 else
342 /* This is the tricky one: render into offscreen cliprect bitmap */
343 if (L->Flags & LAYERSIMPLE)
345 /* We cannot do anything */
346 retval = 0;
349 else if (L->Flags & LAYERSUPER)
351 D(bug("driver_WriteRGBPixel(): Superbitmap not handled yet\n"));
353 else
355 bm_obj = OBTAIN_HIDD_BM(CR->BitMap);
356 if (bm_obj)
358 retval = render_func(funcdata
359 , bm_obj, gc
360 , absx - CR->bounds.MinX + ALIGN_OFFSET(CR->bounds.MinX)
361 , absy - CR->bounds.MinY
362 , GfxBase
365 RELEASE_HIDD_BM(bm_obj, CR->BitMap);
369 } /* If (SMARTREFRESH cliprect) */
372 } /* if (intersecton inside hidden cliprect) */
374 } /* if point is also inside possible rastport clip rectangle */
376 /* The pixel was found and put inside one of the cliprects, just exit */
377 break;
379 } /* if (cliprect intersects with area we want to draw to) */
381 } /* while (cliprects to examine) */
383 UnlockLayerRom( L );
387 return retval;
390 /****************************************************************************************/
392 static ULONG fillrect_render(APTR funcdata, LONG srcx, LONG srcy,
393 OOP_Object *dstbm_obj, OOP_Object *dst_gc,
394 LONG x1, LONG y1, LONG x2, LONG y2,
395 struct GfxBase *GfxBase)
398 HIDD_BM_FillRect(dstbm_obj, dst_gc, x1, y1, x2, y2);
400 return (x2 - x1 + 1) * (y2 - y1 + 1);
403 /****************************************************************************************/
405 LONG fillrect_pendrmd(struct RastPort *rp, LONG x1, LONG y1, LONG x2, LONG y2,
406 HIDDT_Pixel pix, HIDDT_DrawMode drmd, struct GfxBase *GfxBase)
408 LONG pixwritten = 0;
410 HIDDT_DrawMode old_drmd;
411 HIDDT_Pixel old_fg;
412 OOP_Object *gc;
413 struct Rectangle rr;
415 struct TagItem gc_tags[] =
417 { aHidd_GC_DrawMode , drmd },
418 { aHidd_GC_Foreground , pix },
419 { TAG_DONE }
423 if (!OBTAIN_DRIVERDATA(rp, GfxBase))
424 return 0;
426 gc = GetDriverData(rp)->dd_GC;
428 OOP_GetAttr(gc, aHidd_GC_DrawMode, (IPTR *)&old_drmd);
429 OOP_GetAttr(gc, aHidd_GC_Foreground,(IPTR *)&old_fg);
431 OOP_SetAttrs(gc, gc_tags);
433 rr.MinX = x1;
434 rr.MinY = y1;
435 rr.MaxX = x2;
436 rr.MaxY = y2;
438 pixwritten = do_render_func(rp, NULL, &rr, fillrect_render, NULL, FALSE, GfxBase);
440 /* Restore old GC values */
441 gc_tags[0].ti_Data = (IPTR)old_drmd;
442 gc_tags[1].ti_Data = (IPTR)old_fg;
443 OOP_SetAttrs(gc, gc_tags);
445 RELEASE_DRIVERDATA(rp, GfxBase);
447 return pixwritten;
450 /****************************************************************************************/
452 BOOL int_bltbitmap(struct BitMap *srcBitMap, OOP_Object *srcbm_obj, LONG xSrc, LONG ySrc,
453 struct BitMap *dstBitMap, OOP_Object *dstbm_obj, LONG xDest, LONG yDest,
454 LONG xSize, LONG ySize, ULONG minterm, OOP_Object *gc, struct GfxBase *GfxBase)
456 HIDDT_DrawMode drmd;
458 ULONG srcflags = 0;
459 ULONG dstflags = 0;
461 BOOL src_colmap_set = FALSE;
462 BOOL dst_colmap_set = FALSE;
463 BOOL success = TRUE;
464 BOOL colmaps_ok = TRUE;
466 drmd = MINTERM_TO_GCDRMD(minterm);
468 /* We must lock any HIDD_BM_SetColorMap calls */
469 LOCK_BLIT
471 /* Try to get a CLUT for the bitmaps */
472 if (IS_HIDD_BM(srcBitMap))
474 //bug("driver_intbltbitmap: source is hidd bitmap\n");
475 if (NULL != HIDD_BM_COLMAP(srcBitMap))
477 //bug("driver_intbltbitmap: source has colormap\n");
478 srcflags |= FLG_HASCOLMAP;
480 srcflags |= GET_COLMOD_FLAGS(srcBitMap);
482 else
484 //bug("driver_intbltbitmap: source is amiga bitmap\n");
485 /* Amiga BM */
486 srcflags |= FLG_PALETTE;
489 if (IS_HIDD_BM(dstBitMap))
491 //bug("driver_intbltbitmap: dest is hidd bitmap\n");
492 if (NULL != HIDD_BM_COLMAP(dstBitMap))
494 //bug("driver_intbltbitmap: dest has colormap\n");
495 dstflags |= FLG_HASCOLMAP;
497 dstflags |= GET_COLMOD_FLAGS(dstBitMap);
499 else
501 //bug("driver_intbltbitmap: dest is amiga bitmap\n");
502 /* Amiga BM */
503 dstflags |= FLG_PALETTE;
506 if ( (srcflags == FLG_PALETTE || srcflags == FLG_STATICPALETTE))
508 /* palettized with no colmap. Neew to get a colmap from dest*/
509 if (dstflags == FLG_TRUECOLOR)
512 D(bug("!!! NO WAY GETTING PALETTE FOR src IN BltBitMap\n"));
513 colmaps_ok = FALSE;
514 success = FALSE;
517 else if (dstflags == (FLG_TRUECOLOR | FLG_HASCOLMAP))
520 /* Use the dest colmap for src */
521 HIDD_BM_SetColorMap(srcbm_obj, HIDD_BM_COLMAP(dstBitMap));
523 src_colmap_set = TRUE;
526 bug("Colormap:\n");
528 ULONG idx;
529 for (idx = 0; idx < 256; idx ++)
530 bug("[%d]=%d ", idx, HIDD_CM_GetPixel(HIDD_BM_COLMAP(dstBitMap), idx));
536 if ( (dstflags == FLG_PALETTE || dstflags == FLG_STATICPALETTE))
538 /* palettized with no pixtab. Nees to get a pixtab from dest*/
539 if (srcflags == FLG_TRUECOLOR)
541 D(bug("!!! NO WAY GETTING PALETTE FOR dst IN BltBitMap\n"));
542 colmaps_ok = FALSE;
543 success = FALSE;
546 else if (srcflags == (FLG_TRUECOLOR | FLG_HASCOLMAP))
549 /* Use the src colmap for dst */
550 HIDD_BM_SetColorMap(dstbm_obj, HIDD_BM_COLMAP(srcBitMap));
552 dst_colmap_set = TRUE;
556 if (colmaps_ok)
558 /* We need special treatment with drawmode Clear and
559 truecolor bitmaps, in order to set it to
560 colormap[0] instead of just 0
562 if ( (drmd == vHidd_GC_DrawMode_Clear)
563 && ( (dstflags & (FLG_TRUECOLOR | FLG_HASCOLMAP)) == (FLG_TRUECOLOR | FLG_HASCOLMAP) ))
566 HIDDT_DrawMode old_drmd;
567 HIDDT_Pixel old_fg;
569 struct TagItem frtags[] =
571 { aHidd_GC_Foreground , 0 },
572 { aHidd_GC_DrawMode , vHidd_GC_DrawMode_Copy },
573 { TAG_DONE }
576 OOP_GetAttr(gc, aHidd_GC_DrawMode, &old_drmd);
577 OOP_GetAttr(gc, aHidd_GC_Foreground, &old_fg);
579 frtags[0].ti_Data = HIDD_BM_PIXTAB(dstBitMap)[0];
580 frtags[1].ti_Data = vHidd_GC_DrawMode_Copy;
582 OOP_SetAttrs(gc, frtags);
584 HIDD_BM_FillRect(dstbm_obj, gc
585 , xDest, yDest
586 , xDest + xSize - 1
587 , yDest + ySize - 1
590 frtags[0].ti_Data = old_fg;
591 frtags[1].ti_Data = old_drmd;
594 else
596 HIDDT_DrawMode old_drmd;
598 struct TagItem cbtags[] =
600 { aHidd_GC_DrawMode, 0 },
601 { TAG_DONE }
604 OOP_GetAttr(gc, aHidd_GC_DrawMode, &old_drmd);
606 cbtags[0].ti_Data = drmd;
608 OOP_SetAttrs(gc, cbtags);
609 HIDD_Gfx_CopyBox(SDD(GfxBase)->gfxhidd
610 , srcbm_obj
611 , xSrc, ySrc
612 , dstbm_obj
613 , xDest, yDest
614 , xSize, ySize
615 , gc
618 cbtags[0].ti_Data = drmd;
619 OOP_SetAttrs(gc, cbtags);
622 } /* if (colmaps_ok) */
624 if (src_colmap_set)
625 HIDD_BM_SetColorMap(srcbm_obj, NULL);
627 if (dst_colmap_set)
628 HIDD_BM_SetColorMap(dstbm_obj, NULL);
630 ULOCK_BLIT
632 return success;
636 /****************************************************************************************/
638 struct wp8_render_data
640 UBYTE *array;
641 ULONG modulo;
642 HIDDT_PixelLUT *pixlut;
645 static ULONG wp8_render(APTR wp8r_data, LONG srcx, LONG srcy, OOP_Object *dstbm_obj,
646 OOP_Object *dst_gc, LONG x1, LONG y1, LONG x2, LONG y2,
647 struct GfxBase *GfxBase)
649 struct wp8_render_data *wp8rd;
650 ULONG width, height;
652 wp8rd = (struct wp8_render_data *)wp8r_data;
654 width = x2 - x1 + 1;
655 height = y2 - y1 + 1;
657 HIDD_BM_PutImageLUT(dstbm_obj
658 , dst_gc
659 , wp8rd->array + CHUNKY8_COORD_TO_BYTEIDX(srcx, srcy, wp8rd->modulo)
660 , wp8rd->modulo
661 , x1, y1
662 , width, height
663 , wp8rd->pixlut
666 return width * height;
668 /****************************************************************************************/
670 LONG write_pixels_8(struct RastPort *rp, UBYTE *array, ULONG modulo,
671 LONG xstart, LONG ystart, LONG xstop, LONG ystop,
672 HIDDT_PixelLUT *pixlut, struct GfxBase *GfxBase)
675 LONG pixwritten = 0;
677 struct wp8_render_data wp8rd;
678 struct Rectangle rr;
680 OOP_Object *gc;
681 HIDDT_DrawMode old_drmd;
683 struct TagItem gc_tags[] =
685 { aHidd_GC_DrawMode, vHidd_GC_DrawMode_Copy},
686 { TAG_DONE, 0}
690 if (!OBTAIN_DRIVERDATA(rp, GfxBase))
691 return 0;
693 gc = GetDriverData(rp)->dd_GC;
695 OOP_GetAttr(gc, aHidd_GC_DrawMode, &old_drmd);
696 OOP_SetAttrs(gc, gc_tags);
698 wp8rd.modulo = modulo;
699 wp8rd.array = array;
700 wp8rd.pixlut = pixlut;
702 rr.MinX = xstart;
703 rr.MinY = ystart;
704 rr.MaxX = xstop;
705 rr.MaxY = ystop;
707 pixwritten = do_render_func(rp, NULL, &rr, wp8_render, &wp8rd, FALSE, GfxBase);
709 /* Reset to preserved drawmode */
710 gc_tags[0].ti_Data = old_drmd;
711 OOP_SetAttrs(gc, gc_tags);
713 RELEASE_DRIVERDATA(rp, GfxBase);
715 return pixwritten;
719 /****************************************************************************************/
721 struct wtp8_render_data
723 UBYTE *array;
724 ULONG modulo;
725 HIDDT_PixelLUT *pixlut;
726 UBYTE transparent;
729 static ULONG wtp8_render(APTR wtp8r_data, LONG srcx, LONG srcy, OOP_Object *dstbm_obj,
730 OOP_Object *dst_gc, LONG x1, LONG y1, LONG x2, LONG y2,
731 struct GfxBase *GfxBase)
733 struct wtp8_render_data *wtp8rd;
734 ULONG width, height;
736 wtp8rd = (struct wtp8_render_data *)wtp8r_data;
738 width = x2 - x1 + 1;
739 height = y2 - y1 + 1;
741 HIDD_BM_PutTranspImageLUT(dstbm_obj
742 , dst_gc
743 , wtp8rd->array + CHUNKY8_COORD_TO_BYTEIDX(srcx, srcy, wtp8rd->modulo)
744 , wtp8rd->modulo
745 , x1, y1
746 , width, height
747 , wtp8rd->pixlut
748 , wtp8rd->transparent
751 return width * height;
753 /****************************************************************************************/
755 LONG write_transp_pixels_8(struct RastPort *rp, UBYTE *array, ULONG modulo,
756 LONG xstart, LONG ystart, LONG xstop, LONG ystop,
757 HIDDT_PixelLUT *pixlut, UBYTE transparent,
758 struct GfxBase *GfxBase)
761 LONG pixwritten = 0;
763 struct wtp8_render_data wtp8rd;
764 struct Rectangle rr;
766 OOP_Object *gc;
767 HIDDT_DrawMode old_drmd;
769 struct TagItem gc_tags[] =
771 { aHidd_GC_DrawMode, vHidd_GC_DrawMode_Copy},
772 { TAG_DONE, 0}
776 if (!OBTAIN_DRIVERDATA(rp, GfxBase))
777 return 0;
779 gc = GetDriverData(rp)->dd_GC;
781 OOP_GetAttr(gc, aHidd_GC_DrawMode, &old_drmd);
782 OOP_SetAttrs(gc, gc_tags);
784 wtp8rd.modulo = modulo;
785 wtp8rd.array = array;
786 wtp8rd.pixlut = pixlut;
787 wtp8rd.transparent = transparent;
789 rr.MinX = xstart;
790 rr.MinY = ystart;
791 rr.MaxX = xstop;
792 rr.MaxY = ystop;
794 pixwritten = do_render_func(rp, NULL, &rr, wtp8_render, &wtp8rd, FALSE, GfxBase);
796 /* Reset to preserved drawmode */
797 gc_tags[0].ti_Data = old_drmd;
798 OOP_SetAttrs(gc, gc_tags);
800 RELEASE_DRIVERDATA(rp, GfxBase);
802 return pixwritten;
806 /****************************************************************************************/
809 ** General functions for moving blocks of data to or from HIDDs, be it pixelarrays
810 ** or bitmaps. They use a callback-function to get data from amiga/put data to amiga
811 ** bitmaps/pixelarrays
814 /****************************************************************************************/
816 #if 0
818 void amiga2hidd_fast(APTR src_info, OOP_Object *hidd_gc, LONG x_src , LONG y_src,
819 struct BitMap *hidd_bm, LONG x_dest, LONG y_dest,
820 ULONG xsize, ULONG ysize, VOID (*fillbuf_hook)(),
821 struct GfxBase * GfxBase)
825 ULONG tocopy_w,
826 tocopy_h;
828 LONG pixels_left_to_process = xsize * ysize;
830 LONG current_x, current_y, next_x, next_y;
831 OOP_Object *bm_obj;
833 next_x = 0;
834 next_y = 0;
836 bm_obj = OBTAIN_HIDD_BM(hidd_bm);
837 if (NULL == bm_obj)
838 return;
840 LOCK_PIXBUF
842 while (pixels_left_to_process)
845 /* Get some more pixels from the HIDD */
847 current_x = next_x;
848 current_y = next_y;
850 if (NUMPIX < xsize)
852 /* buffer can't hold a single horizontal line, and must
853 divide each line into several copy-operations */
854 tocopy_w = xsize - current_x;
855 if (tocopy_w > NUMPIX)
857 /* Not quite finished with current horizontal pixel line */
858 tocopy_w = NUMPIX;
859 next_x += NUMPIX;
861 else
862 { /* Start at a new line */
863 next_x = 0;
864 next_y ++;
866 tocopy_h = 1;
869 else /* We can copy one or several whole horizontal lines at a time */
871 tocopy_h = MIN(NUMPIX / xsize, ysize - current_y);
873 tocopy_w = xsize;
875 next_x = 0;
876 next_y += tocopy_h;
882 /* Get data */
883 fillbuf_hook(src_info
884 , current_x + x_src
885 , current_y + y_src
886 , current_x + x_dest
887 , current_y + y_dest
888 , tocopy_w, tocopy_h
889 , PrivGBase(GfxBase)->pixel_buf
890 , bm_obj
891 , IS_HIDD_BM(hidd_bm) ? HIDD_BM_PIXTAB(hidd_bm) : NULL
892 , GfxBase
895 /* Put it to the HIDD */
896 D(bug("Putting box\n"));
898 HIDD_BM_PutImage(bm_obj
899 , hidd_gc
900 , (UBYTE*)PrivGBase(GfxBase)->pixel_buf
901 , tocopy_w * sizeof (HIDDT_Pixel)
902 , x_dest + current_x
903 , y_dest + current_y
904 , tocopy_w, tocopy_h
905 , vHidd_StdPixFmt_Native32
908 D(bug("Box put\n"));
910 pixels_left_to_process -= (tocopy_w * tocopy_h);
913 } /* while (pixels left to copy) */
915 ULOCK_PIXBUF
917 RELEASE_HIDD_BM(bm_obj, hidd_bm);
919 return;
923 #endif
925 /****************************************************************************************/
927 void hidd2buf_fast(struct BitMap *hidd_bm, LONG x_src , LONG y_src, APTR dest_info,
928 LONG x_dest, LONG y_dest, ULONG xsize, ULONG ysize, VOID (*putbuf_hook)(),
929 struct GfxBase * GfxBase)
932 ULONG tocopy_w, tocopy_h;
934 LONG pixels_left_to_process = xsize * ysize;
935 ULONG current_x, current_y, next_x, next_y;
937 #warning Src bitmap migh be user initialized so we should not use HIDD_BM_PIXTAB() below
939 OOP_Object *bm_obj;
941 next_x = 0;
942 next_y = 0;
944 bm_obj = OBTAIN_HIDD_BM(hidd_bm);
945 if (NULL == bm_obj)
946 return;
948 LOCK_PIXBUF
950 while (pixels_left_to_process)
953 current_x = next_x;
954 current_y = next_y;
956 if (NUMPIX < xsize)
958 /* buffer cant hold a single horizontal line, and must
959 divide each line into copies */
960 tocopy_w = xsize - current_x;
961 if (tocopy_w > NUMPIX)
963 /* Not quite finished with current horizontal pixel line */
964 tocopy_w = NUMPIX;
965 next_x += NUMPIX;
967 else
968 { /* Start at a new line */
970 next_x = 0;
971 next_y ++;
973 tocopy_h = 1;
976 else
978 tocopy_h = MIN(NUMPIX / xsize, ysize - current_y);
979 tocopy_w = xsize;
981 next_x = 0;
982 next_y += tocopy_h;
987 /* Get some more pixels from the HIDD */
988 HIDD_BM_GetImage(bm_obj
989 , (UBYTE *)PrivGBase(GfxBase)->pixel_buf
990 , tocopy_w
991 , x_src + current_x
992 , y_src + current_y
993 , tocopy_w, tocopy_h
994 , vHidd_StdPixFmt_Native32);
997 /* Write pixels to the destination */
998 putbuf_hook(dest_info
999 , current_x + x_src
1000 , current_y + y_src
1001 , current_x + x_dest
1002 , current_y + y_dest
1003 , tocopy_w, tocopy_h
1004 , (HIDDT_Pixel *)PrivGBase(GfxBase)->pixel_buf
1005 , bm_obj
1006 , IS_HIDD_BM(hidd_bm) ? HIDD_BM_PIXTAB(hidd_bm) : NULL
1009 pixels_left_to_process -= (tocopy_w * tocopy_h);
1013 ULOCK_PIXBUF
1015 RELEASE_HIDD_BM(bm_obj, hidd_bm);
1017 return;
1021 /****************************************************************************************/
1023 UWORD hidd2cyber_pixfmt(HIDDT_StdPixFmt stdpf, struct GfxBase *GfxBase)
1025 UWORD cpf = (UWORD)-1;
1027 bug("hidd2cyber stdpf = %d [%d]\n", stdpf, vHidd_StdPixFmt_BGR032);
1029 switch (stdpf)
1031 case vHidd_StdPixFmt_RGB15:
1032 cpf = PIXFMT_RGB15;
1033 break;
1035 case vHidd_StdPixFmt_RGB15_LE:
1036 cpf = PIXFMT_RGB15PC;
1037 break;
1039 case vHidd_StdPixFmt_BGR15:
1040 cpf = PIXFMT_BGR15;
1041 break;
1043 case vHidd_StdPixFmt_BGR15_LE:
1044 cpf = PIXFMT_BGR15PC;
1045 break;
1047 case vHidd_StdPixFmt_RGB16:
1048 cpf = PIXFMT_RGB16;
1049 break;
1051 case vHidd_StdPixFmt_RGB16_LE:
1052 cpf = PIXFMT_RGB16PC;
1053 break;
1055 case vHidd_StdPixFmt_BGR16:
1056 cpf = PIXFMT_BGR16;
1057 break;
1059 case vHidd_StdPixFmt_BGR16_LE:
1060 cpf = PIXFMT_BGR16PC;
1061 break;
1063 case vHidd_StdPixFmt_RGB24:
1064 cpf = PIXFMT_RGB24;
1065 break;
1067 case vHidd_StdPixFmt_BGR24:
1068 cpf = PIXFMT_BGR24;
1069 break;
1071 case vHidd_StdPixFmt_0RGB32:
1072 case vHidd_StdPixFmt_ARGB32:
1073 cpf = PIXFMT_ARGB32;
1074 break;
1076 case vHidd_StdPixFmt_RGB032:
1077 case vHidd_StdPixFmt_RGBA32:
1078 cpf = PIXFMT_RGBA32;
1079 break;
1081 case vHidd_StdPixFmt_BGRA32:
1082 case vHidd_StdPixFmt_BGR032:
1083 cpf = PIXFMT_BGRA32;
1084 break;
1086 case vHidd_StdPixFmt_ABGR32:
1087 case vHidd_StdPixFmt_0BGR32:
1088 cpf = PIXFMT_ABGR32;
1089 break;
1091 case vHidd_StdPixFmt_LUT8:
1092 cpf = PIXFMT_LUT8;
1093 break;
1095 default:
1096 D(bug("UNKNOWN CYBERGRAPHICS PIXFMT IN cyber2hidd_pixfmt\n"));
1097 break;
1101 return cpf;
1105 /****************************************************************************************/
1107 HIDDT_StdPixFmt cyber2hidd_pixfmt(UWORD cpf, struct GfxBase *GfxBase)
1109 HIDDT_StdPixFmt stdpf = vHidd_StdPixFmt_Unknown;
1111 switch (cpf)
1113 case PIXFMT_RGB15:
1114 stdpf = vHidd_StdPixFmt_RGB15;
1115 break;
1117 case PIXFMT_RGB15PC:
1118 stdpf = vHidd_StdPixFmt_RGB15_LE;
1119 break;
1121 case PIXFMT_BGR15:
1122 stdpf = vHidd_StdPixFmt_BGR15;
1123 break;
1125 case PIXFMT_BGR15PC:
1126 stdpf = vHidd_StdPixFmt_BGR15_LE;
1127 break;
1129 case PIXFMT_RGB16:
1130 stdpf = vHidd_StdPixFmt_RGB16;
1131 break;
1133 case PIXFMT_RGB16PC:
1134 stdpf = vHidd_StdPixFmt_RGB16_LE;
1135 break;
1137 case PIXFMT_BGR16:
1138 stdpf = vHidd_StdPixFmt_BGR16;
1139 break;
1141 case PIXFMT_BGR16PC:
1142 stdpf = vHidd_StdPixFmt_BGR16_LE;
1143 break;
1145 case PIXFMT_RGB24:
1146 stdpf = vHidd_StdPixFmt_RGB24;
1147 break;
1149 case PIXFMT_BGR24:
1150 stdpf = vHidd_StdPixFmt_BGR24;
1151 break;
1153 case PIXFMT_ARGB32:
1154 stdpf = vHidd_StdPixFmt_ARGB32;
1155 break;
1157 case PIXFMT_RGBA32:
1158 stdpf = vHidd_StdPixFmt_RGBA32;
1159 break;
1161 case PIXFMT_BGRA32:
1162 stdpf = vHidd_StdPixFmt_BGRA32;
1163 break;
1165 case PIXFMT_ABGR32:
1166 stdpf = vHidd_StdPixFmt_ABGR32;
1167 break;
1169 case PIXFMT_LUT8:
1170 stdpf = vHidd_StdPixFmt_LUT8;
1171 break;
1173 default:
1174 D(bug("UNKNOWN CYBERGRAPHICS PIXFMT IN cyber2hidd_pixfmt\n"));
1175 break;
1178 return stdpf;
1181 /****************************************************************************************/
1183 #define ENABLE_PROFILING 0
1184 #define USE_OLD_MoveRaster 0
1186 #define rdtscll(val) \
1187 __asm__ __volatile__("rdtsc" : "=A" (val))
1189 #if ENABLE_PROFILING && defined(__i386__)
1192 #define AROS_BEGIN_PROFILING(context) \
1194 unsigned long long _time1, _time2; \
1195 char *_text = #context; \
1196 rdtscll(_time1); \
1199 #define AROS_END_PROFILING \
1201 rdtscll(_time2); \
1202 kprintf("%s: Ticks count: %u\n", _text, (unsigned long)(_time2 - _time1)); \
1205 #else
1207 #define AROS_BEGIN_PROFILING(context)
1208 #define AROS_END_PROFILING
1210 #endif
1212 BOOL MoveRaster (struct RastPort * rp, LONG dx, LONG dy, LONG x1, LONG y1,
1213 LONG x2, LONG y2, BOOL UpdateDamageList, struct GfxBase * GfxBase)
1215 struct Layer *L = rp->Layer;
1216 struct Rectangle ScrollRect;
1217 struct Rectangle Rect;
1219 if (0 == dx && 0 == dy)
1220 return TRUE;
1222 if (!OBTAIN_DRIVERDATA(rp, GfxBase))
1223 return FALSE;
1225 ScrollRect.MinX = x1;
1226 ScrollRect.MinY = y1;
1227 ScrollRect.MaxX = x2;
1228 ScrollRect.MaxY = y2;
1230 if (!L)
1232 Rect = ScrollRect;
1233 TranslateRect(&Rect, -dx, -dy);
1234 if (_AndRectRect(&ScrollRect, &Rect, &Rect))
1236 BltBitMap(rp->BitMap,
1237 Rect.MinX + dx,
1238 Rect.MinY + dy,
1239 rp->BitMap,
1240 Rect.MinX,
1241 Rect.MinY,
1242 Rect.MaxX - Rect.MinX + 1,
1243 Rect.MaxY - Rect.MinY + 1,
1244 0xc0, /* copy */
1245 0xff,
1246 NULL );
1249 else
1251 struct ClipRect *SrcCR;
1253 LockLayerRom(L);
1255 if (L->Flags & LAYERSIMPLE && UpdateDamageList)
1257 /* Scroll the old damagelist within the scroll area */
1258 ScrollRegion(L->DamageList, &ScrollRect, -dx, -dy);
1261 /* The scrolling area is relative to the Layer, so make it relative to the screen */
1262 TranslateRect(&ScrollRect, MinX(L), MinY(L));
1264 /* The damage list will be formed by the now hidden layer's parts that will become visible due
1265 to the scrolling procedure, thus we procede this way:
1267 1) Calculate the invisible region out of the visible one, subtracting it from the
1268 scrolling area
1270 2) Scroll the invisible region by (-dx, -dy) and then subtract from it the not scrolled equivalent
1272 The regions that we obtain after (2) is the new damage list
1275 if (L->Flags & LAYERSIMPLE && UpdateDamageList)
1277 Rect = ScrollRect;
1278 TranslateRect(&Rect, dx, dy);
1280 if (_AndRectRect(&ScrollRect, &Rect, &Rect))
1282 struct Region *Damage;
1284 Damage = NewRectRegion(Rect.MinX, Rect.MinY, Rect.MaxX, Rect.MaxY);
1285 if (Damage)
1289 ClearRegionRegion(L->VisibleRegion, Damage)
1291 Damage->RegionRectangle
1294 struct Region Tmp;
1296 We play sort of dirty here, by making assumptions about the internals of the
1297 Region structure and the region handling functions, but we are allowed to do that,
1298 aren't we? ;-)
1301 Tmp = *Damage;
1303 TranslateRect(Bounds(Damage), -dx, -dy);
1307 ClearRegionRegion(&Tmp, Damage)
1309 Damage->RegionRectangle
1312 /* Join the new damage list with the old one */
1313 TranslateRect(Bounds(Damage), -MinX(L), -MinY(L));
1314 OrRegionRegion(Damage, L->DamageList);
1316 L->Flags |= LAYERREFRESH;
1320 DisposeRegion(Damage);
1325 AROS_BEGIN_PROFILING(SortLayerCR)
1327 #define LayersBase (struct LayersBase *)(GfxBase->gb_LayersBase)
1328 SortLayerCR(L, dx, dy);
1329 #undef LayersBase
1331 AROS_END_PROFILING
1333 AROS_BEGIN_PROFILING(Blitting loop)
1335 #if USE_OLDMoveRaster
1338 struct ClipRect *LastHiddenCR;
1340 for (LastHiddenCR = NULL, SrcCR = L->ClipRect; SrcCR; SrcCR = SrcCR->Next)
1342 SrcCR->_p1 = LastHiddenCR;
1344 if (SrcCR->lobs)
1345 LastHiddenCR = SrcCR;
1350 for (SrcCR = L->ClipRect; SrcCR; SrcCR = SrcCR->Next)
1352 int cando = 0;
1354 if (SrcCR->lobs && (L->Flags & LAYERSIMPLE))
1356 continue;
1359 if (_AndRectRect(&ScrollRect, Bounds(SrcCR), &Rect))
1361 TranslateRect(&Rect, -dx, -dy);
1363 if (_AndRectRect(&ScrollRect, &Rect, &Rect))
1364 cando = 1;
1367 if (cando)
1369 /* Rect.Min(X|Y) are the coordinates to wich the rectangle has to be moved
1370 Rect.Max(X|Y) - Rect.Max(X|Y) - 1 are the dimensions of this rectangle */
1371 if (!SrcCR->_p1 && !SrcCR->lobs)
1373 /* there are no hidden/obscured rectangles this recrtangle has to deal with*/
1374 BltBitMap
1376 rp->BitMap,
1377 Rect.MinX + dx,
1378 Rect.MinY + dy,
1379 rp->BitMap,
1380 Rect.MinX,
1381 Rect.MinY,
1382 Rect.MaxX - Rect.MinX + 1,
1383 Rect.MaxY - Rect.MinY + 1,
1384 0xc0, /* copy */
1385 0xff,
1386 NULL
1389 else
1391 struct BitMap *srcbm;
1392 struct RegionRectangle *rr;
1393 struct Region *RectRegion;
1394 struct Rectangle Tmp;
1395 struct ClipRect *HiddCR;
1396 WORD corrsrcx, corrsrcy;
1397 BOOL dosrcsrc;
1399 RectRegion = NewRectRegion(Rect.MinX, Rect.MinY, Rect.MaxX, Rect.MaxY);
1400 if (!RectRegion)
1401 goto failexit;
1403 if (SrcCR->lobs)
1405 if (L->Flags & LAYERSUPER)
1407 corrsrcx = - MinX(L) - L->Scroll_X;
1408 corrsrcy = - MinY(L) - L->Scroll_Y;
1410 else
1412 corrsrcx = - MinX(SrcCR) + ALIGN_OFFSET(MinX(SrcCR));
1413 corrsrcy = - MinY(SrcCR);
1415 srcbm = SrcCR->BitMap;
1417 else
1419 corrsrcx = 0;
1420 corrsrcy = 0;
1421 srcbm = rp->BitMap;
1424 for (HiddCR = SrcCR->_p1; HiddCR; HiddCR = HiddCR->_p1)
1426 if (_AndRectRect(Bounds(RectRegion), Bounds(HiddCR), &Tmp))
1428 if (!(L->Flags & LAYERSIMPLE))
1430 WORD corrdstx, corrdsty;
1432 if (L->Flags & LAYERSUPER)
1434 corrdstx = - MinX(L) - L->Scroll_X;
1435 corrdsty = - MinY(L) - L->Scroll_Y;
1437 else
1439 /* Smart layer */
1440 corrdstx = - MinX(HiddCR) + ALIGN_OFFSET(MinX(HiddCR));
1441 corrdsty = - MinY(HiddCR);
1445 BltBitMap
1447 srcbm,
1448 Tmp.MinX + corrsrcx + dx,
1449 Tmp.MinY + corrsrcy + dy,
1450 HiddCR->BitMap,
1451 Tmp.MinX + corrdstx,
1452 Tmp.MinY + corrdsty,
1453 Tmp.MaxX - Tmp.MinX + 1,
1454 Tmp.MaxY - Tmp.MinY + 1,
1455 0xc0, /* copy */
1456 0xff,
1457 NULL
1461 if (!ClearRectRegion(RectRegion, &Tmp))
1463 DisposeRegion(RectRegion);
1464 goto failexit;
1469 if ((dosrcsrc = _AndRectRect(Bounds(SrcCR), &Rect, &Tmp)))
1471 if (!ClearRectRegion(RectRegion, &Tmp))
1473 DisposeRegion(RectRegion);
1474 goto failexit;
1478 for (rr = RectRegion->RegionRectangle; rr; rr = rr->Next)
1480 BltBitMap
1482 srcbm,
1483 MinX(rr) + MinX(RectRegion) + corrsrcx + dx,
1484 MinY(rr) + MinY(RectRegion) + corrsrcy + dy,
1485 rp->BitMap,
1486 MinX(rr) + MinX(RectRegion),
1487 MinY(rr) + MinY(RectRegion),
1488 Width(rr),
1489 Height(rr),
1490 0xc0, /* copy */
1491 0xff,
1492 NULL
1496 if (dosrcsrc)
1498 BltBitMap
1500 srcbm,
1501 Tmp.MinX + corrsrcx + dx,
1502 Tmp.MinY + corrsrcy + dy,
1503 srcbm,
1504 Tmp.MinX + corrsrcx,
1505 Tmp.MinY + corrsrcy,
1506 Tmp.MaxX - Tmp.MinX + 1,
1507 Tmp.MaxY - Tmp.MinY + 1,
1508 0xc0, /* copy */
1509 0xff,
1510 NULL
1515 DisposeRegion(RectRegion);
1520 #else
1522 for (SrcCR = L->ClipRect; SrcCR; SrcCR = SrcCR->Next)
1524 if (_AndRectRect(&ScrollRect, Bounds(SrcCR), &Rect))
1526 TranslateRect(&Rect, -dx, -dy);
1528 if (_AndRectRect(&ScrollRect, &Rect, &Rect))
1530 struct BitMap *srcbm;
1531 struct ClipRect *DstCR;
1532 LONG corrsrcx, corrsrcy;
1533 ULONG area;
1535 if (SrcCR->lobs)
1537 if (L->Flags & LAYERSIMPLE) continue;
1539 if (L->Flags & LAYERSUPER)
1541 corrsrcx = - MinX(L) - L->Scroll_X;
1542 corrsrcy = - MinY(L) - L->Scroll_Y;
1544 else
1546 corrsrcx = - MinX(SrcCR) + ALIGN_OFFSET(MinX(SrcCR));
1547 corrsrcy = - MinY(SrcCR);
1549 srcbm = SrcCR->BitMap;
1551 else
1553 corrsrcx = 0;
1554 corrsrcy = 0;
1555 srcbm = rp->BitMap;
1558 area = (ULONG)(Rect.MaxX - Rect.MinX + 1) * (ULONG)(Rect.MaxY - Rect.MinY + 1);
1560 for (DstCR = L->ClipRect ; area && DstCR; DstCR = DstCR->Next)
1562 struct Rectangle Rect2;
1564 if (_AndRectRect(Bounds(DstCR), &Rect, &Rect2))
1566 struct BitMap *dstbm;
1567 LONG corrdstx, corrdsty;
1569 area -= (ULONG)(Rect2.MaxX - Rect2.MinX + 1) * (ULONG)(Rect2.MaxY - Rect2.MinY + 1);
1571 if (DstCR->lobs)
1573 if (L->Flags & LAYERSIMPLE) continue;
1575 if (L->Flags & LAYERSUPER)
1577 corrdstx = - MinX(L) - L->Scroll_X;
1578 corrdsty = - MinY(L) - L->Scroll_Y;
1580 else
1582 corrdstx = - MinX(DstCR) + ALIGN_OFFSET(MinX(DstCR));
1583 corrdsty = - MinY(DstCR);
1585 dstbm = DstCR->BitMap;
1587 else
1589 corrdstx = 0;
1590 corrdsty = 0;
1591 dstbm = rp->BitMap;
1594 BltBitMap
1596 srcbm,
1597 Rect2.MinX + corrsrcx + dx,
1598 Rect2.MinY + corrsrcy + dy,
1599 dstbm,
1600 Rect2.MinX + corrdstx,
1601 Rect2.MinY + corrdsty,
1602 Rect2.MaxX - Rect2.MinX + 1,
1603 Rect2.MaxY - Rect2.MinY + 1,
1604 0xC0,
1605 0xFF,
1606 NULL
1613 #endif
1614 AROS_END_PROFILING
1616 UnlockLayerRom(L);
1619 RELEASE_DRIVERDATA(rp, GfxBase);
1621 return TRUE;
1624 /****************************************************************************************/
1626 BOOL GetRPClipRectangleForLayer(struct RastPort *rp, struct Layer *lay,
1627 struct Rectangle *r, struct GfxBase *GfxBase)
1629 (void)GfxBase;
1631 if (RP_DRIVERDATA(rp)->dd_ClipRectangleFlags & RPCRF_VALID)
1633 *r = RP_DRIVERDATA(rp)->dd_ClipRectangle;
1635 if (RP_DRIVERDATA(rp)->dd_ClipRectangleFlags & RPCRF_RELRIGHT)
1637 r->MaxX += (lay->bounds.MaxX - lay->bounds.MinX + 1) - 1;
1640 if (RP_DRIVERDATA(rp)->dd_ClipRectangleFlags & RPCRF_RELBOTTOM)
1642 r->MaxY += (lay->bounds.MaxY - lay->bounds.MinY + 1) - 1;
1645 r->MinX += lay->bounds.MinX;
1646 r->MinY += lay->bounds.MinY;
1647 r->MaxX += lay->bounds.MinX;
1648 r->MaxY += lay->bounds.MinY;
1650 return TRUE;
1653 return FALSE;
1656 /****************************************************************************************/
1658 BOOL GetRPClipRectangleForBitMap(struct RastPort *rp, struct BitMap *bm,
1659 struct Rectangle *r, struct GfxBase *GfxBase)
1661 if (RP_DRIVERDATA(rp)->dd_ClipRectangleFlags & RPCRF_VALID)
1664 *r = RP_DRIVERDATA(rp)->dd_ClipRectangle;
1666 if (RP_DRIVERDATA(rp)->dd_ClipRectangleFlags & RPCRF_RELRIGHT)
1668 LONG width = GetBitMapAttr(bm, BMA_WIDTH);
1670 r->MaxX += width - 1;
1673 if (RP_DRIVERDATA(rp)->dd_ClipRectangleFlags & RPCRF_RELBOTTOM)
1675 LONG height = GetBitMapAttr(bm, BMA_HEIGHT);
1677 r->MaxY += height - 1;
1680 return TRUE;
1683 return FALSE;
1686 /****************************************************************************************/