00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <Assert.h>
00016 #include <Stdlib.h>
00017
00018 #include <Math.h>
00019
00020 #include "Procedural.h"
00021 #include "String.h"
00022 #include "Bitmap.h"
00023 #include "Ram.h"
00024 #include "gebmutil.h"
00025
00026 #include "Errorlog.h"
00027
00028 #define SMOOTH_WRAP GE_TRUE
00029
00030 #define PI (3.14159f)
00031 #define PI_2 (PI*2)
00032
00033 #define ELECTRICFX_MAX_FX_TYPES 128
00034 #define ELECTRICFX_MAX_VECS 128
00035
00036 #define TOKEN_SEPERATOR " ,"
00037
00038
00039
00040
00041 typedef struct
00042 {
00043 int32 x, y;
00044 } ElectricFx_Vec2d;
00045
00046 typedef enum
00047 {
00048 Fx_Line = 0,
00049 Fx_LineSpin,
00050 Fx_Sparkle,
00051 Fx_EnergySpin
00052 } ElectricFx_Type;
00053
00054 typedef struct
00055 {
00056 ElectricFx_Type Type;
00057 char Str[256];
00058 int32 NumVecs;
00059 } ElectricFx_TypeData;
00060
00061 typedef struct
00062 {
00063 ElectricFx_TypeData *TypeData;
00064 ElectricFx_Vec2d Vecs[2];
00065
00066 float Rotation;
00067 } ElectricFx_Fx;
00068
00069 ElectricFx_TypeData FxTypeDataTable[] =
00070 {
00071 {Fx_Line, "Fx_Line", 2},
00072 {Fx_LineSpin, "Fx_LineSpin", 1},
00073 {Fx_Sparkle, "Fx_Spark", 1},
00074 {Fx_EnergySpin, "Fx_EnergySpin", 1}
00075 };
00076
00077 typedef struct Procedural
00078 {
00079 geBitmap *Bitmap;
00080 geBitmap_Info BitmapInfo;
00081
00082 int32 Width;
00083 int32 Height;
00084 int32 Size;
00085 int32 WMask;
00086 int32 HMask;
00087
00088 uint8 *ZBuffer;
00089
00090 uint16 CLut[256];
00091
00092 int32 PalIndex;
00093
00094 int32 NumFx;
00095 ElectricFx_Fx Fx[ELECTRICFX_MAX_FX_TYPES];
00096
00097 } Procedural;
00098
00099 static int32 FxTypeDataTableSize = (sizeof(FxTypeDataTable)/sizeof(ElectricFx_TypeData));
00100
00101 void ElectricFx_Destroy(Procedural *Proc);
00102 geBoolean ElectricFx_Animate(Procedural *Fx, float ElapsedTime);
00103 geBoolean ElectricFx_Shade(Procedural *Fx);
00104 void ElectricFx_Update(Procedural *Fx, float Time);
00105
00106 ElectricFx_TypeData *ElectricFx_GetFxTypeDataFromString(const char *Str);
00107 int32 ElectricFx_GetPalIndexFromString(const char *Str);
00108 geBoolean ElectricFx_FxParseData(ElectricFx_Fx *Fx);
00109
00110 geBoolean ElectricFx_InitPalette(Procedural *Proc);
00111 geBoolean ElectricFx_InitBitmap(Procedural *Fx, geBitmap **ppBitmap);
00112
00113
00114
00115
00116 Procedural *ElectricFx_Create(geBitmap **Bitmap, const char *StrParms)
00117 {
00118 Procedural *Proc;
00119
00120 assert(Bitmap);
00121 assert(StrParms);
00122
00123 Proc = GE_RAM_ALLOCATE_STRUCT(Procedural);
00124
00125 if (!Proc)
00126 goto ExitWithError;
00127
00128 memset(Proc, 0, sizeof(*Proc));
00129
00130
00131 {
00132 char *Token;
00133 char Parms[1024];
00134
00135 strcpy(Parms, StrParms);
00136
00137 Token = strtok(Parms, TOKEN_SEPERATOR);
00138
00139 if (!Token)
00140 {
00141
00142 strcpy(Parms, "Fx_PalSlime, Fx_EnergySpin, 63, 63");
00143
00144 Token = strtok(Parms, TOKEN_SEPERATOR);
00145
00146 assert(Token);
00147 }
00148
00149 Proc->PalIndex = ElectricFx_GetPalIndexFromString(Token);
00150
00151 Token = strtok(NULL, TOKEN_SEPERATOR);
00152
00153
00154
00155 while(Token)
00156 {
00157 ElectricFx_Fx *Fx;
00158
00159 if (Proc->NumFx >= ELECTRICFX_MAX_FX_TYPES)
00160 break;
00161
00162 Fx = &Proc->Fx[Proc->NumFx++];
00163
00164 Fx->TypeData = ElectricFx_GetFxTypeDataFromString(Token);
00165
00166 if (!Fx->TypeData)
00167 {
00168 geErrorLog_AddString(-1, "ElectricFx_Create: Invalid FxType:", Token);
00169 goto ExitWithError;
00170 }
00171
00172 if (!ElectricFx_FxParseData(Fx))
00173 {
00174 geErrorLog_AddString(-1, "ElectricFx_Create: ElectricFx_FxParseData failed.", NULL);
00175 goto ExitWithError;
00176 }
00177
00178 Token = strtok(NULL, TOKEN_SEPERATOR);
00179 }
00180 }
00181
00182 if (!ElectricFx_InitBitmap(Proc, Bitmap))
00183 goto ExitWithError;
00184
00185 if (!ElectricFx_Animate(Proc, 0.1f))
00186 {
00187 goto ExitWithError;
00188 }
00189
00190 return Proc;
00191
00192 ExitWithError:
00193 {
00194 if (Proc)
00195 ElectricFx_Destroy(Proc);
00196
00197 return NULL;
00198 }
00199 }
00200
00201
00202
00203
00204 void ElectricFx_Destroy(Procedural *Proc)
00205 {
00206 assert(Proc);
00207
00208 if (Proc->ZBuffer)
00209 {
00210 geRam_Free(Proc->ZBuffer);
00211 Proc->ZBuffer = NULL;
00212 }
00213
00214 if (Proc->Bitmap)
00215 {
00216 geBitmap_Destroy(&Proc->Bitmap);
00217 Proc->Bitmap = NULL;
00218 }
00219
00220 geRam_Free(Proc);
00221 }
00222
00223
00224
00225
00226 geBoolean ElectricFx_Animate(Procedural *Fx, float ElapsedTime)
00227 {
00228 if (!Fx->Bitmap)
00229 return GE_TRUE;
00230
00231 ElectricFx_Update(Fx, ElapsedTime);
00232
00233
00234 if (!ElectricFx_Shade(Fx))
00235 return GE_FALSE;
00236
00237 return GE_TRUE;
00238 }
00239
00240
00241
00242 static Procedural_Table ElectricFx_Table =
00243 {
00244 Procedurals_Version,Procedurals_Tag,
00245 "ElectricFx",
00246 ElectricFx_Create,
00247 ElectricFx_Destroy,
00248 ElectricFx_Animate
00249 };
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262 Procedural_Table *ElectricFx_GetProcedural_Table(void)
00263 {
00264 return &ElectricFx_Table;
00265 }
00266
00268
00269
00270
00272
00273 int sgn (long a)
00274 {
00275 if (a > 0)
00276 return +1;
00277 else if (a < 0)
00278 return -1;
00279 else
00280 return 0;
00281 }
00282
00283
00285
00286
00287
00288
00290
00291 int round (long a)
00292 {
00293 if ( (a - (int)a) < 0.5)
00294 return (int)floor(a);
00295 else
00296 return (int)ceil(a);
00297 }
00298
00299
00302 void ElectricFx_PutZ(Procedural *Fx, int x, int y, int ZVal, float ZAge)
00303 {
00304 Fx->ZBuffer[(y&Fx->HMask)*Fx->Width+(x&Fx->WMask)] = ZVal;
00305 }
00306
00307
00309
00310
00311
00312
00314 void ElectricFx_ZLine(Procedural *Fx, int a, int b, int c, int d, int32 ZVal, float ZAge)
00315 {
00316
00317 long u,s,v,d1x,d1y,d2x,d2y,m,n;
00318 int i;
00319
00320 u = c-a;
00321 v = d-b;
00322 d1x = sgn(u);
00323 d1y = sgn(v);
00324 d2x = sgn(u);
00325 d2y = 0;
00326 m = abs(u);
00327 n = abs(v);
00328
00329 if (m<=n)
00330 {
00331 d2x = 0;
00332 d2y = sgn(v);
00333 m = abs(v);
00334 n = abs(u);
00335 }
00336
00337 s = (int)(m>>1);
00338
00339 for (i=round(m); i>0; i--)
00340 {
00341
00342 ElectricFx_PutZ(Fx, a, b, ZVal, ZAge);
00343
00344 s += n;
00345 if (s >= m)
00346 {
00347 s -= m;
00348 a += d1x;
00349 b += d1y;
00350 }
00351 else
00352 {
00353 a += d2x;
00354 b += d2y;
00355 }
00356 }
00357
00358 }
00359
00360
00363 void ElectricFx_ZLine2(Procedural *Fx, int x1, int y1, int x2, int y2, int32 ZVal, float ZAge)
00364 {
00365
00366 int x, y, xlength, ylength, dx, dy;
00367 float xslope, yslope;
00368
00369 xlength = abs(x1-x2);
00370
00371 if ((x1-x2) < 0) dx = -1;
00372 if ((x1-x2) == 0) dx = 0;
00373 if ((x1-x2) > 0) dx = +1;
00374
00375 ylength = abs(y1-y2);
00376 if ((y1-y2) < 0) dy = -1;
00377 if ((y1-y2) == 0) dy = 0;
00378 if ((y1-y2) > 0) dy = +1;
00379
00380 if (dy == 0)
00381 {
00382 if (dx < 0)
00383 for (x=x1; x<x2+1; x++)
00384 ElectricFx_PutZ(Fx, x, y1, ZVal, ZAge);
00385 if (dx > 0)
00386 for (x=x2; x<x1+1; x++)
00387 ElectricFx_PutZ(Fx, x, y1, ZVal, ZAge);
00388 }
00389
00390 if (dx == 0)
00391 {
00392 if (dy < 0)
00393 for (y=y1; y<y2+1; y++)
00394 ElectricFx_PutZ(Fx, x1, y, ZVal, ZAge);
00395 if (dy > 0)
00396 for (y=y2; y<y1+1; y++)
00397 ElectricFx_PutZ(Fx, x1, y, ZVal, ZAge);
00398 }
00399
00400 if ((xlength != 0) && (ylength != 0))
00401 {
00402 xslope = (float)xlength/(float)ylength;
00403 yslope = (float)ylength/(float)xlength;
00404 }
00405 else
00406 {
00407 xslope = 0.0f;
00408 yslope = 0.0f;
00409 }
00410
00411 if ((xslope != 0) && (yslope != 0) && (yslope/xslope < 1) && (yslope/xslope > -1))
00412 {
00413 if (dx < 0)
00414 {
00415 for (x=x1; x<x2+1; x++)
00416 {
00417 y = round((int)(yslope*x));
00418 ElectricFx_PutZ(Fx, x, y, ZVal, ZAge);
00419 }
00420 }
00421 if (dx > 0)
00422 {
00423 for (x=x2; x<x1+1; x++)
00424 {
00425 y = round((int)(yslope*x));
00426 ElectricFx_PutZ(Fx, x, y, ZVal, ZAge);
00427 }
00428 }
00429 }
00430 else
00431 {
00432 if (dy < 0)
00433 {
00434 for (y=x1; y<x2+1; y++)
00435 {
00436 x = round((int)(xslope*y));
00437 ElectricFx_PutZ(Fx, x, y, ZVal, ZAge);
00438 }
00439 }
00440 if (dy > 0)
00441 {
00442 for (y=x2; y<x1+1; y++)
00443 {
00444 x = round((int)(xslope*y));
00445 ElectricFx_PutZ(Fx, x, y, ZVal, ZAge);
00446 }
00447 }
00448 }
00449
00450 }
00451
00452
00453
00454
00455 void ElectricFx_ElectricZLine_r( Procedural *Fx,
00456 int32 x1, int32 y1,
00457 int32 x2, int32 y2,
00458 int32 ZVal, float ZAge,
00459 int32 Recursion)
00460 {
00461 if (Recursion > 0)
00462 {
00463 int32 MidX, MidY;
00464
00465 MidX = (x1+x2)>>1;
00466 MidY = (y1+y2)>>1;
00467
00468 MidX += 8 - (rand()&15);
00469 MidY += 8 - (rand()&15);
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482 ElectricFx_ElectricZLine_r(Fx, x1, y1, MidX, MidY, ZVal, ZAge, Recursion>>1);
00483 ElectricFx_ElectricZLine_r(Fx, MidX, MidY, x2, y2, ZVal, ZAge, Recursion>>1);
00484 }
00485 else
00486 {
00487 ElectricFx_ZLine(Fx, x1, y1, x2, y2, ZVal, ZAge);
00488 }
00489 }
00490
00491
00492
00493
00494 geBoolean ElectricFx_Shade(Procedural *Fx)
00495 {
00496 uint8 *ZBuffer;
00497 uint8 *Bits;
00498 int32 i;
00499 geBitmap *Lock;
00500
00501 if (!geBitmap_LockForWriteFormat(Fx->Bitmap, &Lock, 0, 0, GE_PIXELFORMAT_8BIT_PAL))
00502 goto Fail;
00503
00504 if (!geBitmap_GetInfo(Lock, &(Fx->BitmapInfo),NULL) )
00505 goto Fail;
00506
00507 if (Fx->BitmapInfo.Format != GE_PIXELFORMAT_8BIT_PAL )
00508 goto Fail;
00509
00510 Bits = geBitmap_GetBits(Lock);
00511 ZBuffer = Fx->ZBuffer;
00512
00513
00514
00515 for(i=0;i < Fx->Size-5; i++, ZBuffer++)
00516 {
00517 int32 Result;
00518 int32 Val;
00519
00520 if(*ZBuffer == 0)
00521 continue;
00522
00523 #if 1
00524 Val = (int32)*ZBuffer;
00525
00526 Result = Val;
00527
00528 Bits[i] = min(Result + Bits[i], 255);
00529
00530 if(Val > ZBuffer[1])
00531 Bits[i+1] = max(Bits[i+1]-3,0);
00532 if(Val > ZBuffer[2])
00533 Bits[i+1] = max(Bits[i+2]-7,0);
00534 if(Val > ZBuffer[3])
00535 Bits[i+3] = max(Bits[i+3]-10,0);
00536 if(Val > ZBuffer[4])
00537 Bits[i+4] = max(Bits[i+4]-15,0);
00538 if(Val > ZBuffer[5])
00539 Bits[i+5] = max(Bits[i+5]-7,0);
00540 #else
00541 Val = *ZBuffer;
00542
00543 Result = Val;
00544
00545 Bits[i] = min(Result + Bits[i], 255);
00546 #endif
00547
00548 }
00549
00550
00551 for(i=0;i<2;i++)
00552 {
00553 geBitmapUtil_SmoothBits(&Fx->BitmapInfo, Bits, Bits, 1, SMOOTH_WRAP);
00554 }
00555
00556 if ( ! geBitmap_UnLock(Lock) )
00557 goto Fail;
00558
00559 return GE_TRUE;
00560
00561 Fail:
00562 {
00563 if (Lock )
00564 geBitmap_UnLock(Lock);
00565
00566 return GE_FALSE;
00567 }
00568
00569 }
00570
00571
00572
00573 void ElectricFx_Update(Procedural *EFx, float Time)
00574 {
00575 uint8 *ZBuffer;
00576 ElectricFx_Fx *Fx;
00577 int32 i;
00578
00579 ZBuffer = EFx->ZBuffer;
00580
00581
00582 memset(ZBuffer,0, EFx->Size*sizeof(uint8));
00583
00584 Fx = EFx->Fx;
00585
00586 for (i=0; i< EFx->NumFx; i++, Fx++)
00587 {
00588 assert(Fx->TypeData);
00589
00590 switch(Fx->TypeData->Type)
00591 {
00592 case Fx_Line:
00593 {
00594 ElectricFx_Vec2d *pVec1, *pVec2;
00595
00596 pVec1 = &Fx->Vecs[0];
00597 pVec2 = &Fx->Vecs[1];
00598
00599 ElectricFx_ElectricZLine_r(EFx, pVec1->x, pVec1->y, pVec2->x, pVec2->y, 54, 1.0f, 16);
00600 break;
00601 }
00602
00603 case Fx_Sparkle:
00604 {
00605 int32 i;
00606
00607 for (i=0; i<3; i++)
00608 {
00609 int32 x, y;
00610 float r;
00611
00612 r = ((float)i/6.0f)*PI_2;
00613
00614 r += 2.0f - ((float)rand()/RAND_MAX)*4.0f;
00615
00616 x = (int32)(cos(r)*60.0f);
00617 y = (int32)(sin(r)*60.0f);
00618
00619 x += Fx->Vecs[0].x;
00620 y += Fx->Vecs[0].y;
00621
00622 ElectricFx_ElectricZLine_r(EFx, Fx->Vecs[0].x, Fx->Vecs[0].y, x, y, 64, 1.0f, 4);
00623 }
00624 break;
00625 }
00626
00627 case Fx_EnergySpin:
00628 {
00629 int32 j;
00630 ElectricFx_Vec2d *pVec;
00631
00632 pVec = Fx->Vecs;
00633
00634 for (j=0; j<Fx->TypeData->NumVecs; j++, pVec++)
00635 {
00636 int32 i, x, y;
00637 float r;
00638
00639 for (i=0; i<3; i++)
00640 {
00641 float Val;
00642
00643 r = Fx->Rotation;
00644
00645 Val = ((float)i/3) * PI_2;
00646
00647 r += Val;
00648
00649 x = (int32)(cos(r)*63.0f);
00650 y = (int32)(sin(r)*63.0f);
00651
00652 x += pVec->x;
00653 y += pVec->y;
00654
00655 ElectricFx_ElectricZLine_r(EFx, pVec->x, pVec->y, x, y, 74, 1.0f, 8);
00656 }
00657 }
00658
00659 Fx->Rotation += 2.0f*Time;
00660
00661 if (Fx->Rotation > PI_2)
00662 Fx->Rotation -= PI_2;
00663
00664 break;
00665 }
00666 default:
00667 {
00668 break;
00669 }
00670 }
00671 }
00672 }
00673
00674 typedef struct
00675 {
00676 float f, a, r, g, b;
00677 } CPoint;
00678
00679 static char PalStr[][256] = {
00680 "Fx_PalSlime",
00681 "Fx_PalFire",
00682 "Fx_PalOrange",
00683 "Fx_PalBlue",
00684 };
00685
00686 #define PalStrTableSize (sizeof(PalStr) / sizeof(char[256]))
00687
00688 static CPoint CPoints[PalStrTableSize][3] =
00689 {
00690 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
00691 30.0f, 70.0f, 0.0f, 30.0f, 0.0f,
00692 180.0f, 255.0f, 255.0f, 255.0f, 25.0f,
00693
00694 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
00695 30.0f, 70.0f, 40.0f, 0.0f, 0.0f,
00696 180.0f, 255.0f, 255.0f, 255.0f, 25.0f,
00697
00698 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
00699 30.0f, 70.0f, 70.0f, 10.0f, 0.0f,
00700 180.0f, 255.0f, 255.0f, 255.0f, 25.0f,
00701
00702 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
00703 30.0f, 60.0f, 5.0f, 5.0f, 30.0f,
00704 180.0f, 255.0f, 100.0f, 100.0f, 165.0f
00705 };
00706
00707 static uint16 LerpColor(float c1, float c2, float Ratio)
00708 {
00709 float Val;
00710
00711 Val = c1+(c2 - c1)*Ratio;
00712
00713 Val *= 8.0f;
00714
00715 if (Val > 255.0f)
00716 Val = 255.0f;
00717
00718 return (uint16)Val;
00719 }
00720
00721
00722
00723
00724 int32 ElectricFx_GetPalIndexFromString(const char *Str)
00725 {
00726 int32 i;
00727
00728 for (i=0; i<PalStrTableSize; i++)
00729 {
00730 if (!stricmp(Str, PalStr[i]))
00731 return i;
00732 }
00733
00734 return 0;
00735 }
00736
00737
00738
00739
00740 ElectricFx_TypeData *ElectricFx_GetFxTypeDataFromString(const char *Str)
00741 {
00742 int32 i;
00743
00744 for (i=0; i<FxTypeDataTableSize; i++)
00745 {
00746 if (!stricmp(Str, FxTypeDataTable[i].Str))
00747 return &FxTypeDataTable[i];
00748 }
00749
00750 return NULL;
00751 }
00752
00753
00754
00755
00756 geBoolean ElectricFx_FxParseData(ElectricFx_Fx *Fx)
00757 {
00758 int32 VecNum;
00759 char *Token;
00760
00761 assert(Fx);
00762
00763 VecNum = 0;
00764
00765 while (1)
00766 {
00767
00768 Token = strtok(NULL, TOKEN_SEPERATOR);
00769
00770 assert(ElectricFx_GetFxTypeDataFromString(Token) == NULL);
00771
00772 if (!Token)
00773 return GE_FALSE;
00774
00775 Fx->Vecs[VecNum].x = atoi(Token);
00776
00777
00778 Token = strtok(NULL, TOKEN_SEPERATOR);
00779
00780 assert(ElectricFx_GetFxTypeDataFromString(Token) == NULL);
00781
00782 if (!Token)
00783 return GE_FALSE;
00784
00785 Fx->Vecs[VecNum].y = atoi(Token);
00786
00787 VecNum++;
00788
00789 if (VecNum >= Fx->TypeData->NumVecs)
00790 break;
00791 }
00792
00793 return GE_TRUE;
00794 }
00795
00796
00797
00798 geBoolean ElectricFx_InitBitmap(Procedural *Fx, geBitmap **ppBitmap)
00799 {
00800 assert( ppBitmap);
00801
00802 if ( ! *ppBitmap )
00803 {
00804 *ppBitmap = geBitmap_Create(128, 128, 1, GE_PIXELFORMAT_8BIT_PAL);
00805
00806 if ( ! *ppBitmap )
00807 return GE_FALSE;
00808 }
00809 else
00810 {
00811 geBitmap_CreateRef(*ppBitmap);
00812 }
00813
00814 if (!geBitmap_SetFormat(*ppBitmap,GE_PIXELFORMAT_8BIT_PAL,GE_TRUE,255,NULL) )
00815 return GE_FALSE;
00816
00817 if (!geBitmap_ClearMips(*ppBitmap) )
00818 return GE_FALSE;
00819
00820 if (!geBitmap_SetPreferredFormat(*ppBitmap,GE_PIXELFORMAT_16BIT_4444_ARGB) )
00821 return GE_FALSE;
00822
00823 if (!geBitmapUtil_SetColor(*ppBitmap,0,0,0,0) )
00824 return GE_FALSE;
00825
00826 if (!geBitmap_GetInfo(*ppBitmap, &Fx->BitmapInfo, NULL))
00827 return GE_FALSE;
00828
00829 Fx->Bitmap = *ppBitmap;
00830
00831 if (!ElectricFx_InitPalette(Fx))
00832 return GE_FALSE;
00833
00834 Fx->Width = Fx->BitmapInfo.Width;
00835 Fx->Height = Fx->BitmapInfo.Height;
00836 Fx->Size = Fx->Width*Fx->Height;
00837
00838 Fx->WMask = Fx->Width-1;
00839 Fx->HMask = Fx->Height-1;
00840
00841 Fx->ZBuffer = GE_RAM_ALLOCATE_ARRAY(uint8, Fx->Size);
00842
00843 if (!Fx->ZBuffer)
00844 return GE_FALSE;
00845
00846
00847 memset(Fx->ZBuffer,0, Fx->Size*sizeof(uint8));
00848
00849 return GE_TRUE;
00850 }
00851
00852
00853
00854 geBoolean ElectricFx_InitPalette(Procedural *Proc)
00855 {
00856 geBitmap_Info Info;
00857 geBitmap_Palette *Pal;
00858 void *PalData = NULL;
00859 gePixelFormat PalFormat;
00860 int PalSize;
00861
00862 Pal = geBitmap_Palette_Create(GE_PIXELFORMAT_32BIT_ARGB,256);
00863 if ( ! Pal )
00864 goto fail;
00865 if ( ! geBitmap_SetPalette(Proc->Bitmap,Pal) )
00866 goto fail;
00867 geBitmap_Palette_Destroy(&Pal);
00868
00869 if (!geBitmap_GetInfo(Proc->Bitmap,&Info,NULL) )
00870 goto fail;
00871
00872 if (Info.Format != GE_PIXELFORMAT_8BIT_PAL )
00873 goto fail;
00874
00875 if (!(Pal = geBitmap_GetPalette(Proc->Bitmap)) )
00876 goto fail;
00877
00878 if (!geBitmap_Palette_Lock(Pal,&PalData, &PalFormat, &PalSize) )
00879 goto fail;
00880 if ( PalSize < 256 )
00881 goto fail;
00882
00883 {
00884 int32 i;
00885 int32 NumControlPoints, Current;
00886 CPoint *pPoint;
00887
00888
00889 NumControlPoints = 3;
00890
00891 Current = 0;
00892
00893 pPoint = &CPoints[Proc->PalIndex][0];
00894
00895 for (i=0; i<256; i++)
00896 {
00897 float Ratio;
00898 int32 Next;
00899 uint32 R,G,B,A;
00900 uint8 *PalPtr;
00901
00902 Next = Current+1;
00903
00904 if (Next > NumControlPoints-1)
00905 Next = NumControlPoints-1;
00906
00907 Ratio = (float)(i-pPoint[Current].f)/pPoint[Next].f;
00908
00909 if (Ratio > 1.0f)
00910 Ratio = 1.0f;
00911 else if (Ratio < 0.0f)
00912 Ratio = 0.0f;
00913
00914 PalPtr = ((uint8 *)PalData) + i * gePixelFormat_BytesPerPel(PalFormat);
00915
00916 A = (uint32)LerpColor(pPoint[Current].a, pPoint[Next].a, Ratio);
00917 R = (uint32)LerpColor(pPoint[Current].r, pPoint[Next].r, Ratio);
00918 G = (uint32)LerpColor(pPoint[Current].g, pPoint[Next].g, Ratio);
00919 B = (uint32)LerpColor(pPoint[Current].b, pPoint[Next].b, Ratio);
00920
00921 gePixelFormat_PutColor(PalFormat,&PalPtr,R,G,B,A);
00922
00923 if ((float)i >= pPoint[Next].f)
00924 {
00925 Current++;
00926
00927 if (Current > NumControlPoints-1)
00928 Current = NumControlPoints-1;
00929 }
00930 }
00931 }
00932
00933 PalData = NULL;
00934
00935 if ( ! geBitmap_Palette_UnLock(Pal) )
00936 return GE_FALSE;
00937
00938 return GE_TRUE;
00939
00940 fail:
00941
00942 if ( PalData )
00943 geBitmap_Palette_UnLock(Pal);
00944
00945 return GE_FALSE;
00946
00947 }