1 /***********************************************************
2  * AGSBlend                                                *
3  *                                                         *
4  * Author: Steven Poulton                                  *
5  *                                                         *
6  * Date: 09/01/2011                                        *
7  *                                                         *
8  * Description: An AGS Plugin to allow true Alpha Blending *
9  *                                                         *
10  ***********************************************************/
11 
12 #pragma region Defines_and_Includes
13 
14 #define MIN_EDITOR_VERSION 1
15 #define MIN_ENGINE_VERSION 3
16 
17 #ifdef WIN32
18 #define WIN32_LEAN_AND_MEAN
19 #include <windows.h>
20 #endif
21 
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <math.h>
25 
26 #if !defined(BUILTIN_PLUGINS)
27 #define THIS_IS_THE_PLUGIN
28 #endif
29 
30 #include "plugin/agsplugin.h"
31 
32 #if defined(BUILTIN_PLUGINS)
33 namespace agsblend {
34 #endif
35 
36 typedef unsigned char uint8;
37 
38 #define DEFAULT_RGB_R_SHIFT_32  16
39 #define DEFAULT_RGB_G_SHIFT_32  8
40 #define DEFAULT_RGB_B_SHIFT_32  0
41 #define DEFAULT_RGB_A_SHIFT_32  24
42 
43 #if !defined(WINDOWS_VERSION)
44 #define min(x,y) (((x) < (y)) ? (x) : (y))
45 #define max(x,y) (((x) > (y)) ? (x) : (y))
46 #endif
47 
48 #define abs(a)						 ((a)<0 ? -(a) : (a))
49 #define ChannelBlend_Normal(B,L)     ((uint8)(B))
50 #define ChannelBlend_Lighten(B,L)    ((uint8)((L > B) ? L:B))
51 #define ChannelBlend_Darken(B,L)     ((uint8)((L > B) ? B:L))
52 #define ChannelBlend_Multiply(B,L)   ((uint8)((B * L) / 255))
53 #define ChannelBlend_Average(B,L)    ((uint8)((B + L) / 2))
54 #define ChannelBlend_Add(B,L)        ((uint8)(min(255, (B + L))))
55 #define ChannelBlend_Subtract(B,L)   ((uint8)((B + L < 255) ? 0:(B + L - 255)))
56 #define ChannelBlend_Difference(B,L) ((uint8)(abs(B - L)))
57 #define ChannelBlend_Negation(B,L)   ((uint8)(255 - abs(255 - B - L)))
58 #define ChannelBlend_Screen(B,L)     ((uint8)(255 - (((255 - B) * (255 - L)) >> 8)))
59 #define ChannelBlend_Exclusion(B,L)  ((uint8)(B + L - 2 * B * L / 255))
60 #define ChannelBlend_Overlay(B,L)    ((uint8)((L < 128) ? (2 * B * L / 255):(255 - 2 * (255 - B) * (255 - L) / 255)))
61 #define ChannelBlend_SoftLight(B,L)  ((uint8)((L < 128)?(2*((B>>1)+64))*((float)L/255):(255-(2*(255-((B>>1)+64))*(float)(255-L)/255))))
62 #define ChannelBlend_HardLight(B,L)  (ChannelBlend_Overlay(L,B))
63 #define ChannelBlend_ColorDodge(B,L) ((uint8)((L == 255) ? L:min(255, ((B << 8 ) / (255 - L)))))
64 #define ChannelBlend_ColorBurn(B,L)  ((uint8)((L == 0) ? L:max(0, (255 - ((255 - B) << 8 ) / L))))
65 #define ChannelBlend_LinearDodge(B,L)(ChannelBlend_Add(B,L))
66 #define ChannelBlend_LinearBurn(B,L) (ChannelBlend_Subtract(B,L))
67 #define ChannelBlend_LinearLight(B,L)((uint8)(L < 128)?ChannelBlend_LinearBurn(B,(2 * L)):ChannelBlend_LinearDodge(B,(2 * (L - 128))))
68 #define ChannelBlend_VividLight(B,L) ((uint8)(L < 128)?ChannelBlend_ColorBurn(B,(2 * L)):ChannelBlend_ColorDodge(B,(2 * (L - 128))))
69 #define ChannelBlend_PinLight(B,L)   ((uint8)(L < 128)?ChannelBlend_Darken(B,(2 * L)):ChannelBlend_Lighten(B,(2 * (L - 128))))
70 #define ChannelBlend_HardMix(B,L)    ((uint8)((ChannelBlend_VividLight(B,L) < 128) ? 0:255))
71 #define ChannelBlend_Reflect(B,L)    ((uint8)((L == 255) ? L:min(255, (B * B / (255 - L)))))
72 #define ChannelBlend_Glow(B,L)       (ChannelBlend_Reflect(L,B))
73 #define ChannelBlend_Phoenix(B,L)    ((uint8)(min(B,L) - max(B,L) + 255))
74 #define ChannelBlend_Alpha(B,L,O)    ((uint8)(O * B + (1 - O) * L))
75 #define ChannelBlend_AlphaF(B,L,F,O) (ChannelBlend_Alpha(F(B,L),B,O))
76 
77 
78 #pragma endregion
79 
80 #if defined(WINDOWS_VERSION)
81 // The standard Windows DLL entry point
82 
DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)83 BOOL APIENTRY DllMain( HANDLE hModule,
84                        DWORD  ul_reason_for_call,
85                        LPVOID lpReserved) {
86 
87   switch (ul_reason_for_call)	{
88 		case DLL_PROCESS_ATTACH:
89 		case DLL_THREAD_ATTACH:
90 		case DLL_THREAD_DETACH:
91 		case DLL_PROCESS_DETACH:
92 			break;
93   }
94   return TRUE;
95 }
96 #endif
97 
98 //define engine
99 
100 IAGSEngine *engine;
101 
102 
103 #pragma region Color_Functions
104 
105 
getr32(int c)106   int getr32(int c)
107 {
108    return ((c >> DEFAULT_RGB_R_SHIFT_32) & 0xFF);
109 }
110 
111 
getg32(int c)112 int getg32 (int c)
113 {
114    return ((c >> DEFAULT_RGB_G_SHIFT_32) & 0xFF);
115 }
116 
117 
getb32(int c)118 int getb32 (int c)
119 {
120    return ((c >> DEFAULT_RGB_B_SHIFT_32) & 0xFF);
121 }
122 
123 
geta32(int c)124 int geta32 (int c)
125 {
126    return ((c >> DEFAULT_RGB_A_SHIFT_32) & 0xFF);
127 }
128 
129 
makeacol32(int r,int g,int b,int a)130 int makeacol32 (int r, int g, int b, int a)
131 {
132    return ((r << DEFAULT_RGB_R_SHIFT_32) |
133            (g << DEFAULT_RGB_G_SHIFT_32) |
134            (b << DEFAULT_RGB_B_SHIFT_32) |
135            (a << DEFAULT_RGB_A_SHIFT_32));
136 }
137 
138 #pragma endregion
139 
140 #pragma region Pixel32_Definition
141 
142 struct Pixel32{
143 
144       public:
145              Pixel32();
~Pixel32agsblend::Pixel32146              ~Pixel32() {}
147 			 int GetColorAsInt();
148              int Red;
149              int Green;
150              int Blue;
151              int Alpha;
152 
153 };
154 
Pixel32()155 Pixel32::Pixel32() {
156 	Red = 0;
157 	Blue = 0;
158 	Green = 0;
159 	Alpha = 0;
160 }
161 
GetColorAsInt()162 int Pixel32::GetColorAsInt() {
163 
164 	return makeacol32(Red,Green,Blue,Alpha);
165 
166 }
167 
168 #pragma endregion
169 
170 /// <summary>
171 /// Gets the alpha value at coords x,y
172 /// </summary>
GetAlpha(int sprite,int x,int y)173 int GetAlpha(int sprite, int x, int y){
174 
175 
176     BITMAP *engineSprite = engine->GetSpriteGraphic(sprite);
177 
178     unsigned char **charbuffer = engine->GetRawBitmapSurface (engineSprite);
179     unsigned int **longbuffer = (unsigned int**)charbuffer;
180 
181     int alpha = geta32(longbuffer[y][x]);
182 
183     engine->ReleaseBitmapSurface (engineSprite);
184 
185     return alpha;
186 
187 }
188 
189 /// <summary>
190 /// Sets the alpha value at coords x,y
191 /// </summary>
PutAlpha(int sprite,int x,int y,int alpha)192 int PutAlpha(int sprite, int x, int y, int alpha){
193 
194     BITMAP *engineSprite = engine->GetSpriteGraphic(sprite);
195 
196     unsigned char **charbuffer = engine->GetRawBitmapSurface (engineSprite);
197     unsigned int **longbuffer = (unsigned int**)charbuffer;
198 
199 
200     int r = getr32(longbuffer[y][x]);
201     int g = getg32(longbuffer[y][x]);
202     int b = getb32(longbuffer[y][x]);
203     longbuffer[y][x] = makeacol32(r,g,b,alpha);
204 
205     engine->ReleaseBitmapSurface (engineSprite);
206 
207     return alpha;
208 
209 }
210 
211 
212 /// <summary>
213 ///  Translates index from a 2D array to a 1D array
214 /// </summary>
xytolocale(int x,int y,int width)215 int xytolocale(int x, int y, int width){
216 
217  return (y * width + x);
218 
219 
220 }
221 
HighPass(int sprite,int threshold)222 int HighPass(int sprite, int threshold){
223 
224     BITMAP* src = engine->GetSpriteGraphic(sprite);
225     int srcWidth, srcHeight;
226 
227 	engine->GetBitmapDimensions(src, &srcWidth, &srcHeight, NULL);
228 
229     unsigned char **srccharbuffer = engine->GetRawBitmapSurface (src);
230     unsigned int **srclongbuffer = (unsigned int**)srccharbuffer;
231 
232         for (int y = 0; y<srcHeight; y++){
233 
234          for (int x = 0; x<srcWidth; x++){
235 
236             int srcr = getb32(srclongbuffer[y][x]);
237             int srcg = getg32(srclongbuffer[y][x]);
238             int srcb = getr32(srclongbuffer[y][x]);
239             int tempmaxim = max(srcr, srcg);
240 			int maxim = max(tempmaxim, srcb);
241             int tempmin = min( srcr, srcg);
242             int minim = min( srcb, tempmin);
243             int light = (maxim + minim) /2 ;
244             if (light < threshold) srclongbuffer[y][x] = makeacol32(0,0,0,0);
245 
246          }
247 
248      }
249 
250     return 0;
251 
252 }
253 
254 
Blur(int sprite,int radius)255 int Blur (int sprite, int radius) {
256 
257     BITMAP* src = engine->GetSpriteGraphic(sprite);
258 
259     int srcWidth, srcHeight;
260     engine->GetBitmapDimensions(src, &srcWidth, &srcHeight, NULL);
261 
262     unsigned char **srccharbuffer = engine->GetRawBitmapSurface (src);
263     unsigned int **srclongbuffer = (unsigned int**)srccharbuffer;
264     int negrad = -1 * radius;
265 
266     //use a 1Dimensional array since the array is on the free store, not the stack
267     Pixel32 * Pixels = new Pixel32[(srcWidth + (radius * 2)) * (srcHeight + (radius * 2))]; // this defines a copy of the individual channels in class form.
268     Pixel32 * Dest = new Pixel32[(srcWidth + (radius * 2)) * (srcHeight + (radius * 2))]; // this is the destination sprite. both have a border all the way round equal to the radius for the blurring.
269     Pixel32 * Temp = new Pixel32[(srcWidth + (radius * 2)) * (srcHeight + (radius * 2))];
270 
271 
272     int arraywidth = srcWidth + (radius * 2); //define the array width since its used many times in the algorithm
273 
274 
275     for (int y = 0; y<srcHeight; y++){ //copy the sprite to the Pixels class array
276 
277          for (int x = 0; x<srcWidth; x++){
278 
279              int locale = xytolocale(x + radius, y + radius, arraywidth);
280 
281              Pixels[locale].Red = getr32(srclongbuffer[y][x]);
282              Pixels[locale].Green = getg32(srclongbuffer[y][x]);
283              Pixels[locale].Blue = getb32(srclongbuffer[y][x]);
284              Pixels[locale].Alpha = geta32(srclongbuffer[y][x]);
285 
286 
287 
288          }
289 
290      }
291 
292 
293     int  numofpixels = (radius * 2 + 1);
294     for (int y = 0; y < srcHeight; y++) {
295 
296                 int totalr = 0;
297                 int totalg = 0;
298                 int totalb = 0;
299                 int totala = 0;
300 
301             // Process entire window for first pixel
302             for (int kx = negrad; kx <= radius; kx++){
303                 int locale = xytolocale(kx + radius, y + radius, arraywidth);
304                  totala += Pixels[locale].Alpha;
305                  totalr += (Pixels[locale].Red * Pixels[locale].Alpha)/ 255;
306                  totalg += (Pixels[locale].Green * Pixels[locale].Alpha)/ 255;
307                  totalb += (Pixels[locale].Blue * Pixels[locale].Alpha)/ 255;
308                 }
309 
310             int locale = xytolocale(radius, y + radius, arraywidth);
311             Temp[locale].Red = totalr / numofpixels; // take an average and assign it to the destination array
312             Temp[locale].Green = totalg / numofpixels;
313             Temp[locale].Blue = totalb / numofpixels;
314             Temp[locale].Alpha = totala / numofpixels;
315 
316 
317             // Subsequent pixels just update window total
318             for (int x = 1; x < srcWidth; x++) {
319                 // Subtract pixel leaving window
320                 int locale = xytolocale(x - 1, y + radius, arraywidth);
321                 totala -= Pixels[locale].Alpha;
322                 totalr -= (Pixels[locale].Red * Pixels[locale].Alpha)/ 255;
323                 totalg -= (Pixels[locale].Green * Pixels[locale].Alpha)/ 255;
324                 totalb -= (Pixels[locale].Blue * Pixels[locale].Alpha)/ 255;
325 
326 
327                 // Add pixel entering window
328 
329                 locale = xytolocale(x + radius + radius, y + radius, arraywidth);
330                  totala += Pixels[locale].Alpha;
331                  totalr += (Pixels[locale].Red * Pixels[locale].Alpha)/ 255;
332                  totalg += (Pixels[locale].Green * Pixels[locale].Alpha)/ 255;
333                  totalb += (Pixels[locale].Blue * Pixels[locale].Alpha)/ 255;
334 
335 
336                  locale = xytolocale(x + radius, y + radius, arraywidth);
337                  Temp[locale].Red = totalr / numofpixels; // take an average and assign it to the destination array
338                  Temp[locale].Green = totalg / numofpixels;
339                  Temp[locale].Blue = totalb / numofpixels;
340                  Temp[locale].Alpha = totala / numofpixels;
341 
342             }
343         }
344 
345 
346 
347 
348     for (int x = 0; x < srcWidth; x++) {
349 
350                 int totalr = 0;
351                 int totalg = 0;
352                 int totalb = 0;
353                 int totala = 0;
354 
355             // Process entire window for first pixel
356             for (int ky = negrad; ky <= radius; ky++){
357                 int locale = xytolocale(x + radius, ky + radius, arraywidth);
358                  totala += Temp[locale].Alpha;
359                  totalr += (Temp[locale].Red * Temp[locale].Alpha)/ 255;
360                  totalg += (Temp[locale].Green * Temp[locale].Alpha)/ 255;
361                  totalb += (Temp[locale].Blue * Temp[locale].Alpha)/ 255;
362                 }
363 
364             int locale = xytolocale(x + radius,radius, arraywidth);
365             Dest[locale].Red = totalr / numofpixels; // take an average and assign it to the destination array
366             Dest[locale].Green = totalg / numofpixels;
367             Dest[locale].Blue = totalb / numofpixels;
368             Dest[locale].Alpha = totala / numofpixels;
369 
370 
371             // Subsequent pixels just update window total
372             for (int y = 1; y < srcHeight; y++) {
373                 // Subtract pixel leaving window
374                 int locale = xytolocale(x + radius, y - 1, arraywidth);
375                 totala -= Temp[locale].Alpha;
376                 totalr -= (Temp[locale].Red * Temp[locale].Alpha)/ 255;
377                 totalg -= (Temp[locale].Green * Temp[locale].Alpha)/ 255;
378                 totalb -= (Temp[locale].Blue * Temp[locale].Alpha)/ 255;
379 
380 
381                 // Add pixel entering window
382 
383                 locale = xytolocale(x + radius, y + radius + radius, arraywidth);
384                  totala += Temp[locale].Alpha;
385                  totalr += (Temp[locale].Red * Temp[locale].Alpha)/ 255;
386                  totalg += (Temp[locale].Green * Temp[locale].Alpha)/ 255;
387                  totalb += (Temp[locale].Blue * Temp[locale].Alpha)/ 255;
388 
389 
390                  locale = xytolocale(x + radius, y + radius, arraywidth);
391                  Dest[locale].Red = totalr / numofpixels; // take an average and assign it to the destination array
392                  Dest[locale].Green = totalg / numofpixels;
393                  Dest[locale].Blue = totalb / numofpixels;
394 				 Dest[locale].Alpha = totala / numofpixels;
395 
396             }
397         }
398 
399 
400 
401         for (int y = 0; y<srcHeight; y++){
402 
403              for (int x = 0; x<srcWidth; x++){
404                 int locale = xytolocale(x + radius, y + radius, arraywidth);
405                 srclongbuffer[y][x] = Dest[locale].GetColorAsInt(); //write the destination array to the main buffer
406 
407              }
408 
409          }
410         delete [] Pixels;
411         delete [] Dest;
412         delete [] Temp;
413         engine->ReleaseBitmapSurface(src);
414         delete srclongbuffer;
415         delete srccharbuffer;
416 	return 0;
417 }
418 
Clamp(int val,int min,int max)419 int Clamp(int val, int min, int max){
420 
421  if (val < min) return min;
422  else if (val > max) return max;
423  else return val;
424 
425 }
426 
DrawSprite(int destination,int sprite,int x,int y,int DrawMode,int trans)427 int DrawSprite(int destination, int sprite, int x, int y, int DrawMode, int trans){
428 
429     trans = 100 - trans;
430     int srcWidth, srcHeight, destWidth, destHeight;
431 
432     BITMAP* src = engine->GetSpriteGraphic(sprite);
433     BITMAP* dest = engine->GetSpriteGraphic(destination);
434 
435     engine->GetBitmapDimensions(src, &srcWidth, &srcHeight, NULL);
436     engine->GetBitmapDimensions(dest, &destWidth, &destHeight, NULL);
437 
438     if (x > destWidth || y > destHeight || x + srcWidth < 0 || y + srcHeight < 0) return 1; // offscreen
439 
440     unsigned char **srccharbuffer = engine->GetRawBitmapSurface (src);
441     unsigned int **srclongbuffer = (unsigned int**)srccharbuffer;
442 
443     unsigned char **destcharbuffer = engine->GetRawBitmapSurface (dest);
444     unsigned int **destlongbuffer = (unsigned int**)destcharbuffer;
445 
446 
447 
448     if (srcWidth + x > destWidth) srcWidth = destWidth - x - 1;
449     if (srcHeight + y > destHeight) srcHeight = destHeight - y - 1;
450 
451     int destx, desty;
452     int srcr, srcg, srcb, srca, destr, destg, destb, desta, finalr, finalg, finalb, finala;
453     unsigned int col;
454     int starty = 0;
455     int startx = 0;
456 
457     if (x < 0) startx = -1 * x;
458     if (y < 0) starty = -1 * y;
459 
460     int ycount = 0;
461     int xcount = 0;
462     for(ycount = starty; ycount<srcHeight; ycount ++){
463 
464         for(xcount = startx; xcount<srcWidth; xcount ++){
465 
466             destx = xcount + x;
467             desty = ycount + y;
468 
469             srca =  (geta32(srclongbuffer[ycount][xcount]));
470 
471             if (srca != 0) {
472                 srca = srca * trans / 100;
473                 srcr =  getr32(srclongbuffer[ycount][xcount]);
474                 srcg =  getg32(srclongbuffer[ycount][xcount]);
475                 srcb =  getb32(srclongbuffer[ycount][xcount]);
476 
477                 destr =  getr32(destlongbuffer[desty][destx]);
478                 destg =  getg32(destlongbuffer[desty][destx]);
479                 destb =  getb32(destlongbuffer[desty][destx]);
480                 desta =  geta32(destlongbuffer[desty][destx]);
481 
482 
483 
484 
485                 switch (DrawMode) {
486 
487                 case 0:
488 
489                      finalr = srcr;
490                      finalg = srcg;
491                      finalb = srcb;
492                      break;
493 
494                 case 1:
495 
496                      finalr = ChannelBlend_Lighten(srcr,destr);
497                      finalg = ChannelBlend_Lighten(srcg,destg);
498                      finalb = ChannelBlend_Lighten(srcb,destb);
499                      break;
500 
501                 case 2:
502 
503 
504                      finalr = ChannelBlend_Darken(srcr,destr);
505                      finalg = ChannelBlend_Darken(srcg,destg);
506                      finalb = ChannelBlend_Darken(srcb,destb);
507                      break;
508 
509                 case 3:
510 
511 
512                      finalr = ChannelBlend_Multiply(srcr,destr);
513                      finalg = ChannelBlend_Multiply(srcg,destg);
514                      finalb = ChannelBlend_Multiply(srcb,destb);
515                      break;
516 
517                 case 4:
518 
519 
520                      finalr = ChannelBlend_Add(srcr,destr);
521                      finalg = ChannelBlend_Add(srcg,destg);
522                      finalb = ChannelBlend_Add(srcb,destb);
523                      break;
524 
525                 case 5:
526 
527 
528                      finalr = ChannelBlend_Subtract(srcr,destr);
529                      finalg = ChannelBlend_Subtract(srcg,destg);
530                      finalb = ChannelBlend_Subtract(srcb,destb);
531                      break;
532 
533                 case 6:
534 
535 
536                      finalr = ChannelBlend_Difference(srcr,destr);
537                      finalg = ChannelBlend_Difference(srcg,destg);
538                      finalb = ChannelBlend_Difference(srcb,destb);
539                      break;
540 
541                 case 7:
542 
543 
544                      finalr = ChannelBlend_Negation(srcr,destr);
545                      finalg = ChannelBlend_Negation(srcg,destg);
546                      finalb = ChannelBlend_Negation(srcb,destb);
547                      break;
548 
549                 case 8:
550 
551 
552                      finalr = ChannelBlend_Screen(srcr,destr);
553                      finalg = ChannelBlend_Screen(srcg,destg);
554                      finalb = ChannelBlend_Screen(srcb,destb);
555                      break;
556 
557 
558                 case 9:
559 
560 
561                      finalr = ChannelBlend_Exclusion(srcr,destr);
562                      finalg = ChannelBlend_Exclusion(srcg,destg);
563                      finalb = ChannelBlend_Exclusion(srcb,destb);
564                      break;
565 
566 
567                 case 10:
568 
569 
570                      finalr = ChannelBlend_Overlay(srcr,destr);
571                      finalg = ChannelBlend_Overlay(srcg,destg);
572                      finalb = ChannelBlend_Overlay(srcb,destb);
573                      break;
574 
575 
576                 case 11:
577 
578 
579                      finalr = ChannelBlend_SoftLight(srcr,destr);
580                      finalg = ChannelBlend_SoftLight(srcg,destg);
581                      finalb = ChannelBlend_SoftLight(srcb,destb);
582                      break;
583 
584                 case 12:
585 
586 
587                      finalr = ChannelBlend_HardLight(srcr,destr);
588                      finalg = ChannelBlend_HardLight(srcg,destg);
589                      finalb = ChannelBlend_HardLight(srcb,destb);
590                      break;
591 
592                 case 13:
593 
594 
595                      finalr = ChannelBlend_ColorDodge(srcr,destr);
596                      finalg = ChannelBlend_ColorDodge(srcg,destg);
597                      finalb = ChannelBlend_ColorDodge(srcb,destb);
598                      break;
599 
600                 case 14:
601 
602 
603                      finalr = ChannelBlend_ColorBurn(srcr,destr);
604                      finalg = ChannelBlend_ColorBurn(srcg,destg);
605                      finalb = ChannelBlend_ColorBurn(srcb,destb);
606                      break;
607 
608                 case 15:
609 
610 
611                      finalr = ChannelBlend_LinearDodge(srcr,destr);
612                      finalg = ChannelBlend_LinearDodge(srcg,destg);
613                      finalb = ChannelBlend_LinearDodge(srcb,destb);
614                      break;
615 
616                 case 16:
617 
618 
619                      finalr = ChannelBlend_LinearBurn(srcr,destr);
620                      finalg = ChannelBlend_LinearBurn(srcg,destg);
621                      finalb = ChannelBlend_LinearBurn(srcb,destb);
622                      break;
623 
624 
625 
626                 case 17:
627 
628 
629                      finalr = ChannelBlend_LinearLight(srcr,destr);
630                      finalg = ChannelBlend_LinearLight(srcg,destg);
631                      finalb = ChannelBlend_LinearLight(srcb,destb);
632                      break;
633 
634 
635 
636                 case 18:
637 
638 
639                      finalr = ChannelBlend_VividLight(srcr,destr);
640                      finalg = ChannelBlend_VividLight(srcg,destg);
641                      finalb = ChannelBlend_VividLight(srcb,destb);
642                      break;
643 
644                 case 19:
645 
646 
647                      finalr = ChannelBlend_PinLight(srcr,destr);
648                      finalg = ChannelBlend_PinLight(srcg,destg);
649                      finalb = ChannelBlend_PinLight(srcb,destb);
650                      break;
651 
652                 case 20:
653 
654 
655                      finalr = ChannelBlend_HardMix(srcr,destr);
656                      finalg = ChannelBlend_HardMix(srcg,destg);
657                      finalb = ChannelBlend_HardMix(srcb,destb);
658                      break;
659 
660                 case 21:
661 
662 
663                      finalr = ChannelBlend_Reflect(srcr,destr);
664                      finalg = ChannelBlend_Reflect(srcg,destg);
665                      finalb = ChannelBlend_Reflect(srcb,destb);
666                      break;
667 
668                 case 22:
669 
670 
671                      finalr = ChannelBlend_Glow(srcr,destr);
672                      finalg = ChannelBlend_Glow(srcg,destg);
673                      finalb = ChannelBlend_Glow(srcb,destb);
674                      break;
675 
676                 case 23:
677 
678 
679                      finalr = ChannelBlend_Phoenix(srcr,destr);
680                      finalg = ChannelBlend_Phoenix(srcg,destg);
681                      finalb = ChannelBlend_Phoenix(srcb,destb);
682                      break;
683 
684                 }
685 
686                 finala = 255-(255-srca)*(255-desta)/255;
687                 finalr = srca*finalr/finala + desta*destr*(255-srca)/finala/255;
688                 finalg = srca*finalg/finala + desta*destg*(255-srca)/finala/255;
689                 finalb = srca*finalb/finala + desta*destb*(255-srca)/finala/255;
690                 col = makeacol32(finalr, finalg, finalb, finala);
691                 destlongbuffer[desty][destx] = col;
692 
693             }
694 
695 
696           }
697 
698     }
699 
700     engine->ReleaseBitmapSurface(src);
701     engine->ReleaseBitmapSurface(dest);
702     engine->NotifySpriteUpdated(destination);
703     return 0;
704 
705 }
706 
707 
DrawAdd(int destination,int sprite,int x,int y,float scale)708 int DrawAdd(int destination, int sprite, int x, int y, float scale){
709 
710 
711     int srcWidth, srcHeight, destWidth, destHeight;
712 
713     BITMAP* src = engine->GetSpriteGraphic(sprite);
714     BITMAP* dest = engine->GetSpriteGraphic(destination);
715 
716     engine->GetBitmapDimensions(src, &srcWidth, &srcHeight, NULL);
717     engine->GetBitmapDimensions(dest, &destWidth, &destHeight, NULL);
718 
719     if (x > destWidth || y > destHeight) return 1; // offscreen
720 
721     unsigned char **srccharbuffer = engine->GetRawBitmapSurface (src);
722     unsigned int **srclongbuffer = (unsigned int**)srccharbuffer;
723 
724     unsigned char **destcharbuffer = engine->GetRawBitmapSurface (dest);
725     unsigned int **destlongbuffer = (unsigned int**)destcharbuffer;
726 
727     if (srcWidth + x > destWidth) srcWidth = destWidth - x - 1;
728     if (srcHeight + y > destHeight) srcHeight = destHeight - y - 1;
729 
730     int destx, desty;
731     int srcr, srcg, srcb, srca, destr, destg, destb, desta, finalr, finalg, finalb, finala;
732     unsigned int col;
733     int ycount = 0;
734     int xcount = 0;
735 
736     int starty = 0;
737     int startx = 0;
738 
739     if (x < 0) startx = -1 * x;
740     if (y < 0) starty = -1 * y;
741 
742 
743 
744     for(ycount = starty; ycount<srcHeight; ycount ++){
745 
746         for(xcount = startx; xcount<srcWidth; xcount ++){
747 
748             destx = xcount + x;
749             desty = ycount + y;
750 
751             srca =  (geta32(srclongbuffer[ycount][xcount]));
752 
753             if (srca != 0) {
754 
755 
756                 srcr =  getr32(srclongbuffer[ycount][xcount]) * srca / 255 * scale;
757                 srcg =  getg32(srclongbuffer[ycount][xcount]) * srca / 255 * scale;
758                 srcb =  getb32(srclongbuffer[ycount][xcount]) * srca / 255 * scale;
759                 desta =  geta32(destlongbuffer[desty][destx]);
760 
761                 if (desta == 0){
762                    destr = 0;
763                    destg = 0;
764                    destb = 0;
765 
766                 }
767                 else {
768                 destr =  getr32(destlongbuffer[desty][destx]);
769                 destg =  getg32(destlongbuffer[desty][destx]);
770                 destb =  getb32(destlongbuffer[desty][destx]);
771                 }
772 
773                 finala = 255-(255-srca)*(255-desta)/255;
774                 finalr = Clamp(srcr + destr, 0, 255);
775                 finalg = Clamp(srcg + destg, 0, 255);
776                 finalb = Clamp(srcb + destb, 0, 255);
777                 col = makeacol32(finalr, finalg, finalb, finala);
778                 destlongbuffer[desty][destx] = col;
779 
780             }
781 
782           }
783 
784     }
785 
786     engine->ReleaseBitmapSurface(src);
787     engine->ReleaseBitmapSurface(dest);
788     engine->NotifySpriteUpdated(destination);
789     return 0;
790 
791 
792 
793 }
794 
795 
796 
DrawAlpha(int destination,int sprite,int x,int y,int trans)797 int DrawAlpha(int destination, int sprite, int x, int y, int trans)
798 {
799 
800     trans = 100 - trans;
801 
802     int srcWidth, srcHeight, destWidth, destHeight;
803 
804     BITMAP* src = engine->GetSpriteGraphic(sprite);
805     BITMAP* dest = engine->GetSpriteGraphic(destination);
806 
807     engine->GetBitmapDimensions(src, &srcWidth, &srcHeight, NULL);
808     engine->GetBitmapDimensions(dest, &destWidth, &destHeight, NULL);
809 
810     if (x > destWidth || y > destHeight) return 1; // offscreen
811 
812     unsigned char **srccharbuffer = engine->GetRawBitmapSurface (src);
813     unsigned int **srclongbuffer = (unsigned int**)srccharbuffer;
814 
815     unsigned char **destcharbuffer = engine->GetRawBitmapSurface (dest);
816     unsigned int **destlongbuffer = (unsigned int**)destcharbuffer;
817 
818     if (srcWidth + x > destWidth) srcWidth = destWidth - x - 1;
819     if (srcHeight + y > destHeight) srcHeight = destHeight - y - 1;
820 
821     int destx, desty;
822     int srcr, srcg, srcb, srca, destr, destg, destb, desta, finalr, finalg, finalb, finala;
823 
824     int ycount = 0;
825     int xcount = 0;
826 
827 	int starty = 0;
828     int startx = 0;
829 
830     if (x < 0) startx = -1 * x;
831     if (y < 0) starty = -1 * y;
832 
833 
834     for(ycount = starty; ycount<srcHeight; ycount ++){
835 
836         for(xcount = startx; xcount<srcWidth; xcount ++){
837 
838             destx = xcount + x;
839             desty = ycount + y;
840 
841             srca =  (geta32(srclongbuffer[ycount][xcount])) * trans / 100;
842 
843             if (srca != 0) {
844 
845                 srcr =  getr32(srclongbuffer[ycount][xcount]);
846                 srcg =  getg32(srclongbuffer[ycount][xcount]);
847                 srcb =  getb32(srclongbuffer[ycount][xcount]);
848 
849                 destr =  getr32(destlongbuffer[desty][destx]);
850                 destg =  getg32(destlongbuffer[desty][destx]);
851                 destb =  getb32(destlongbuffer[desty][destx]);
852                 desta =  geta32(destlongbuffer[desty][destx]);
853 
854                 finala = 255-(255-srca)*(255-desta)/255;
855                 finalr = srca*srcr/finala + desta*destr*(255-srca)/finala/255;
856                 finalg = srca*srcg/finala + desta*destg*(255-srca)/finala/255;
857                 finalb = srca*srcb/finala + desta*destb*(255-srca)/finala/255;
858 
859                 destlongbuffer[desty][destx] = makeacol32(finalr, finalg, finalb, finala);
860 
861             }
862 
863           }
864 
865     }
866 
867     engine->ReleaseBitmapSurface(src);
868     engine->ReleaseBitmapSurface(dest);
869     engine->NotifySpriteUpdated(destination);
870 
871     return 0;
872 }
873 
874 
875 #if defined(WINDOWS_VERSION)
876 
877 //==============================================================================
878 
879 // ***** Design time *****
880 
881 IAGSEditor *editor; // Editor interface
882 
883 const char *ourScriptHeader =
884   "import int DrawAlpha(int destination, int sprite, int x, int y, int transparency);\r\n"
885   "import int GetAlpha(int sprite, int x, int y);\r\n"
886   "import int PutAlpha(int sprite, int x, int y, int alpha);\r\n"
887   "import int Blur(int sprite, int radius);\r\n"
888   "import int HighPass(int sprite, int threshold);\r\n"
889   "import int DrawAdd(int destination, int sprite, int x, int y, float scale);\r\n"
890   "import int DrawSprite(int destination, int sprite, int x, int y, int DrawMode, int trans);";
891 
892 
893 
894 
895 //------------------------------------------------------------------------------
896 
AGS_GetPluginName()897 LPCSTR AGS_GetPluginName()
898 {
899 	return ("AGSBlend");
900 }
901 
902 //------------------------------------------------------------------------------
903 
AGS_EditorStartup(IAGSEditor * lpEditor)904 int AGS_EditorStartup(IAGSEditor *lpEditor)
905 {
906 	// User has checked the plugin to use it in their game
907 
908 	// If it's an earlier version than what we need, abort.
909 	if (lpEditor->version < MIN_EDITOR_VERSION)
910 		return (-1);
911 
912 	editor = lpEditor;
913 	editor->RegisterScriptHeader(ourScriptHeader);
914 
915 	// Return 0 to indicate success
916 	return (0);
917 }
918 
919 //------------------------------------------------------------------------------
920 
AGS_EditorShutdown()921 void AGS_EditorShutdown()
922 {
923 	// User has un-checked the plugin from their game
924 	editor->UnregisterScriptHeader(ourScriptHeader);
925 }
926 
927 //------------------------------------------------------------------------------
928 
AGS_EditorProperties(HWND parent)929 void AGS_EditorProperties(HWND parent)                        //*** optional ***
930 {
931 	// User has chosen to view the Properties of the plugin
932 	// We could load up an options dialog or something here instead
933 /*	MessageBox(parent,
934 	           L"AGSBlend v1.0 By Calin Leafshade",
935 	           L"About",
936 			   MB_OK | MB_ICONINFORMATION);
937          */
938 }
939 
940 //------------------------------------------------------------------------------
941 
AGS_EditorSaveGame(char * buffer,int bufsize)942 int AGS_EditorSaveGame(char *buffer, int bufsize)             //*** optional ***
943 {
944 	// Called by the editor when the current game is saved to disk.
945 	// Plugin configuration can be stored in [buffer] (max [bufsize] bytes)
946 	// Return the amount of bytes written in the buffer
947 	return (0);
948 }
949 
950 //------------------------------------------------------------------------------
951 
AGS_EditorLoadGame(char * buffer,int bufsize)952 void AGS_EditorLoadGame(char *buffer, int bufsize)            //*** optional ***
953 {
954 	// Called by the editor when a game is loaded from disk
955 	// Previous written data can be read from [buffer] (size [bufsize]).
956 	// Make a copy of the data, the buffer is freed after this function call.
957 }
958 
959 //==============================================================================
960 
961 #endif
962 
963 // ***** Run time *****
964 
965  // Engine interface
966 
967 //------------------------------------------------------------------------------
968 
969 #define REGISTER(x) engine->RegisterScriptFunction(#x, (void *) (x));
970 #define STRINGIFY(s) STRINGIFY_X(s)
971 #define STRINGIFY_X(s) #s
972 
AGS_EngineStartup(IAGSEngine * lpEngine)973 void AGS_EngineStartup(IAGSEngine *lpEngine)
974 {
975 	engine = lpEngine;
976 
977 	// Make sure it's got the version with the features we need
978 	if (engine->version < MIN_ENGINE_VERSION)
979 		engine->AbortGame("Plugin needs engine version " STRINGIFY(MIN_ENGINE_VERSION) " or newer.");
980 
981 	//register functions
982 
983 	REGISTER(GetAlpha)
984 	REGISTER(PutAlpha)
985     REGISTER(DrawAlpha)
986     REGISTER(Blur)
987     REGISTER(HighPass)
988     REGISTER(DrawAdd)
989     REGISTER(DrawSprite)
990 
991 
992 }
993 
994 //------------------------------------------------------------------------------
995 
AGS_EngineShutdown()996 void AGS_EngineShutdown()
997 {
998 	// Called by the game engine just before it exits.
999 	// This gives you a chance to free any memory and do any cleanup
1000 	// that you need to do before the engine shuts down.
1001 }
1002 
1003 //------------------------------------------------------------------------------
1004 
AGS_EngineOnEvent(int event,int data)1005 int AGS_EngineOnEvent(int event, int data)                    //*** optional ***
1006 {
1007 	switch (event)
1008 	{
1009 /*
1010 		case AGSE_KEYPRESS:
1011 		case AGSE_MOUSECLICK:
1012 		case AGSE_POSTSCREENDRAW:
1013 		case AGSE_PRESCREENDRAW:
1014 		case AGSE_SAVEGAME:
1015 		case AGSE_RESTOREGAME:
1016 		case AGSE_PREGUIDRAW:
1017 		case AGSE_LEAVEROOM:
1018 		case AGSE_ENTERROOM:
1019 		case AGSE_TRANSITIONIN:
1020 		case AGSE_TRANSITIONOUT:
1021 		case AGSE_FINALSCREENDRAW:
1022 		case AGSE_TRANSLATETEXT:
1023 		case AGSE_SCRIPTDEBUG:
1024 		case AGSE_SPRITELOAD:
1025 		case AGSE_PRERENDER:
1026 		case AGSE_PRESAVEGAME:
1027 		case AGSE_POSTRESTOREGAME:
1028 */
1029 		default:
1030 			break;
1031 	}
1032 
1033 	// Return 1 to stop event from processing further (when needed)
1034 	return (0);
1035 }
1036 
1037 //------------------------------------------------------------------------------
1038 
AGS_EngineDebugHook(const char * scriptName,int lineNum,int reserved)1039 int AGS_EngineDebugHook(const char *scriptName,
1040                         int lineNum, int reserved)            //*** optional ***
1041 {
1042 	// Can be used to debug scripts, see documentation
1043 	return 0;
1044 }
1045 
1046 //------------------------------------------------------------------------------
1047 
AGS_EngineInitGfx(const char * driverID,void * data)1048 void AGS_EngineInitGfx(const char *driverID, void *data)      //*** optional ***
1049 {
1050 	// This allows you to make changes to how the graphics driver starts up.
1051 	// See documentation
1052 }
1053 
1054 //..............................................................................
1055 
1056 
1057 #if defined(BUILTIN_PLUGINS)
1058 }
1059 #endif
1060