simplify rendering routine. small formatting fixes. separate rectlist from private...
[AROS.git] / workbench / c / Decoration / drawfuncs.c
blob7b0061691fe54c01d240fcdc951a4e6cbc948e62
1 /*
2 Copyright © 2011-2014, The AROS Development Team.
3 $Id$
4 */
6 #include <aros/debug.h>
8 #include <intuition/imageclass.h>
9 #include <graphics/rpattr.h>
10 #include <libraries/cybergraphics.h>
11 #include <proto/arossupport.h>
12 #include <proto/graphics.h>
13 #include <proto/cybergraphics.h>
14 #include <proto/layers.h>
15 #include <proto/exec.h>
17 #include <hidd/graphics.h>
19 #include <math.h>
21 #include "drawfuncs.h"
23 #if AROS_BIG_ENDIAN
24 #define GET_A(rgb) ((rgb >> 24) & 0xff)
25 #define GET_R(rgb) ((rgb >> 16) & 0xff)
26 #define GET_G(rgb) ((rgb >> 8) & 0xff)
27 #define GET_B(rgb) (rgb & 0xff)
28 #define SET_ARGB(a, r, g, b) a << 24 | r << 16 | g << 8 | b
29 #else
30 #define GET_A(rgb) (rgb & 0xff)
31 #define GET_R(rgb) ((rgb >> 8) & 0xff)
32 #define GET_G(rgb) ((rgb >> 16) & 0xff)
33 #define GET_B(rgb) ((rgb >> 24) & 0xff)
34 #define SET_ARGB(a, r, g, b) b << 24 | g << 16 | r << 8 | a
35 #endif
37 struct ShadeData
39 struct NewImage *ni;
40 UWORD fact;
43 struct RectList
45 ULONG rl_num;
46 struct RectList *rl_next;
47 struct Rectangle rl_rect;
50 struct layerhookmsg
52 struct Layer *l;
53 /* struct Rectangle rect; (replaced by the next line!) */
54 WORD MinX, MinY, MaxX, MaxY;
55 LONG OffsetX, OffsetY;
58 /* This function provides a number of ways to blit a NewImage onto RastPort. Please take great care when modifying it.
60 * The number of combinations of arguments is quite high. Please take time to understand it.
62 * Arguments:
63 * ni - a NewImage that is to be blitted
64 * subimageCol, subimageRow - define the initial read offset in source image based on assumption that image contains
65 * a number of subimages drawn in rows or columns
66 * xSrc, ySrc - define additional read offset in the source image subimage
67 * destRP - destination RastPort to blit the image to
68 * xDest, yDest - coordinates on the destination RastPort to where the imatge will be blitted
69 * widthSrc, heightSrc - width/height of region to be read from, if -1 then use the width/height of subimage
70 * widthDest, heightDest - width/height of blit on destination RastPort, if -1 then use widthSrc/heightSrc
73 static void BltScaleNewImageSubImageRastPort(struct NewImage * ni, ULONG subimageCol, ULONG subimageRow,
74 LONG xSrc, LONG ySrc, struct RastPort * destRP, LONG xDest, LONG yDest,
75 LONG widthSrc, LONG heightSrc, LONG widthDest, LONG heightDest)
77 ULONG subimagewidth = ni->w / ni->subimagescols;
78 ULONG subimageheight = ni->h / ni->subimagesrows;
80 if (subimageCol >= ni->subimagescols) return;
81 if (subimageRow >= ni->subimagesrows) return;
83 /* If source size not provided, use subimage size */
84 if (widthSrc < 0) widthSrc = (LONG)subimagewidth;
85 if (heightSrc < 0) heightSrc = (LONG)subimageheight;
87 /* If destination size not provided, use source */
88 if (widthDest < 0) widthDest = widthSrc;
89 if (heightDest < 0) heightDest = heightSrc;
91 /* If source and destination sizes do not match, scale */
92 if ((widthSrc != widthDest) || (heightSrc != heightDest))
94 /* FIXME: The scaled blitting needs similar optimized code paths as non-scaled */
95 ULONG * srcptr = (ni->data) + (((subimageheight * subimageRow) + ySrc) * ni->w) +
96 ((subimagewidth * subimageCol) + xSrc); /* Go to (0,0) of source rect */
98 ULONG * scaleddata = ScaleBuffer(srcptr, ni->w, widthSrc, heightSrc, widthDest, heightDest);
100 D(bug("[Decoration] SCALED %d,%d -> %d,%d!\n", widthSrc, heightSrc, widthDest, heightDest));
102 WritePixelArrayAlpha(scaleddata, 0, 0, widthDest * 4, destRP, xDest, yDest, widthDest, heightDest, 0xffffffff);
104 FreeVec(scaleddata);
106 else /* ((widthSrc != widthDest) || (heightSrc != heightDest)) */
108 /* Detect if image can be drawn using blitting instead of alpha draw */
109 if ((!ni->subimageinbm) || (!(ni->subimageinbm[subimageCol + (subimageRow * ni->subimagescols)])))
111 WritePixelArrayAlpha(ni->data, (subimagewidth * subimageCol) + xSrc ,
112 (subimageheight * subimageRow) + ySrc, ni->w * 4, destRP,
113 xDest, yDest, widthSrc, heightSrc, 0xffffffff);
115 else
117 /* LUT */
118 if (ni->bitmap != NULL)
120 if (ni->mask)
122 BltMaskBitMapRastPort(ni->bitmap, (subimagewidth * subimageCol) + xSrc ,
123 (subimageheight * subimageRow) + ySrc, destRP, xDest, yDest,
124 widthSrc, heightSrc, 0xe0, (PLANEPTR) ni->mask);
126 else
128 BltBitMapRastPort(ni->bitmap, (subimagewidth * subimageCol) + xSrc ,
129 (subimageheight * subimageRow) + ySrc, destRP, xDest, yDest,
130 widthSrc, heightSrc, 0xc0);
134 /* Truecolor */
135 if (ni->bitmap2 != NULL)
137 BltBitMapRastPort(ni->bitmap2, (subimagewidth * subimageCol) + xSrc ,
138 (subimageheight * subimageRow) + ySrc, destRP, xDest, yDest,
139 widthSrc, heightSrc, 0xc0);
145 /* HELPER WRAPPERS */
146 static inline void BltNewImageSubImageRastPort(struct NewImage * ni, ULONG subimageCol, ULONG subimageRow,
147 LONG xSrc, LONG ySrc, struct RastPort * destRP, LONG xDest, LONG yDest, LONG widthSrc, LONG heightSrc)
149 BltScaleNewImageSubImageRastPort(ni, subimageCol, subimageRow, xSrc, ySrc, destRP,
150 xDest, yDest, widthSrc, heightSrc, -1, -1);
153 static inline void BltNewImageSubImageRastPortSimple(struct NewImage * ni, ULONG subimageCol, ULONG subimageRow,
154 struct RastPort * destRP, LONG xDest, LONG yDest)
156 BltNewImageSubImageRastPort(ni, subimageCol, subimageRow, 0, 0, destRP,
157 xDest, yDest, -1, -1);
160 static inline void BltScaleNewImageSubImageRastPortSimple(struct NewImage * ni, ULONG subimageCol, ULONG subimageRow,
161 struct RastPort * destRP, LONG xDest, LONG yDest, LONG widthDest, LONG heightDest)
163 BltScaleNewImageSubImageRastPort(ni, subimageCol, subimageRow, 0, 0, destRP,
164 xDest, yDest, -1, -1, widthDest, heightDest);
166 /* HELPER WRAPPERS */
168 static void DrawTileToImage(struct NewImage *src, struct NewImage *dest, UWORD _sx, UWORD _sy, UWORD _sw, UWORD _sh, UWORD _dx, UWORD _dy, UWORD _dw, UWORD _dh)
171 ULONG dy, dx;
172 LONG dh, height, dw, width;
174 if (src == NULL) return;
175 if (dest == NULL) return;
177 dh = _sh;
178 dy = _dy;
179 height = _dh;
181 while (height > 0)
183 if ((height-dh)<0) dh = height;
184 height -= dh;
185 dw = _sw;
186 width = _dw;
187 dx = _dx;
188 while (width > 0)
190 if ((width-dw)<0) dw = width;
191 width -= dw;
192 DrawPartToImage(src, dest, _sx, _sy, dw, dh, dx, dy);
193 dx += dw;
195 dy += dh;
199 static void TileImageToImageMenuBar(struct NewImage *src, struct TileInfo * srcti, struct NewImage *dest)
201 UWORD y, h;
203 if (dest == NULL) return;
204 if (src == NULL) return;
205 if (srcti == NULL) return;
206 y = 0;
208 h = src->h;
210 if ((srcti->TileTop + srcti->TileBottom) > dest->h) return;
211 if (srcti->TileRight > dest->w) return;
213 DrawTileToImage(src, dest, srcti->TileLeft, y, src->w - srcti->TileLeft - srcti->TileRight, srcti->TileTop, 0, 0, dest->w - srcti->TileRight, srcti->TileTop);
214 DrawTileToImage(src, dest, srcti->TileLeft, y + h - srcti->TileBottom, src->w - srcti->TileLeft - srcti->TileRight, srcti->TileBottom, 0, dest->h - srcti->TileBottom, dest->w - srcti->TileRight, srcti->TileBottom);
215 DrawTileToImage(src, dest, srcti->TileLeft, y + srcti->TileTop, src->w - srcti->TileLeft - srcti->TileRight, h - srcti->TileBottom - srcti->TileTop, 0, srcti->TileTop + 0, dest->w - srcti->TileRight, dest->h - srcti->TileTop - srcti->TileBottom - 0);
218 DrawTileToImage(src, dest, src->w - srcti->TileRight, y, srcti->TileRight, srcti->TileTop, dest->w - srcti->TileRight, 0, srcti->TileRight, srcti->TileTop);
219 DrawTileToImage(src, dest, src->w - srcti->TileRight, y + h - srcti->TileBottom, srcti->TileRight, srcti->TileBottom, dest->w - srcti->TileRight , dest->h - srcti->TileBottom, srcti->TileRight, srcti->TileBottom);
220 DrawTileToImage(src, dest, src->w - srcti->TileRight, y + srcti->TileTop, srcti->TileRight, h - srcti->TileBottom - srcti->TileTop, dest->w - srcti->TileRight, srcti->TileTop + 0, srcti->TileRight, dest->h - srcti->TileTop - srcti->TileBottom - 0);
224 static void TileImageToImage(struct NewImage *src, struct TileInfo * srcti, struct NewImage *dest)
226 UWORD y, h;
228 if (dest == NULL) return;
229 if (src == NULL) return;
230 if (srcti == NULL) return;
231 y = 0;
233 h = src->h;
235 if ((srcti->TileTop + srcti->TileBottom) > dest->h) return;
236 if ((srcti->TileLeft + srcti->TileRight) > dest->w) return;
238 DrawTileToImage(src, dest, 0, y, srcti->TileLeft, srcti->TileTop, 0 , 0, srcti->TileLeft, srcti->TileTop);
239 DrawTileToImage(src, dest, 0, y + h - srcti->TileBottom, srcti->TileLeft, srcti->TileBottom, 0 , dest->h - srcti->TileBottom, srcti->TileLeft, srcti->TileBottom);
240 DrawTileToImage(src, dest, src->w - srcti->TileRight, y, srcti->TileRight, srcti->TileTop, dest->w - srcti->TileRight, 0, srcti->TileRight, srcti->TileTop);
241 DrawTileToImage(src, dest, src->w - srcti->TileRight, y + h - srcti->TileBottom, srcti->TileRight, srcti->TileBottom, dest->w - srcti->TileRight , dest->h - srcti->TileBottom, srcti->TileRight, srcti->TileBottom);
243 DrawTileToImage(src, dest, srcti->TileLeft, y, src->w - srcti->TileLeft - srcti->TileRight, srcti->TileTop, srcti->TileLeft, 0, dest->w - srcti->TileLeft - srcti->TileRight, srcti->TileTop);
244 DrawTileToImage(src, dest, srcti->TileLeft, y + h - srcti->TileBottom, src->w - srcti->TileLeft - srcti->TileRight, srcti->TileBottom, srcti->TileLeft, dest->h - srcti->TileBottom, dest->w - srcti->TileLeft - srcti->TileRight, srcti->TileBottom);
245 DrawTileToImage(src, dest, 0, y + srcti->TileTop, srcti->TileLeft, h - srcti->TileBottom - srcti->TileTop, 0 , srcti->TileTop + 0, srcti->TileLeft, dest->h - srcti->TileTop - srcti->TileBottom - 0);
246 DrawTileToImage(src, dest, src->w - srcti->TileRight, y + srcti->TileTop, srcti->TileRight, h - srcti->TileBottom - srcti->TileTop, dest->w - srcti->TileRight, srcti->TileTop + 0, srcti->TileRight, dest->h - srcti->TileTop - srcti->TileBottom - 0);
247 DrawTileToImage(src, dest, srcti->TileLeft, y + srcti->TileTop, src->w - srcti->TileLeft - srcti->TileRight, h - srcti->TileBottom - srcti->TileTop, srcti->TileLeft, srcti->TileTop + 0, dest->w - srcti->TileLeft - srcti->TileRight, dest->h - srcti->TileTop - srcti->TileBottom - 0);
250 static void MixImage(struct NewImage *dst, struct NewImage *src, struct TileInfo *srcti, UWORD ratio, UWORD w, UWORD h, UWORD dx, UWORD dy)
252 ULONG *s, *d;
253 ULONG rgba, rgb;
254 UWORD r, g, b;
255 UBYTE as, rs, gs, bs, rd, gd, bd;
256 BOOL tiled = FALSE;
257 int x, y;
259 if (src == NULL) return;
260 if (dst == NULL) return;
262 s = src->data;
263 d = dst->data;
265 if (srcti) tiled = TRUE;
267 for (y = 0; y < h; y++)
269 for (x = 0; x < w; x++)
271 rgba = s[x+y*src->w];
272 as = GET_A(rgba);
273 rs = GET_R(rgba);
274 gs = GET_G(rgba);
275 bs = GET_B(rgba);
276 rgb = d[x+dx + (y+dy) * dst->w];
278 rd = GET_R(rgb);
279 gd = GET_G(rgb);
280 bd = GET_B(rgb);
282 r = ((rs * ratio) >> 8) + ((rd * (255 - ratio)) >> 8);
283 g = ((gs * ratio) >> 8) + ((gd * (255 - ratio)) >> 8);
284 b = ((bs * ratio) >> 8) + ((bd * (255 - ratio)) >> 8);
286 if (tiled) {
287 r = ((r * as) >> 8) + ((rd * (255 - as)) >> 8);
288 g = ((g * as) >> 8) + ((gd * (255 - as)) >> 8);
289 b = ((b * as) >> 8) + ((bd * (255 - as)) >> 8);
292 r = r & 0xff;
293 g = g & 0xff;
294 b = b & 0xff;
296 d[x+dx + (y+dy) * dst->w] = SET_ARGB(as, r, g, b);
302 static void BlurSourceAndMixTexture(struct NewImage *pic, struct NewImage *texture, struct TileInfo * textureti, UWORD ratio)
304 int x, y, ytw, t1, t2, b1, b2, l1, l2, r1, r2;
305 UWORD red, green, blue, alpha= 0, rs, gs, bs, as;
306 ULONG rgb, argb;
307 int width, w, height, ah, aw, xpos, ypos;
308 BOOL tiled = FALSE;
309 ULONG *raw, tw, th;
311 if (pic == NULL) return;
312 if (pic->data == NULL) return;
314 tw = pic->w;
315 if (textureti) tiled = TRUE;
316 th = pic->h;
317 raw = pic->data;
318 height = th;
319 width = tw;
321 if (raw)
323 for (y = 0; y < th; y++)
325 t1 = tw;
326 t2 = tw+tw;
327 b1 = tw;
328 b2 = tw+tw;
329 if (y == 0) t1 = t2 = 0;
330 else if (y == 1) t2 = t1;
332 if (y == (th-1)) b1 = b2 = 0;
333 else if (y == (th-2)) b2 = b1;
335 ytw = y*tw;
337 for (x = 0; x < tw; x++)
339 r1 = 1;
340 r2 = 2;
341 l1 = 1;
342 l2 = 2;
344 if (x == 0) l1 = r1 = 0;
345 else if (x == 1) l2 = l1;
347 if (x == (tw-1)) r1 = r2 = 0;
348 else if (x == (tw-2)) r2 = r1;
350 rgb = raw[x+ytw];
351 red = GET_R(rgb);
352 green = GET_G(rgb);
353 blue = GET_B(rgb);
355 rgb = raw[x+ytw-t2];
356 red += GET_R(rgb);
357 green += GET_G(rgb);
358 blue += GET_B(rgb);
360 rgb = raw[x+ytw-l1-t1];
361 red += GET_R(rgb);
362 green += GET_G(rgb);
363 blue += GET_B(rgb);
365 rgb = raw[x+ytw-t1];
366 red += GET_R(rgb);
367 green += GET_G(rgb);
368 blue += GET_B(rgb);
370 rgb = raw[x+ytw-t1];
371 red += GET_R(rgb);
372 green += GET_G(rgb);
373 blue += GET_B(rgb);
375 rgb = raw[x+ytw-t1+r1];
376 red += GET_R(rgb);
377 green += GET_G(rgb);
378 blue += GET_B(rgb);
380 rgb = raw[x+ytw-l2];
381 red += GET_R(rgb);
382 green += GET_G(rgb);
383 blue += GET_B(rgb);
385 rgb = raw[x+ytw-l1];
386 red += GET_R(rgb);
387 green += GET_G(rgb);
388 blue += GET_B(rgb);
390 rgb = raw[x+ytw+r1];
391 red += GET_R(rgb);
392 green += GET_G(rgb);
393 blue += GET_B(rgb);
395 rgb = raw[x+ytw+r2];
396 red += GET_R(rgb);
397 green += GET_G(rgb);
398 blue += GET_B(rgb);
400 rgb = raw[x+ytw+b1-l1];
401 red += GET_R(rgb);
402 green += GET_G(rgb);
403 blue += GET_B(rgb);
405 rgb = raw[x+ytw+b1];
406 red += GET_R(rgb);
407 green += GET_G(rgb);
408 blue += GET_B(rgb);
410 rgb = raw[x+ytw+b1+r1];
411 red += GET_R(rgb);
412 green += GET_G(rgb);
413 blue += GET_B(rgb);
415 rgb = raw[x+ytw+b2];
416 red += GET_R(rgb);
417 green += GET_G(rgb);
418 blue += GET_B(rgb);
420 red = red/14;
421 green = green/14;
422 blue = blue/14;
423 alpha = 255;
425 if (tiled)
427 argb = raw[x+ytw];
428 as = 255 - GET_A(texture->data[x + y * texture->w]);
429 rs = GET_R(argb);
430 gs = GET_G(argb);
431 bs = GET_B(argb);
433 red = ((rs * as) >> 8) + ((red * (255 - as)) >> 8);
434 green = ((gs * as) >> 8) + ((green * (255 - as)) >> 8);
435 blue = ((bs * as) >> 8) + ((blue * (255 - as)) >> 8);
437 raw[x+ytw] = SET_ARGB(as, red, green, blue);
440 else
442 raw[x+ytw] = SET_ARGB(alpha, red, green, blue);
447 if (ratio < 100)
449 if (texture)
451 ypos = 0;
452 while (height>0)
454 ah = texture->h;
455 if (ah > height) ah = height;
456 xpos = 0;
457 w = width;
458 while (w>0)
460 aw = texture->w;
461 if (aw > w) aw = w;
462 MixImage(pic, texture, textureti, 255 - (2.55 * ratio), aw, ah, xpos, ypos);
463 w -= aw;
464 xpos += aw;
466 height -= ah;
467 ypos += ah;
473 static void RenderBackgroundTiled(struct NewImage *pic, struct NewImage *texture, struct TileInfo *textureti,
474 UWORD ratio, VOID (*TileImageToImageFunc)(struct NewImage *src, struct TileInfo * srcti, struct NewImage *dest))
476 struct NewImage *ni;
478 if (texture)
480 ni = NewImageContainer(pic->w, pic->h);
481 if (ni)
483 if (textureti)
485 TileImageToImageFunc(texture, textureti, ni);
486 BlurSourceAndMixTexture(pic, ni, textureti, ratio);
488 else BlurSourceAndMixTexture(pic, texture, textureti, ratio);
490 DisposeImageContainer(ni);
492 else BlurSourceAndMixTexture(pic, texture, textureti, ratio);
494 else BlurSourceAndMixTexture(pic, NULL, NULL, ratio);
497 static void DrawMapTileToRP(struct NewImage *src, struct RastPort *rp, UWORD _sx, UWORD _sy, UWORD _sw, UWORD _sh, UWORD _dx, UWORD _dy, UWORD _dw, UWORD _dh)
500 ULONG dy, dx;
501 LONG dh, height, dw, width;
503 if (src == NULL) return;
504 if (rp == NULL) return;
506 dh = _sh;
507 dy = _dy;
508 height = _dh;
510 if (!src->ok) return;
512 while (height > 0)
514 if ((height-dh)<0) dh = height;
515 height -= dh;
516 dw = _sw;
517 width = _dw;
518 dx = _dx;
519 while (width > 0)
521 if ((width-dw)<0) dw = width;
522 width -= dw;
524 if (src->mask)
526 BltMaskBitMapRastPort(src->bitmap, _sx, _sy, rp, dx, dy, dw, dh, 0xe0, (PLANEPTR) src->mask);
528 else BltBitMapRastPort(src->bitmap, _sx, _sy, rp, dx, dy, dw, dh, 0xc0);
530 dx += dw;
532 dy += dh;
536 /******************************************************************************/
537 /******************************************************************************/
538 /******************************************************************************/
539 /******************************************************************************/
540 /******************************************************************************/
542 void DrawPartImageToRP(struct RastPort *rp, struct NewImage *ni, UWORD x, UWORD y, UWORD sx, UWORD sy, UWORD sw, UWORD sh)
544 if (ni->ok)
546 if (ni->bitmap == NULL)
548 WritePixelArray(ni->data, sx, sy, ni->w*4, rp, x, y, sw, sh, RECTFMT_ARGB);
550 else
552 BltBitMapRastPort(ni->bitmap, sx, sy, rp, x, y, sw, sh, 0xc0);
557 void DrawPartToImage(struct NewImage *src, struct NewImage *dest, UWORD sx, UWORD sy, UWORD sw, UWORD sh, UWORD dx, UWORD dy)
559 UWORD x, y;
561 for (y = 0; y < sh; y++)
563 for (x = 0; x < sw; x++)
565 dest->data[dx + x + (dy + y) * dest->w] = src->data[sx + x + (sy + y) * src->w];
570 void RenderMenuBackground(struct NewImage *pic, struct NewImage *texture, struct TileInfo *textureti, UWORD ratio)
572 if (texture)
574 if (textureti) RenderBackgroundTiled(pic, texture, textureti, ratio, TileImageToImage);
575 else BlurSourceAndMixTexture(pic, texture, textureti, ratio);
577 else BlurSourceAndMixTexture(pic, NULL, NULL, ratio);
580 void RenderMenuBarBackground(struct NewImage *pic, struct NewImage *texture, struct TileInfo *textureti, UWORD ratio)
582 if (texture && textureti)
585 /* Fill the image with the center tile */
586 DrawTileToImage(texture, pic,
587 textureti->TileLeft, textureti->TileTop,
588 texture->w - textureti->TileLeft - textureti->TileRight, texture->h - textureti->TileBottom - textureti->TileTop,
589 0, 0, pic->w, pic->h);
591 RenderBackgroundTiled(pic, texture, textureti, ratio, TileImageToImageMenuBar);
595 void WriteAlphaPixelArray(struct NewImage *src, struct NewLUT8Image *dst, LONG sx, LONG sy, LONG dx, LONG dy, LONG w, LONG h)
597 ULONG *s = src->data;
598 ULONG argb;
599 UBYTE *d = dst->data;
600 int x, y;
602 for (y = 0; y < h; y++)
604 for (x = 0; x < w; x++)
606 argb = s[sx + x + (sy + y) * src->w];
607 d[dx + x + (dy + y) * dst->w] = GET_A(argb);
612 void SetImageTint(struct NewImage *dst, UWORD ratio, ULONG argb)
615 ULONG *d;
616 ULONG rgb;
617 UWORD r, g, b, w, h;
618 UBYTE rs, gs, bs, rd, gd, bd;
619 int x, y;
621 if (dst == NULL) return;
623 d = dst->data;
625 w = dst->w;
626 h = dst->h;
628 rs = (argb >> 16) & 0xff;
629 gs = (argb >> 8) & 0xff;
630 bs = argb & 0xff;
632 for (y = 0; y < h; y++)
634 for (x = 0; x < w; x++)
636 rgb = d[x + y * w];
637 rd = GET_R(rgb);
638 gd = GET_G(rgb);
639 bd = GET_B(rgb);
640 r = ((rs * ratio) >> 8) + ((rd * (255 - ratio)) >> 8);
641 g = ((gs * ratio) >> 8) + ((gd * (255 - ratio)) >> 8);
642 b = ((bs * ratio) >> 8) + ((bd * (255 - ratio)) >> 8);
644 r = r & 0xff;
645 g = g & 0xff;
646 b = b & 0xff;
648 d[x + y * w] = SET_ARGB(255, r, g, b);
654 * offx - offset between start of ni and place where image should be sample from
655 * offy - offset between start of ni and place where image should be sample from
656 * x, y, w, h - coords in rastport rp
658 void HorizVertRepeatNewImage(struct NewImage *ni, ULONG color, UWORD offx, UWORD offy, struct RastPort *rp, UWORD x, UWORD y, WORD w, WORD h)
660 ULONG ow, oh, sy, sx, dy, dx;
661 LONG dh, height, dw, width;
663 if ((w <= 0) || (h <= 0)) return;
665 if (!ni->ok)
667 FillPixelArray(rp, x, y, w, h, color);
668 return;
671 ow = ni->w;
672 oh = ni->h;
674 sy = offy % oh;
675 dh = oh - sy;
676 height = h;
677 dy = y;
678 while (height > 0)
680 if ((height-dh)<0) dh = height;
681 height -= dh;
683 sx = offx % ow;
684 dw = ow - sx;
685 width = w;
686 dx = x;
687 while (width > 0)
689 if ((width-dw)<0) dw = width;
690 width -= dw;
692 BltNewImageSubImageRastPort(ni, 0, 0, sx, sy, rp, dx, dy, dw, dh);
694 dx += dw;
695 sx = 0;
696 dw = ow;
698 dy += dh;
699 sy = 0;
700 dh = oh;
704 /* NOTE: fill parameter is ignored, previously it was forcing a no-alpha blit, but
705 this is already handled in BltNewImageSubImageRastPort */
706 /* dh - destination height to which subimage will be scaled to */
707 LONG WriteTiledImageTitle(BOOL fill, struct Window *win,
708 struct RastPort *rp, struct NewImage *ni, LONG sx, LONG sy, LONG sw,
709 LONG sh, LONG xp, LONG yp, LONG dw, LONG dh)
711 int w = dw;
712 int x = xp;
713 int ddw;
715 if (!ni->ok) return x;
717 if ((sw == 0) || (dw == 0)) return xp;
719 if (win)
721 if (x > win->Width) return xp;
722 if ((x + w) > win->Width) w = win->Width - x;
725 while (w > 0)
727 ddw = sw;
728 if (w < ddw) ddw = w;
730 BltScaleNewImageSubImageRastPort(ni, 0, 0, sx, sy, rp, x, yp, ddw, -1, -1, dh);
732 w -= ddw;
733 x += ddw;
735 return x;
739 * dh - destination height to scale to, -1 to use subimage height
741 LONG WriteVerticalScaledTiledImageHorizontal(struct RastPort *rp, struct NewImage *ni, ULONG subimage,
742 LONG sx, LONG sw, LONG xp, LONG yp, LONG sh, LONG dw, LONG dh)
744 LONG w = dw;
745 LONG x = xp;
746 LONG ddw;
748 if (!ni->ok) return xp;
750 if ((sw == 0) || (dw == 0)) return xp;
752 while (w > 0)
754 ddw = sw;
755 if (w < ddw) ddw = w;
757 BltScaleNewImageSubImageRastPort(ni, 0, subimage, sx, 0, rp, x, yp, ddw, sh, -1, dh);
759 w -= ddw;
760 x += ddw;
763 return x;
766 LONG WriteTiledImageHorizontal(struct RastPort *rp, struct NewImage *ni, ULONG subimage, LONG sx, LONG sw, LONG xp, LONG yp, LONG dw)
768 return WriteVerticalScaledTiledImageHorizontal(rp, ni, subimage, sx, sw, xp, yp, -1, dw, -1);
771 LONG WriteTiledImageVertical(struct RastPort *rp, struct NewImage *ni, ULONG subimage, LONG sy, LONG sh, LONG xp, LONG yp, LONG dh)
773 int h = dh;
774 int y = yp;
775 int ddh;
777 if (!ni->ok) return y;
779 if ((sh == 0) || (dh == 0)) return yp;
781 while (h > 0)
783 ddh = sh;
784 if (h < ddh) ddh = h;
786 BltNewImageSubImageRastPort(ni, subimage, 0, 0, sy, rp, xp, y, -1, ddh);
788 h -= ddh;
789 y += ddh;
791 return y;
794 struct myrgb
796 int red,green,blue;
799 void FillMemoryBufferRGBGradient(UBYTE * buf, LONG pen, LONG xt, LONG yt, LONG xb, LONG yb, LONG xp, LONG yp, LONG w, LONG h, ULONG start_rgb, ULONG end_rgb, LONG angle)
801 /* The basic idea of this algorithm is to calc the intersection between the
802 * diagonal of the rectangle (xs,ys) with dimension (xw,yw) a with the line starting
803 * at (x,y) (every pixel inside the rectangle) and angle angle with direction vector (vx,vy).
805 * Having the intersection point we then know the color of the pixel.
807 * TODO: Turn the algorithm into a incremental one
808 * Remove the use of floating point variables */
809 double rad = angle*M_PI/180;
810 double cosarc = cos(rad);
811 double sinarc = sin(rad);
813 struct myrgb startRGB,endRGB;
815 int diffR, diffG, diffB;
817 int r,t; /* some helper variables to short the code */
818 int l,y,c,x;
819 int y1; /* The intersection point */
820 int incr_y1; /* increment of y1 */
821 int xs,ys,xw,yw;
822 int xadd,ystart,yadd;
823 // double vx = -cosarc;
824 // double vy = sinarc;
825 int vx = (int)(-cosarc*0xff);
826 int vy = (int)(sinarc*0xff);
828 int width = xb - xt + 1;
829 int height = yb - yt + 1;
831 if (buf == NULL) return;
833 startRGB.red = (start_rgb >> 16) & 0xff;
834 startRGB.green = (start_rgb >> 8) & 0xff;
835 startRGB.blue = start_rgb & 0xff;
837 endRGB.red = (end_rgb >> 16) & 0xff;
838 endRGB.green = (end_rgb >> 8) & 0xff;
839 endRGB.blue = end_rgb & 0xff;
841 diffR = endRGB.red - startRGB.red;
842 diffG = endRGB.green - startRGB.green;
843 diffB = endRGB.blue - startRGB.blue;
845 /* Normalize the angle */
846 if (angle < 0) angle = 360 - ((-angle)%360);
847 if (angle >= 0) angle = angle % 360;
849 if (angle <= 90 || (angle > 180 && angle <= 270))
851 /* The to be intersected diagonal goes from the top left edge to the bottom right edge */
852 xs = 0;
853 ys = 0;
854 xw = width;
855 yw = height;
856 } else
858 /* The to be intersected diagonal goes from the bottom left edge to the top right edge */
859 xs = 0;
860 ys = height;
861 xw = width;
862 yw = -height;
865 if (angle > 90 && angle <= 270)
867 /* for these angle we have y1 = height - y1. Instead of
869 * y1 = height - (-vy*(yw* xs -xw* ys) + yw*(vy* x -vx* y)) /(-yw*vx + xw*vy);
871 * we can write
873 * y1 = (-vy*(yw*(-xs)-xw*(-ys+height)) + yw*(vy*(-x)-vx*(-y+height)))/(-yw*vx + xw*vy);
875 * so height - y1 can be expressed with the normal formular adapting some parameters.
877 * Note that if one would exchanging startRGB/endRGB the values would only work
878 * for linear color gradients */
879 xadd = -1;
880 yadd = -1;
881 ystart = height;
883 xs = -xs;
884 ys = -ys + height;
886 else
888 xadd = 1;
889 yadd = 1;
890 ystart = 0;
893 r = -vy*(yw*xs-xw*ys);
894 t = -yw*vx + xw*vy;
896 /* The formular as shown above is
898 * y1 = ((-vy*(yw*xs-xw*ys) + yw*(vy*x-vx*y)) /(-yw*vx + xw*vy));
900 * We see that only yw*(vy*x-vx*y) changes during the loop.
902 * We write
904 * Current Pixel: y1(x,y) = (r + yw*(vy*x-vx*y))/t = r/t + yw*(vy*x-vx*y)/t
905 * Next Pixel: y1(x+xadd,y) = (r + vw*(vy*(x+xadd)-vx*y))/t
907 * t*(y1(x+xadd,y) - y1(x,y)) = yw*(vy*(x+xadd)-vx*y) - yw*(vy*x-vx*y) = yw*vy*xadd; */
909 incr_y1 = yw*vy*xadd;
910 UBYTE *bufptr = buf;
911 for (l = 0, y = ystart + ((yp - yt)* yadd); l < h; l++, y+=yadd)
913 /* Calculate initial y1 accu, can be brought out of the loop as well (x=0). It's probably a
914 * a good idea to add here also a value of (t-1)/2 to ensure the correct rounding
915 * This (and for r) is also a place were actually a overflow can happen |yw|=16 |y|=16. So for
916 * vx nothing is left, currently 9 bits are used for vx or vy */
917 int y1_mul_t_accu = r - yw*vx*y;
921 for (c = 0, x = ((xp - xt) * xadd); c < w; c++, x+=xadd)
923 int red,green,blue;
925 /* Calculate the intersection of two lines, this is not the fastet way to do but
926 * it is intuitive. Note: very slow! Will be optimzed later (remove FFP usage
927 * and making it incremental)...update: it's now incremental and no FFP is used
928 * but it probably can be optimized more by removing some more of the divisions and
929 * further specialize the stuff here (use of three accus). */
930 /* y1 = (int)((-vy*(yw*xs-xw*ys) + yw*(vy*x-vx*y)) /(-yw*vx + xw*vy));*/
931 y1 = y1_mul_t_accu / t;
933 red = startRGB.red + (int)(diffR*y1/height);
934 green = startRGB.green + (int)(diffG*y1/height);
935 blue = startRGB.blue + (int)(diffB*y1/height);
936 /* By using full 32 bits this can be made faster as well */
937 *bufptr++ = red;
938 *bufptr++ = green;
939 *bufptr++ = blue;
941 y1_mul_t_accu += incr_y1;
947 void FillPixelArrayGradient(LONG pen, BOOL tc, struct RastPort *rp, LONG xt, LONG yt, LONG xb, LONG yb, LONG xp, LONG yp, LONG w, LONG h, ULONG start_rgb, ULONG end_rgb, LONG angle, LONG dx, LONG dy)
949 UBYTE * buf = NULL;
951 if ((w <= 0) || (h <= 0)) return;
953 /* By bringing building the gradient array in the same format as the RastPort BitMap a call
954 to WritePixelArray() can be made also faster */
955 buf = AllocVec(1 * yb * 3, 0);
957 FillMemoryBufferRGBGradient(buf, pen, xt, yt, xb, yb, xp, yp, 1, yb, start_rgb, end_rgb, angle);
959 HorizRepeatBuffer(buf, dy, pen, tc, rp, xp, yp, w, h);
961 FreeVec(buf);
964 void HorizRepeatBuffer(UBYTE * buf, LONG offy, LONG pen, BOOL tc, struct RastPort *rp, LONG x, LONG y, LONG w, LONG h)
966 UBYTE * bufblit = NULL;
967 ULONG xi, yi;
968 ULONG idxd;
969 ULONG idxs;
971 if ((w <= 0) || (h <= 0)) return;
972 if (!tc)
974 if (pen != -1) SetAPen(rp, pen); else SetAPen(rp, 2);
975 RectFill(rp, x, y, x + w - 1, y + h - 1);
976 return;
979 /* By bringing building the gradient array in the same format as the RastPort BitMap a call
980 to WritePixelArray() can be made also faster */
981 bufblit = AllocVec(w * h * 3, MEMF_ANY);
983 /* Copy one column buffer into blit buffer */
984 for (yi = 0; yi < h; yi++)
986 idxs = (offy + yi) * 3; /* source index */
987 idxd = yi * 3 * w; /* dest index */
988 for (xi = 0; xi < w; xi++)
990 /* Copy RGB pixel */
991 bufblit[idxd++] = buf[idxs + 0];
992 bufblit[idxd++] = buf[idxs + 1];
993 bufblit[idxd++] = buf[idxs + 2];
997 WritePixelArray(bufblit, 0, 0, w * 3, rp, x, y, w, h, RECTFMT_RGB);
999 FreeVec(bufblit);
1002 void TileMapToBitmap(struct NewImage *src, struct TileInfo *srcti, struct BitMap *map, UWORD dw, UWORD dh)
1004 UWORD y, h;
1006 if (map == NULL) return;
1007 if (src == NULL) return;
1008 if (srcti == NULL) return;
1009 y = 0;
1011 h = src->h;
1013 if ((srcti->TileTop + srcti->TileBottom) > dh) return;
1014 if ((srcti->TileLeft + srcti->TileRight) > dw) return;
1016 struct RastPort *dest = CreateRastPort();
1018 if (dest != NULL)
1020 dest->BitMap = map;
1022 DrawMapTileToRP(src, dest, 0, y, srcti->TileLeft, srcti->TileTop, 0 , 0, srcti->TileLeft, srcti->TileTop);
1023 DrawMapTileToRP(src, dest, 0, y + h - srcti->TileBottom, srcti->TileLeft, srcti->TileBottom, 0 , dh - srcti->TileBottom, srcti->TileLeft, srcti->TileBottom);
1024 DrawMapTileToRP(src, dest, src->w - srcti->TileRight, y, srcti->TileRight, srcti->TileTop, dw - srcti->TileRight, 0, srcti->TileRight, srcti->TileTop);
1025 DrawMapTileToRP(src, dest, src->w - srcti->TileRight, y + h - srcti->TileBottom, srcti->TileRight, srcti->TileBottom, dw - srcti->TileRight , dh - srcti->TileBottom, srcti->TileRight, srcti->TileBottom);
1027 DrawMapTileToRP(src, dest, srcti->TileLeft, y, src->w - srcti->TileLeft - srcti->TileRight, srcti->TileTop, srcti->TileLeft, 0, dw - srcti->TileLeft - srcti->TileRight, srcti->TileTop);
1028 DrawMapTileToRP(src, dest, srcti->TileLeft, y + h - srcti->TileBottom, src->w - srcti->TileLeft - srcti->TileRight, srcti->TileBottom, srcti->TileLeft, dh - srcti->TileBottom, dw - srcti->TileLeft - srcti->TileRight, srcti->TileBottom);
1029 DrawMapTileToRP(src, dest, 0, y + srcti->TileTop, srcti->TileLeft, h - srcti->TileBottom - srcti->TileTop, 0 , srcti->TileTop + 0, srcti->TileLeft, dh - srcti->TileTop - srcti->TileBottom - 0);
1030 DrawMapTileToRP(src, dest, src->w - srcti->TileRight, y + srcti->TileTop, srcti->TileRight, h - srcti->TileBottom - srcti->TileTop, dw - srcti->TileRight, srcti->TileTop + 0, srcti->TileRight, dh - srcti->TileTop - srcti->TileBottom - 0);
1031 DrawMapTileToRP(src, dest, srcti->TileLeft, y + srcti->TileTop, src->w - srcti->TileLeft - srcti->TileRight, h - srcti->TileBottom - srcti->TileTop, srcti->TileLeft, srcti->TileTop + 0, dw - srcti->TileLeft - srcti->TileRight, dh - srcti->TileTop - srcti->TileBottom - 0);
1032 FreeRastPort(dest);
1036 struct NewImage *GetImageFromRP(struct RastPort *rp, UWORD x, UWORD y, UWORD w, UWORD h)
1038 struct NewImage *ni;
1040 ni = NewImageContainer(w, h);
1041 if (ni)
1043 ReadPixelArray(ni->data, 0, 0, w*4, rp, x, y, w, h, RECTFMT_ARGB);
1045 return ni;
1048 void PutImageToRP(struct RastPort *rp, struct NewImage *ni, UWORD x, UWORD y) {
1050 if (ni)
1052 if (ni->data) WritePixelArray(ni->data, 0, 0, ni->w*4, rp, x, y, ni->w, ni->h, RECTFMT_ARGB);
1053 DisposeImageContainer(ni);
1057 ULONG CalcShade(ULONG base, UWORD fact)
1059 int c0, c1, c2, c3;
1061 c0 = (base >> 24) & 0xff;
1062 c1 = (base >> 16) & 0xff;
1063 c2 = (base >> 8) & 0xff;
1064 c3 = base & 0xff;
1065 c0 *= fact;
1066 c1 *= fact;
1067 c2 *= fact;
1068 c3 *= fact;
1069 c0 = c0 >> 8;
1070 c1 = c1 >> 8;
1071 c2 = c2 >> 8;
1072 c3 = c3 >> 8;
1074 if (c0 > 255) c0 = 255;
1075 if (c1 > 255) c1 = 255;
1076 if (c2 > 255) c2 = 255;
1077 if (c3 > 255) c3 = 255;
1079 return (ULONG)((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
1082 AROS_UFH3(void, RectShadeFunc,
1083 AROS_UFHA(struct Hook * , h, A0),
1084 AROS_UFHA(struct RastPort * , rp, A2),
1085 AROS_UFHA(struct layerhookmsg *, msg, A1))
1087 AROS_USERFUNC_INIT
1089 struct ShadeData *data = h->h_Data;
1090 ULONG color;
1091 HIDDT_Color col;
1092 APTR bm_handle;
1093 int px, py, x, y;
1095 bm_handle = LockBitMapTags(rp->BitMap,
1096 TAG_END);
1098 for (px = msg->MinX; px < (msg->MaxX + 1); px++)
1100 x = (px - rp->Layer->bounds.MinX) % data->ni->w;
1101 for (py = msg->MinY; py < (msg->MaxY + 1); py++)
1103 y = (py - rp->Layer->bounds.MinY) % data->ni->h;
1105 color = CalcShade(data->ni->data[(y * data->ni->w) + x], data->fact);
1107 if (bm_handle)
1109 col.alpha = (HIDDT_ColComp)((color >> 16) & 0x0000FF00);
1110 col.red = (HIDDT_ColComp)((color >> 8) & 0x0000FF00);
1111 col.green = (HIDDT_ColComp)(color & 0x0000FF00);
1112 col.blue = (HIDDT_ColComp)((color << 8) & 0x0000FF00);
1114 HIDD_BM_PutPixel(HIDD_BM_OBJ(rp->BitMap), px, py, HIDD_BM_MapColor(HIDD_BM_OBJ(rp->BitMap), &col));
1116 else
1118 WriteRGBPixel(rp, px + msg->OffsetX - msg->MinX, py + msg->OffsetY - msg->MinY, color);
1123 if (bm_handle)
1125 struct RectList bm_rectlist;
1126 struct TagItem bm_ultags[3] =
1128 {UBMI_REALLYUNLOCK, TRUE },
1129 {UBMI_UPDATERECTS, (IPTR)&bm_rectlist },
1130 {TAG_DONE, 0 }
1133 bm_rectlist.rl_num = 1;
1134 bm_rectlist.rl_next = (struct RectList *)0;
1135 bm_rectlist.rl_rect.MinX = msg->MinX;
1136 bm_rectlist.rl_rect.MinY = msg->MinY;
1137 bm_rectlist.rl_rect.MaxX = msg->MaxX;
1138 bm_rectlist.rl_rect.MaxY = msg->MaxY;
1140 UnLockBitMapTagList(bm_handle, bm_ultags);
1143 AROS_USERFUNC_EXIT
1146 void ShadeLine(LONG pen, BOOL tc, BOOL usegradients, struct RastPort *rp, struct NewImage *ni, ULONG basecolor, UWORD fact, UWORD _offy, UWORD x0, UWORD y0, UWORD x1, UWORD y1)
1148 ULONG color;
1150 if ((x1 < x0) || (y1 < y0)) return;
1151 if (!tc)
1153 SetAPen(rp, pen);
1154 Move(rp, x0, y0);
1155 Draw(rp, x1, y1);
1156 return;
1158 if (usegradients)
1160 color = CalcShade(basecolor, fact);
1161 SetRPAttrs(rp, RPTAG_PenMode, FALSE, RPTAG_FgColor, color, TAG_DONE);
1162 Move(rp, x0, y0);
1163 Draw(rp, x1, y1);
1165 else if (ni->ok)
1167 struct ShadeData shadeParams;
1168 struct Hook shadeHook;
1169 struct Rectangle shadeRect;
1171 shadeRect.MinX = x0;
1172 shadeRect.MaxX = x1;
1173 shadeRect.MinY = y0;
1174 shadeRect.MaxY = y1;
1176 shadeParams.ni = ni;
1177 shadeParams.fact = fact;
1179 shadeHook.h_Entry = (HOOKFUNC)AROS_ASMSYMNAME(RectShadeFunc);
1180 shadeHook.h_Data = &shadeParams;
1182 DoHookClipRects(&shadeHook, rp, &shadeRect);
1184 else
1186 Move(rp, x0, y0);
1187 Draw(rp, x1, y1);
1191 void DrawScaledStatefulGadgetImageToRP(struct RastPort *rp, struct NewImage *ni, ULONG state, UWORD xp, UWORD yp,
1192 WORD scaledwidth, WORD scaledheight)
1195 UWORD subimagecol = 0;
1196 UWORD subimagerow = 0;
1198 if (ni->ok)
1200 switch(state)
1202 case IDS_NORMAL:
1203 break;
1204 case IDS_SELECTED:
1205 subimagecol = 1;
1206 break;
1207 case IDS_INACTIVENORMAL:
1208 subimagecol = 2;
1209 break;
1212 BltScaleNewImageSubImageRastPortSimple(ni, subimagecol, subimagerow, rp, xp, yp, scaledwidth, scaledheight);
1216 void DrawStatefulGadgetImageToRP(struct RastPort *rp, struct NewImage *ni, ULONG state, UWORD xp, UWORD yp)
1218 DrawScaledStatefulGadgetImageToRP(rp, ni, state, xp, yp, -1, -1);