Hint added.
[AROS.git] / workbench / c / Decoration / drawfuncs.c
blobbdbcb640459f204835d5aa0ee4dbc0fabf0ab7ef
1 /*
2 Copyright © 2011-2016, 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 #define DECOR_USELINEBUFF
25 #if AROS_BIG_ENDIAN
26 #define GET_A(rgb) ((rgb >> 24) & 0xff)
27 #define GET_R(rgb) ((rgb >> 16) & 0xff)
28 #define GET_G(rgb) ((rgb >> 8) & 0xff)
29 #define GET_B(rgb) (rgb & 0xff)
30 #define SET_ARGB(a, r, g, b) (a << 24 | r << 16 | g << 8 | b)
31 #else
32 #define GET_A(rgb) (rgb & 0xff)
33 #define GET_R(rgb) ((rgb >> 8) & 0xff)
34 #define GET_G(rgb) ((rgb >> 16) & 0xff)
35 #define GET_B(rgb) ((rgb >> 24) & 0xff)
36 #define SET_ARGB(a, r, g, b) (b << 24 | g << 16 | r << 8 | a)
37 #endif
39 struct ShadeData
41 struct NewImage *ni;
42 UWORD fact;
45 struct RectList
47 ULONG rl_num;
48 struct RectList *rl_next;
49 struct Rectangle rl_rect;
52 struct layerhookmsg
54 struct Layer *l;
55 /* struct Rectangle rect; (replaced by the next line!) */
56 WORD MinX, MinY, MaxX, MaxY;
57 LONG OffsetX, OffsetY;
60 /* This function provides a number of ways to blit a NewImage onto RastPort. Please take great care when modifying it.
62 * The number of combinations of arguments is quite high. Please take time to understand it.
64 * Arguments:
65 * ni - a NewImage that is to be blitted
66 * subimageCol, subimageRow - define the initial read offset in source image based on assumption that image contains
67 * a number of subimages drawn in rows or columns
68 * xSrc, ySrc - define additional read offset in the source image subimage
69 * destRP - destination RastPort to blit the image to
70 * xDest, yDest - coordinates on the destination RastPort to where the imatge will be blitted
71 * widthSrc, heightSrc - width/height of region to be read from, if -1 then use the width/height of subimage
72 * widthDest, heightDest - width/height of blit on destination RastPort, if -1 then use widthSrc/heightSrc
75 static void BltScaleNewImageSubImageRastPort(struct NewImage * ni, ULONG subimageCol, ULONG subimageRow,
76 LONG xSrc, LONG ySrc, struct RastPort * destRP, LONG xDest, LONG yDest,
77 LONG widthSrc, LONG heightSrc, LONG widthDest, LONG heightDest)
79 ULONG subimagewidth = ni->w / ni->subimagescols;
80 ULONG subimageheight = ni->h / ni->subimagesrows;
82 if (subimageCol >= ni->subimagescols) return;
83 if (subimageRow >= ni->subimagesrows) return;
85 /* If source size not provided, use subimage size */
86 if (widthSrc < 0) widthSrc = (LONG)subimagewidth;
87 if (heightSrc < 0) heightSrc = (LONG)subimageheight;
89 /* If destination size not provided, use source */
90 if (widthDest < 0) widthDest = widthSrc;
91 if (heightDest < 0) heightDest = heightSrc;
93 /* If source and destination sizes do not match, scale */
94 if ((widthSrc != widthDest) || (heightSrc != heightDest))
96 /* FIXME: The scaled blitting needs similar optimized code paths as non-scaled */
97 ULONG * srcptr = (ni->data) + (((subimageheight * subimageRow) + ySrc) * ni->w) +
98 ((subimagewidth * subimageCol) + xSrc); /* Go to (0,0) of source rect */
100 ULONG * scaleddata = ScaleBuffer(srcptr, ni->w, widthSrc, heightSrc, widthDest, heightDest);
102 D(bug("[Decoration] SCALED %d,%d -> %d,%d!\n", widthSrc, heightSrc, widthDest, heightDest));
104 WritePixelArrayAlpha(scaleddata, 0, 0, widthDest * 4, destRP, xDest, yDest, widthDest, heightDest, 0xffffffff);
106 FreeVec(scaleddata);
108 else /* ((widthSrc != widthDest) || (heightSrc != heightDest)) */
110 /* Detect if image can be drawn using blitting instead of alpha draw */
111 if ((!ni->subimageinbm) || (!(ni->subimageinbm[subimageCol + (subimageRow * ni->subimagescols)])))
113 WritePixelArrayAlpha(ni->data, (subimagewidth * subimageCol) + xSrc ,
114 (subimageheight * subimageRow) + ySrc, ni->w * 4, destRP,
115 xDest, yDest, widthSrc, heightSrc, 0xffffffff);
117 else
119 /* LUT */
120 if (ni->bitmap != NULL)
122 if (ni->mask)
124 BltMaskBitMapRastPort(ni->bitmap, (subimagewidth * subimageCol) + xSrc ,
125 (subimageheight * subimageRow) + ySrc, destRP, xDest, yDest,
126 widthSrc, heightSrc, 0xe0, (PLANEPTR) ni->mask);
128 else
130 BltBitMapRastPort(ni->bitmap, (subimagewidth * subimageCol) + xSrc ,
131 (subimageheight * subimageRow) + ySrc, destRP, xDest, yDest,
132 widthSrc, heightSrc, 0xc0);
136 /* Truecolor */
137 if (ni->bitmap2 != NULL)
139 BltBitMapRastPort(ni->bitmap2, (subimagewidth * subimageCol) + xSrc ,
140 (subimageheight * subimageRow) + ySrc, destRP, xDest, yDest,
141 widthSrc, heightSrc, 0xc0);
147 /* HELPER WRAPPERS */
148 static inline void BltNewImageSubImageRastPort(struct NewImage * ni, ULONG subimageCol, ULONG subimageRow,
149 LONG xSrc, LONG ySrc, struct RastPort * destRP, LONG xDest, LONG yDest, LONG widthSrc, LONG heightSrc)
151 BltScaleNewImageSubImageRastPort(ni, subimageCol, subimageRow, xSrc, ySrc, destRP,
152 xDest, yDest, widthSrc, heightSrc, -1, -1);
155 static inline void BltNewImageSubImageRastPortSimple(struct NewImage * ni, ULONG subimageCol, ULONG subimageRow,
156 struct RastPort * destRP, LONG xDest, LONG yDest)
158 BltNewImageSubImageRastPort(ni, subimageCol, subimageRow, 0, 0, destRP,
159 xDest, yDest, -1, -1);
162 static inline void BltScaleNewImageSubImageRastPortSimple(struct NewImage * ni, ULONG subimageCol, ULONG subimageRow,
163 struct RastPort * destRP, LONG xDest, LONG yDest, LONG widthDest, LONG heightDest)
165 BltScaleNewImageSubImageRastPort(ni, subimageCol, subimageRow, 0, 0, destRP,
166 xDest, yDest, -1, -1, widthDest, heightDest);
168 /* HELPER WRAPPERS */
170 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)
173 ULONG dy, dx;
174 LONG dh, height, dw, width;
176 if (src == NULL) return;
177 if (dest == NULL) return;
179 dh = _sh;
180 dy = _dy;
181 height = _dh;
183 while (height > 0)
185 if ((height-dh)<0) dh = height;
186 height -= dh;
187 dw = _sw;
188 width = _dw;
189 dx = _dx;
190 while (width > 0)
192 if ((width-dw)<0) dw = width;
193 width -= dw;
194 DrawPartToImage(src, dest, _sx, _sy, dw, dh, dx, dy);
195 dx += dw;
197 dy += dh;
201 static void TileImageToImageMenuBar(struct NewImage *src, struct TileInfo * srcti, struct NewImage *dest)
203 UWORD y, h;
205 if (dest == NULL) return;
206 if (src == NULL) return;
207 if (srcti == NULL) return;
208 y = 0;
210 h = src->h;
212 if ((srcti->TileTop + srcti->TileBottom) > dest->h) return;
213 if (srcti->TileRight > dest->w) return;
215 DrawTileToImage(src, dest, srcti->TileLeft, y, src->w - srcti->TileLeft - srcti->TileRight, srcti->TileTop, 0, 0, dest->w - srcti->TileRight, srcti->TileTop);
216 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);
217 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);
220 DrawTileToImage(src, dest, src->w - srcti->TileRight, y, srcti->TileRight, srcti->TileTop, dest->w - srcti->TileRight, 0, srcti->TileRight, srcti->TileTop);
221 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);
222 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);
226 static void TileImageToImage(struct NewImage *src, struct TileInfo * srcti, struct NewImage *dest)
228 UWORD y, h;
230 if (dest == NULL) return;
231 if (src == NULL) return;
232 if (srcti == NULL) return;
233 y = 0;
235 h = src->h;
237 if ((srcti->TileTop + srcti->TileBottom) > dest->h) return;
238 if ((srcti->TileLeft + srcti->TileRight) > dest->w) return;
240 DrawTileToImage(src, dest, 0, y, srcti->TileLeft, srcti->TileTop, 0 , 0, srcti->TileLeft, srcti->TileTop);
241 DrawTileToImage(src, dest, 0, y + h - srcti->TileBottom, srcti->TileLeft, srcti->TileBottom, 0 , dest->h - srcti->TileBottom, srcti->TileLeft, srcti->TileBottom);
242 DrawTileToImage(src, dest, src->w - srcti->TileRight, y, srcti->TileRight, srcti->TileTop, dest->w - srcti->TileRight, 0, srcti->TileRight, srcti->TileTop);
243 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);
245 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);
246 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);
247 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);
248 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);
249 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);
252 static void MixImage(struct NewImage *dst, struct NewImage *src, struct TileInfo *srcti, UWORD ratio, UWORD w, UWORD h, UWORD dx, UWORD dy)
254 ULONG *s, *d;
255 ULONG rgba, rgb;
256 UWORD r, g, b;
257 UBYTE as, rs, gs, bs, rd, gd, bd;
258 BOOL tiled = FALSE;
259 int x, y;
261 if (src == NULL) return;
262 if (dst == NULL) return;
264 s = src->data;
265 d = dst->data;
267 if (srcti) tiled = TRUE;
269 for (y = 0; y < h; y++)
271 for (x = 0; x < w; x++)
273 rgba = s[x+y*src->w];
274 as = GET_A(rgba);
275 rs = GET_R(rgba);
276 gs = GET_G(rgba);
277 bs = GET_B(rgba);
278 rgb = d[x+dx + (y+dy) * dst->w];
280 rd = GET_R(rgb);
281 gd = GET_G(rgb);
282 bd = GET_B(rgb);
284 r = ((rs * ratio) >> 8) + ((rd * (255 - ratio)) >> 8);
285 g = ((gs * ratio) >> 8) + ((gd * (255 - ratio)) >> 8);
286 b = ((bs * ratio) >> 8) + ((bd * (255 - ratio)) >> 8);
288 if (tiled) {
289 r = ((r * as) >> 8) + ((rd * (255 - as)) >> 8);
290 g = ((g * as) >> 8) + ((gd * (255 - as)) >> 8);
291 b = ((b * as) >> 8) + ((bd * (255 - as)) >> 8);
294 r = r & 0xff;
295 g = g & 0xff;
296 b = b & 0xff;
298 d[x+dx + (y+dy) * dst->w] = SET_ARGB(as, r, g, b);
304 static void BlurSourceAndMixTexture(struct NewImage *pic, struct NewImage *texture, struct TileInfo * textureti, UWORD ratio)
306 int x, y, ytw, t1, t2, b1, b2, l1, l2, r1, r2;
307 UWORD red, green, blue, alpha= 0, rs, gs, bs, as;
308 ULONG rgb, argb;
309 int width, w, height, ah, aw, xpos, ypos;
310 BOOL tiled = FALSE;
311 ULONG *raw, tw, th;
313 if (pic == NULL) return;
314 if (pic->data == NULL) return;
316 tw = pic->w;
317 if (textureti) tiled = TRUE;
318 th = pic->h;
319 raw = pic->data;
320 height = th;
321 width = tw;
323 if (raw)
325 for (y = 0; y < th; y++)
327 t1 = tw;
328 t2 = tw+tw;
329 b1 = tw;
330 b2 = tw+tw;
331 if (y == 0) t1 = t2 = 0;
332 else if (y == 1) t2 = t1;
334 if (y == (th-1)) b1 = b2 = 0;
335 else if (y == (th-2)) b2 = b1;
337 ytw = y*tw;
339 for (x = 0; x < tw; x++)
341 r1 = 1;
342 r2 = 2;
343 l1 = 1;
344 l2 = 2;
346 if (x == 0) l1 = r1 = 0;
347 else if (x == 1) l2 = l1;
349 if (x == (tw-1)) r1 = r2 = 0;
350 else if (x == (tw-2)) r2 = r1;
352 rgb = raw[x+ytw];
353 red = GET_R(rgb);
354 green = GET_G(rgb);
355 blue = GET_B(rgb);
357 rgb = raw[x+ytw-t2];
358 red += GET_R(rgb);
359 green += GET_G(rgb);
360 blue += GET_B(rgb);
362 rgb = raw[x+ytw-l1-t1];
363 red += GET_R(rgb);
364 green += GET_G(rgb);
365 blue += GET_B(rgb);
367 rgb = raw[x+ytw-t1];
368 red += GET_R(rgb);
369 green += GET_G(rgb);
370 blue += GET_B(rgb);
372 rgb = raw[x+ytw-t1];
373 red += GET_R(rgb);
374 green += GET_G(rgb);
375 blue += GET_B(rgb);
377 rgb = raw[x+ytw-t1+r1];
378 red += GET_R(rgb);
379 green += GET_G(rgb);
380 blue += GET_B(rgb);
382 rgb = raw[x+ytw-l2];
383 red += GET_R(rgb);
384 green += GET_G(rgb);
385 blue += GET_B(rgb);
387 rgb = raw[x+ytw-l1];
388 red += GET_R(rgb);
389 green += GET_G(rgb);
390 blue += GET_B(rgb);
392 rgb = raw[x+ytw+r1];
393 red += GET_R(rgb);
394 green += GET_G(rgb);
395 blue += GET_B(rgb);
397 rgb = raw[x+ytw+r2];
398 red += GET_R(rgb);
399 green += GET_G(rgb);
400 blue += GET_B(rgb);
402 rgb = raw[x+ytw+b1-l1];
403 red += GET_R(rgb);
404 green += GET_G(rgb);
405 blue += GET_B(rgb);
407 rgb = raw[x+ytw+b1];
408 red += GET_R(rgb);
409 green += GET_G(rgb);
410 blue += GET_B(rgb);
412 rgb = raw[x+ytw+b1+r1];
413 red += GET_R(rgb);
414 green += GET_G(rgb);
415 blue += GET_B(rgb);
417 rgb = raw[x+ytw+b2];
418 red += GET_R(rgb);
419 green += GET_G(rgb);
420 blue += GET_B(rgb);
422 red = red/14;
423 green = green/14;
424 blue = blue/14;
425 alpha = 255;
427 if (tiled)
429 argb = raw[x+ytw];
430 as = 255 - GET_A(texture->data[x + y * texture->w]);
431 rs = GET_R(argb);
432 gs = GET_G(argb);
433 bs = GET_B(argb);
435 red = ((rs * as) >> 8) + ((red * (255 - as)) >> 8);
436 green = ((gs * as) >> 8) + ((green * (255 - as)) >> 8);
437 blue = ((bs * as) >> 8) + ((blue * (255 - as)) >> 8);
439 raw[x+ytw] = SET_ARGB(as, red, green, blue);
442 else
444 raw[x+ytw] = SET_ARGB(alpha, red, green, blue);
449 if (ratio < 100)
451 if (texture)
453 ypos = 0;
454 while (height>0)
456 ah = texture->h;
457 if (ah > height) ah = height;
458 xpos = 0;
459 w = width;
460 while (w>0)
462 aw = texture->w;
463 if (aw > w) aw = w;
464 MixImage(pic, texture, textureti, 255 - (2.55 * ratio), aw, ah, xpos, ypos);
465 w -= aw;
466 xpos += aw;
468 height -= ah;
469 ypos += ah;
475 static void RenderBackgroundTiled(struct NewImage *pic, struct NewImage *texture, struct TileInfo *textureti,
476 UWORD ratio, VOID (*TileImageToImageFunc)(struct NewImage *src, struct TileInfo * srcti, struct NewImage *dest))
478 struct NewImage *ni;
480 if (texture)
482 ni = NewImageContainer(pic->w, pic->h);
483 if (ni)
485 if (textureti)
487 TileImageToImageFunc(texture, textureti, ni);
488 BlurSourceAndMixTexture(pic, ni, textureti, ratio);
490 else BlurSourceAndMixTexture(pic, texture, textureti, ratio);
492 DisposeImageContainer(ni);
494 else BlurSourceAndMixTexture(pic, texture, textureti, ratio);
496 else BlurSourceAndMixTexture(pic, NULL, NULL, ratio);
499 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)
502 ULONG dy, dx;
503 LONG dh, height, dw, width;
505 if (src == NULL) return;
506 if (rp == NULL) return;
508 dh = _sh;
509 dy = _dy;
510 height = _dh;
512 if (!src->ok) return;
514 while (height > 0)
516 if ((height-dh)<0) dh = height;
517 height -= dh;
518 dw = _sw;
519 width = _dw;
520 dx = _dx;
521 while (width > 0)
523 if ((width-dw)<0) dw = width;
524 width -= dw;
526 if (src->mask)
528 BltMaskBitMapRastPort(src->bitmap, _sx, _sy, rp, dx, dy, dw, dh, 0xe0, (PLANEPTR) src->mask);
530 else BltBitMapRastPort(src->bitmap, _sx, _sy, rp, dx, dy, dw, dh, 0xc0);
532 dx += dw;
534 dy += dh;
538 /******************************************************************************/
539 /******************************************************************************/
540 /******************************************************************************/
541 /******************************************************************************/
542 /******************************************************************************/
544 void DrawPartImageToRP(struct RastPort *rp, struct NewImage *ni, UWORD x, UWORD y, UWORD sx, UWORD sy, UWORD sw, UWORD sh)
546 if (ni->ok)
548 if (ni->bitmap == NULL)
550 WritePixelArray(ni->data, sx, sy, ni->w*4, rp, x, y, sw, sh, RECTFMT_ARGB);
552 else
554 BltBitMapRastPort(ni->bitmap, sx, sy, rp, x, y, sw, sh, 0xc0);
559 void DrawPartToImage(struct NewImage *src, struct NewImage *dest, UWORD sx, UWORD sy, UWORD sw, UWORD sh, UWORD dx, UWORD dy)
561 UWORD x, y;
563 for (y = 0; y < sh; y++)
565 for (x = 0; x < sw; x++)
567 dest->data[dx + x + (dy + y) * dest->w] = src->data[sx + x + (sy + y) * src->w];
572 void RenderMenuBackground(struct NewImage *pic, struct NewImage *texture, struct TileInfo *textureti, UWORD ratio)
574 if (texture)
576 if (textureti) RenderBackgroundTiled(pic, texture, textureti, ratio, TileImageToImage);
577 else BlurSourceAndMixTexture(pic, texture, textureti, ratio);
579 else BlurSourceAndMixTexture(pic, NULL, NULL, ratio);
582 void RenderMenuBarBackground(struct NewImage *pic, struct NewImage *texture, struct TileInfo *textureti, UWORD ratio)
584 if (texture && textureti)
587 /* Fill the image with the center tile */
588 DrawTileToImage(texture, pic,
589 textureti->TileLeft, textureti->TileTop,
590 texture->w - textureti->TileLeft - textureti->TileRight, texture->h - textureti->TileBottom - textureti->TileTop,
591 0, 0, pic->w, pic->h);
593 RenderBackgroundTiled(pic, texture, textureti, ratio, TileImageToImageMenuBar);
597 void WriteAlphaPixelArray(struct NewImage *src, struct NewLUT8Image *dst, LONG sx, LONG sy, LONG dx, LONG dy, LONG w, LONG h)
599 ULONG *s = src->data;
600 ULONG argb;
601 UBYTE *d = dst->data;
602 int x, y;
604 for (y = 0; y < h; y++)
606 for (x = 0; x < w; x++)
608 argb = s[sx + x + (sy + y) * src->w];
609 d[dx + x + (dy + y) * dst->w] = GET_A(argb);
614 void SetImageTint(struct NewImage *dst, UWORD ratio, ULONG argb)
617 ULONG *d;
618 ULONG rgb;
619 UWORD r, g, b, w, h;
620 UBYTE rs, gs, bs, rd, gd, bd;
621 int x, y;
623 if (dst == NULL) return;
625 d = dst->data;
627 w = dst->w;
628 h = dst->h;
630 rs = (argb >> 16) & 0xff;
631 gs = (argb >> 8) & 0xff;
632 bs = argb & 0xff;
634 for (y = 0; y < h; y++)
636 for (x = 0; x < w; x++)
638 rgb = d[x + y * w];
639 rd = GET_R(rgb);
640 gd = GET_G(rgb);
641 bd = GET_B(rgb);
642 r = ((rs * ratio) >> 8) + ((rd * (255 - ratio)) >> 8);
643 g = ((gs * ratio) >> 8) + ((gd * (255 - ratio)) >> 8);
644 b = ((bs * ratio) >> 8) + ((bd * (255 - ratio)) >> 8);
646 r = r & 0xff;
647 g = g & 0xff;
648 b = b & 0xff;
650 d[x + y * w] = SET_ARGB(255, r, g, b);
656 * offx - offset between start of ni and place where image should be sample from
657 * offy - offset between start of ni and place where image should be sample from
658 * x, y, w, h - coords in rastport rp
660 void HorizVertRepeatNewImage(struct NewImage *ni, ULONG color, UWORD offx, UWORD offy, struct RastPort *rp, UWORD x, UWORD y, WORD w, WORD h)
662 ULONG ow, oh, sy, sx, dy, dx;
663 LONG dh, height, dw, width;
665 if ((w <= 0) || (h <= 0)) return;
667 if (!ni->ok)
669 FillPixelArray(rp, x, y, w, h, color);
670 return;
673 ow = ni->w;
674 oh = ni->h;
676 sy = offy % oh;
677 dh = oh - sy;
678 height = h;
679 dy = y;
680 while (height > 0)
682 if ((height-dh)<0) dh = height;
683 height -= dh;
685 sx = offx % ow;
686 dw = ow - sx;
687 width = w;
688 dx = x;
689 while (width > 0)
691 if ((width-dw)<0) dw = width;
692 width -= dw;
694 BltNewImageSubImageRastPort(ni, 0, 0, sx, sy, rp, dx, dy, dw, dh);
696 dx += dw;
697 sx = 0;
698 dw = ow;
700 dy += dh;
701 sy = 0;
702 dh = oh;
706 /* NOTE: fill parameter is ignored, previously it was forcing a no-alpha blit, but
707 this is already handled in BltNewImageSubImageRastPort */
708 /* dh - destination height to which subimage will be scaled to */
709 LONG WriteTiledImageTitle(BOOL fill, struct Window *win,
710 struct RastPort *rp, struct NewImage *ni, LONG sx, LONG sy, LONG sw,
711 LONG sh, LONG xp, LONG yp, LONG dw, LONG dh)
713 int w = dw;
714 int x = xp;
715 int ddw;
717 if (!ni->ok) return x;
719 if ((sw == 0) || (dw == 0)) return xp;
721 if (win)
723 if (x > win->Width) return xp;
724 if ((x + w) > win->Width) w = win->Width - x;
727 while (w > 0)
729 ddw = sw;
730 if (w < ddw) ddw = w;
732 BltScaleNewImageSubImageRastPort(ni, 0, 0, sx, sy, rp, x, yp, ddw, -1, -1, dh);
734 w -= ddw;
735 x += ddw;
737 return x;
741 * dh - destination height to scale to, -1 to use subimage height
743 LONG WriteVerticalScaledTiledImageHorizontal(struct RastPort *rp, struct NewImage *ni, ULONG subimage,
744 LONG sx, LONG sw, LONG xp, LONG yp, LONG sh, LONG dw, LONG dh)
746 LONG w = dw;
747 LONG x = xp;
748 LONG ddw;
750 if (!ni->ok) return xp;
752 if ((sw == 0) || (dw == 0)) return xp;
754 while (w > 0)
756 ddw = sw;
757 if (w < ddw) ddw = w;
759 BltScaleNewImageSubImageRastPort(ni, 0, subimage, sx, 0, rp, x, yp, ddw, sh, -1, dh);
761 w -= ddw;
762 x += ddw;
765 return x;
768 LONG WriteTiledImageHorizontal(struct RastPort *rp, struct NewImage *ni, ULONG subimage, LONG sx, LONG sw, LONG xp, LONG yp, LONG dw)
770 return WriteVerticalScaledTiledImageHorizontal(rp, ni, subimage, sx, sw, xp, yp, -1, dw, -1);
773 LONG WriteTiledImageVertical(struct RastPort *rp, struct NewImage *ni, ULONG subimage, LONG sy, LONG sh, LONG xp, LONG yp, LONG dh)
775 int h = dh;
776 int y = yp;
777 int ddh;
779 if (!ni->ok) return y;
781 if ((sh == 0) || (dh == 0)) return yp;
783 while (h > 0)
785 ddh = sh;
786 if (h < ddh) ddh = h;
788 BltNewImageSubImageRastPort(ni, subimage, 0, 0, sy, rp, xp, y, -1, ddh);
790 h -= ddh;
791 y += ddh;
793 return y;
796 struct myrgb
798 int red,green,blue;
801 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)
803 /* The basic idea of this algorithm is to calc the intersection between the
804 * diagonal of the rectangle (xs,ys) with dimension (xw,yw) a with the line starting
805 * at (x,y) (every pixel inside the rectangle) and angle angle with direction vector (vx,vy).
807 * Having the intersection point we then know the color of the pixel.
809 * TODO: Turn the algorithm into a incremental one
810 * Remove the use of floating point variables */
811 double rad = angle*M_PI/180;
812 double cosarc = cos(rad);
813 double sinarc = sin(rad);
815 struct myrgb startRGB,endRGB;
817 int diffR, diffG, diffB;
819 int r,t; /* some helper variables to short the code */
820 int l,y,c,x;
821 int y1; /* The intersection point */
822 int incr_y1; /* increment of y1 */
823 int xs,ys,xw,yw;
824 int xadd,ystart,yadd;
825 // double vx = -cosarc;
826 // double vy = sinarc;
827 int vx = (int)(-cosarc*0xff);
828 int vy = (int)(sinarc*0xff);
830 int width = xb - xt + 1;
831 int height = yb - yt + 1;
833 if (buf == NULL) return;
835 startRGB.red = (start_rgb >> 16) & 0xff;
836 startRGB.green = (start_rgb >> 8) & 0xff;
837 startRGB.blue = start_rgb & 0xff;
839 endRGB.red = (end_rgb >> 16) & 0xff;
840 endRGB.green = (end_rgb >> 8) & 0xff;
841 endRGB.blue = end_rgb & 0xff;
843 diffR = endRGB.red - startRGB.red;
844 diffG = endRGB.green - startRGB.green;
845 diffB = endRGB.blue - startRGB.blue;
847 /* Normalize the angle */
848 if (angle < 0) angle = 360 - ((-angle)%360);
849 if (angle >= 0) angle = angle % 360;
851 if (angle <= 90 || (angle > 180 && angle <= 270))
853 /* The to be intersected diagonal goes from the top left edge to the bottom right edge */
854 xs = 0;
855 ys = 0;
856 xw = width;
857 yw = height;
858 } else
860 /* The to be intersected diagonal goes from the bottom left edge to the top right edge */
861 xs = 0;
862 ys = height;
863 xw = width;
864 yw = -height;
867 if (angle > 90 && angle <= 270)
869 /* for these angle we have y1 = height - y1. Instead of
871 * y1 = height - (-vy*(yw* xs -xw* ys) + yw*(vy* x -vx* y)) /(-yw*vx + xw*vy);
873 * we can write
875 * y1 = (-vy*(yw*(-xs)-xw*(-ys+height)) + yw*(vy*(-x)-vx*(-y+height)))/(-yw*vx + xw*vy);
877 * so height - y1 can be expressed with the normal formular adapting some parameters.
879 * Note that if one would exchanging startRGB/endRGB the values would only work
880 * for linear color gradients */
881 xadd = -1;
882 yadd = -1;
883 ystart = height;
885 xs = -xs;
886 ys = -ys + height;
888 else
890 xadd = 1;
891 yadd = 1;
892 ystart = 0;
895 r = -vy*(yw*xs-xw*ys);
896 t = -yw*vx + xw*vy;
898 /* The formular as shown above is
900 * y1 = ((-vy*(yw*xs-xw*ys) + yw*(vy*x-vx*y)) /(-yw*vx + xw*vy));
902 * We see that only yw*(vy*x-vx*y) changes during the loop.
904 * We write
906 * Current Pixel: y1(x,y) = (r + yw*(vy*x-vx*y))/t = r/t + yw*(vy*x-vx*y)/t
907 * Next Pixel: y1(x+xadd,y) = (r + vw*(vy*(x+xadd)-vx*y))/t
909 * t*(y1(x+xadd,y) - y1(x,y)) = yw*(vy*(x+xadd)-vx*y) - yw*(vy*x-vx*y) = yw*vy*xadd; */
911 incr_y1 = yw*vy*xadd;
912 UBYTE *bufptr = buf;
913 for (l = 0, y = ystart + ((yp - yt)* yadd); l < h; l++, y+=yadd)
915 /* Calculate initial y1 accu, can be brought out of the loop as well (x=0). It's probably a
916 * a good idea to add here also a value of (t-1)/2 to ensure the correct rounding
917 * This (and for r) is also a place were actually a overflow can happen |yw|=16 |y|=16. So for
918 * vx nothing is left, currently 9 bits are used for vx or vy */
919 int y1_mul_t_accu = r - yw*vx*y;
923 for (c = 0, x = ((xp - xt) * xadd); c < w; c++, x+=xadd)
925 int red,green,blue;
927 /* Calculate the intersection of two lines, this is not the fastet way to do but
928 * it is intuitive. Note: very slow! Will be optimzed later (remove FFP usage
929 * and making it incremental)...update: it's now incremental and no FFP is used
930 * but it probably can be optimized more by removing some more of the divisions and
931 * further specialize the stuff here (use of three accus). */
932 /* y1 = (int)((-vy*(yw*xs-xw*ys) + yw*(vy*x-vx*y)) /(-yw*vx + xw*vy));*/
933 y1 = y1_mul_t_accu / t;
935 red = startRGB.red + (int)(diffR*y1/height);
936 green = startRGB.green + (int)(diffG*y1/height);
937 blue = startRGB.blue + (int)(diffB*y1/height);
938 /* By using full 32 bits this can be made faster as well */
939 *bufptr++ = red;
940 *bufptr++ = green;
941 *bufptr++ = blue;
943 y1_mul_t_accu += incr_y1;
949 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)
951 UBYTE * buf = NULL;
953 if ((w <= 0) || (h <= 0)) return;
955 /* By bringing building the gradient array in the same format as the RastPort BitMap a call
956 to WritePixelArray() can be made also faster */
957 buf = AllocVec(1 * yb * 3, 0);
959 FillMemoryBufferRGBGradient(buf, pen, xt, yt, xb, yb, xp, yp, 1, yb, start_rgb, end_rgb, angle);
961 HorizRepeatBuffer(buf, dy, pen, tc, rp, xp, yp, w, h);
963 FreeVec(buf);
966 void HorizRepeatBuffer(UBYTE * buf, LONG offy, LONG pen, BOOL tc, struct RastPort *rp, LONG x, LONG y, LONG w, LONG h)
968 UBYTE * bufblit = NULL;
969 ULONG xi, yi;
970 ULONG idxd;
971 ULONG idxs;
973 if ((w <= 0) || (h <= 0)) return;
974 if (!tc)
976 if (pen != -1) SetAPen(rp, pen); else SetAPen(rp, 2);
977 RectFill(rp, x, y, x + w - 1, y + h - 1);
978 return;
981 /* By bringing building the gradient array in the same format as the RastPort BitMap a call
982 to WritePixelArray() can be made also faster */
983 bufblit = AllocVec(w * h * 3, MEMF_ANY);
984 if (!bufblit)
985 return;
987 /* Copy one column buffer into blit buffer */
988 for (yi = 0; yi < h; yi++)
990 idxs = (offy + yi) * 3; /* source index */
991 idxd = yi * 3 * w; /* dest index */
992 for (xi = 0; xi < w; xi++)
994 /* Copy RGB pixel */
995 bufblit[idxd++] = buf[idxs + 0];
996 bufblit[idxd++] = buf[idxs + 1];
997 bufblit[idxd++] = buf[idxs + 2];
1001 WritePixelArray(bufblit, 0, 0, w * 3, rp, x, y, w, h, RECTFMT_RGB);
1003 FreeVec(bufblit);
1006 void TileMapToBitmap(struct NewImage *src, struct TileInfo *srcti, struct BitMap *map, UWORD dw, UWORD dh)
1008 UWORD y, h;
1010 if (map == NULL) return;
1011 if (src == NULL) return;
1012 if (srcti == NULL) return;
1013 y = 0;
1015 h = src->h;
1017 if ((srcti->TileTop + srcti->TileBottom) > dh) return;
1018 if ((srcti->TileLeft + srcti->TileRight) > dw) return;
1020 struct RastPort *dest = CreateRastPort();
1022 if (dest != NULL)
1024 dest->BitMap = map;
1026 DrawMapTileToRP(src, dest, 0, y, srcti->TileLeft, srcti->TileTop, 0 , 0, srcti->TileLeft, srcti->TileTop);
1027 DrawMapTileToRP(src, dest, 0, y + h - srcti->TileBottom, srcti->TileLeft, srcti->TileBottom, 0 , dh - srcti->TileBottom, srcti->TileLeft, srcti->TileBottom);
1028 DrawMapTileToRP(src, dest, src->w - srcti->TileRight, y, srcti->TileRight, srcti->TileTop, dw - srcti->TileRight, 0, srcti->TileRight, srcti->TileTop);
1029 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);
1031 DrawMapTileToRP(src, dest, srcti->TileLeft, y, src->w - srcti->TileLeft - srcti->TileRight, srcti->TileTop, srcti->TileLeft, 0, dw - srcti->TileLeft - srcti->TileRight, srcti->TileTop);
1032 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);
1033 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);
1034 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);
1035 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);
1036 FreeRastPort(dest);
1040 struct NewImage *GetImageFromRP(struct RastPort *rp, UWORD x, UWORD y, UWORD w, UWORD h)
1042 struct NewImage *ni;
1044 ni = NewImageContainer(w, h);
1045 if (ni)
1047 ReadPixelArray(ni->data, 0, 0, w*4, rp, x, y, w, h, RECTFMT_ARGB);
1049 return ni;
1052 void PutImageToRP(struct RastPort *rp, struct NewImage *ni, UWORD x, UWORD y) {
1054 if (ni)
1056 if (ni->data) WritePixelArray(ni->data, 0, 0, ni->w*4, rp, x, y, ni->w, ni->h, RECTFMT_ARGB);
1057 DisposeImageContainer(ni);
1061 ULONG CalcShade(ULONG base, UWORD fact)
1063 int c0, c1, c2, c3;
1065 c0 = GET_A(base);
1066 c1 = GET_R(base);
1067 c2 = GET_G(base);
1068 c3 = GET_B(base);
1069 c0 *= fact;
1070 c1 *= fact;
1071 c2 *= fact;
1072 c3 *= fact;
1073 c0 = c0 >> 8;
1074 c1 = c1 >> 8;
1075 c2 = c2 >> 8;
1076 c3 = c3 >> 8;
1078 if (c0 > 255) c0 = 255;
1079 if (c1 > 255) c1 = 255;
1080 if (c2 > 255) c2 = 255;
1081 if (c3 > 255) c3 = 255;
1083 return (ULONG)SET_ARGB(c0, c1, c2, c3);
1086 AROS_UFH3(void, RectShadeFunc,
1087 AROS_UFHA(struct Hook * , h, A0),
1088 AROS_UFHA(struct RastPort * , rp, A2),
1089 AROS_UFHA(struct layerhookmsg *, msg, A1))
1091 AROS_USERFUNC_INIT
1093 struct ShadeData *data = h->h_Data;
1094 #if defined(DECOR_USELINEBUFF)
1095 ULONG *outline = NULL;
1096 UWORD width = 1 + msg->MaxX - msg->MinX;
1097 #endif
1098 ULONG color;
1100 HIDDT_Color col;
1101 APTR bm_handle;
1102 int px, py, x, y;
1104 #if defined(DECOR_USELINEBUFF)
1105 if (width > 1) {
1106 outline = AllocMem((width << 2), MEMF_ANY);
1107 bm_handle = NULL;
1108 } else
1109 #endif
1110 bm_handle = LockBitMapTags(rp->BitMap,
1111 TAG_END);
1113 for (py = msg->MinY; py <= msg->MaxY; py++)
1115 y = (py - rp->Layer->bounds.MinY) % data->ni->h;
1117 for (px = msg->MinX; px <= msg->MaxX; px++)
1119 x = (px - rp->Layer->bounds.MinX) % data->ni->w;
1121 color = CalcShade(data->ni->data[(y * data->ni->w) + x], data->fact);
1123 #if defined(DECOR_USELINEBUFF)
1124 if (outline)
1126 outline[px - msg->MinX] = color;
1128 else
1129 #endif
1130 if (bm_handle)
1132 col.alpha = (HIDDT_ColComp) GET_A(color) << 8;
1133 col.red = (HIDDT_ColComp) GET_R(color) << 8;
1134 col.green = (HIDDT_ColComp) GET_G(color) << 8;
1135 col.blue = (HIDDT_ColComp) GET_B(color) << 8;
1137 HIDD_BM_PutPixel(HIDD_BM_OBJ(rp->BitMap), px, py, HIDD_BM_MapColor(HIDD_BM_OBJ(rp->BitMap), &col));
1139 else
1141 WriteRGBPixel(rp, px + msg->OffsetX - msg->MinX, py + msg->OffsetY - msg->MinY, color);
1144 #if defined(DECOR_USELINEBUFF)
1145 if (outline)
1146 WritePixelArray(outline, 0, 0, width, rp, msg->OffsetX, py + msg->OffsetY - msg->MinY, width, 1, RECTFMT_ARGB);
1147 #endif
1150 #if defined(DECOR_USELINEBUFF)
1151 if (outline)
1152 FreeMem(outline, (width << 2));
1153 else
1154 #endif
1155 if (bm_handle)
1157 struct RectList bm_rectlist;
1158 struct TagItem bm_ultags[3] =
1160 {UBMI_REALLYUNLOCK, TRUE },
1161 {UBMI_UPDATERECTS, (IPTR)&bm_rectlist },
1162 {TAG_DONE, 0 }
1165 bm_rectlist.rl_num = 1;
1166 bm_rectlist.rl_next = (struct RectList *)0;
1167 bm_rectlist.rl_rect.MinX = msg->MinX;
1168 bm_rectlist.rl_rect.MinY = msg->MinY;
1169 bm_rectlist.rl_rect.MaxX = msg->MaxX;
1170 bm_rectlist.rl_rect.MaxY = msg->MaxY;
1172 UnLockBitMapTagList(bm_handle, bm_ultags);
1175 AROS_USERFUNC_EXIT
1178 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)
1180 ULONG color;
1182 if ((x1 < x0) || (y1 < y0)) return;
1183 if (!tc)
1185 SetAPen(rp, pen);
1186 Move(rp, x0, y0);
1187 Draw(rp, x1, y1);
1188 return;
1190 if (usegradients)
1192 color = CalcShade(basecolor, fact);
1193 SetRPAttrs(rp, RPTAG_PenMode, FALSE, RPTAG_FgColor, color, TAG_DONE);
1194 Move(rp, x0, y0);
1195 Draw(rp, x1, y1);
1197 else if (ni->ok)
1199 struct ShadeData shadeParams;
1200 struct Hook shadeHook;
1201 struct Rectangle shadeRect;
1203 shadeRect.MinX = x0;
1204 shadeRect.MaxX = x1;
1205 shadeRect.MinY = y0;
1206 shadeRect.MaxY = y1;
1208 shadeParams.ni = ni;
1209 shadeParams.fact = fact;
1211 shadeHook.h_Entry = (HOOKFUNC)AROS_ASMSYMNAME(RectShadeFunc);
1212 shadeHook.h_Data = &shadeParams;
1214 DoHookClipRects(&shadeHook, rp, &shadeRect);
1216 else
1218 Move(rp, x0, y0);
1219 Draw(rp, x1, y1);
1223 void DrawScaledStatefulGadgetImageToRP(struct RastPort *rp, struct NewImage *ni, ULONG state, UWORD xp, UWORD yp,
1224 WORD scaledwidth, WORD scaledheight)
1227 UWORD subimagecol = 0;
1228 UWORD subimagerow = 0;
1230 if (ni->ok)
1232 switch(state)
1234 case IDS_NORMAL:
1235 break;
1236 case IDS_SELECTED:
1237 subimagecol = 1;
1238 break;
1239 case IDS_INACTIVENORMAL:
1240 subimagecol = 2;
1241 break;
1244 BltScaleNewImageSubImageRastPortSimple(ni, subimagecol, subimagerow, rp, xp, yp, scaledwidth, scaledheight);
1248 void DrawStatefulGadgetImageToRP(struct RastPort *rp, struct NewImage *ni, ULONG state, UWORD xp, UWORD yp)
1250 DrawScaledStatefulGadgetImageToRP(rp, ni, state, xp, yp, -1, -1);