/trunk/src/common/Gdc2/GdcCommon.cpp
C++ | 633 lines | 544 code | 75 blank | 14 comment | 60 complexity | a779ab5a00320ed723551279f00eeec7 MD5 | raw file
Possible License(s): LGPL-2.1, Unlicense
- #include "Lgi.h"
- /////////////////////////////////////////////////////////////////////////////
- // Mem ops
- void Add64(ulong *DestH, ulong *DestL, ulong SrcH, ulong SrcL)
- {
- *DestH += SrcH + (*DestL & SrcL & 0x80000000) ? 1 : 0;
- *DestL += SrcL;
- }
- void MemSet(void *d, int c, uint s)
- {
- if (d AND s > 0) memset(d, c, s);
- }
- void MemCpy(void *d, void *s, uint l)
- {
- if (d AND s AND l > 0) memcpy(d, s, l);
- }
- void MemAnd(void *d, void *s, uint l)
- {
- uchar *D = (uchar*) d;
- uchar *S = (uchar*) s;
- if (D AND S)
- {
- for (; l > 0; l--)
- {
- *D++ &= *S++;
- }
- }
- }
- void MemXor(void *d, void *s, uint l)
- {
- uchar *D = (uchar*) d;
- uchar *S = (uchar*) s;
- if (D AND S)
- {
- for (; l > 0; l--)
- {
- *D++ ^= *S++;
- }
- }
- }
- void MemOr(void *d, void *s, uint l)
- {
- uchar *D = (uchar*) d;
- uchar *S = (uchar*) s;
- if (D AND S)
- {
- for (; l > 0; l--)
- {
- *D++ |= *S++;
- }
- }
- }
- //////////////////////////////////////////////////////////////////////
- // Drawing functions
- void LgiDrawBox(GSurface *pDC, GRect &r, bool Sunken, bool Fill)
- {
- if (Fill)
- {
- pDC->Colour(LC_MED, 24);
- pDC->Rectangle(r.x1+1, r.y1+1, r.x2-1, r.y2-1);
- }
- pDC->Colour((Sunken) ? LC_LIGHT : LC_LOW, 24);
- pDC->Line(r.x2, r.y2, r.x2, r.y1);
- pDC->Line(r.x2, r.y2, r.x1, r.y2);
- pDC->Colour((Sunken) ? LC_LOW : LC_LIGHT, 24);
- pDC->Line(r.x1, r.y1, r.x1, r.y2);
- pDC->Line(r.x1, r.y1, r.x2, r.y1);
- }
- void LgiWideBorder(GSurface *pDC, GRect &r, int Type)
- {
- if (!pDC) return;
- COLOUR Old = pDC->Colour();
- COLOUR VLow = LC_SHADOW;
- COLOUR Low = LC_LOW;
- COLOUR High = LC_HIGH;
- COLOUR VHigh = LC_LIGHT;
- switch (Type)
- {
- case SUNKEN:
- {
- pDC->Colour(Low, 24);
- pDC->Line(r.x1, r.y1, r.x2-1, r.y1);
- pDC->Line(r.x1, r.y1, r.x1, r.y2-1);
- pDC->Colour(VLow, 24);
- pDC->Line(r.x1+1, r.y1+1, r.x2-2, r.y1+1);
- pDC->Line(r.x1+1, r.y1+1, r.x1+1, r.y2-2);
- pDC->Colour(High, 24);
- pDC->Line(r.x2-1, r.y2-1, r.x2-1, r.y1+1);
- pDC->Line(r.x2-1, r.y2-1, r.x1+1, r.y2-1);
- pDC->Colour(VHigh, 24);
- pDC->Line(r.x2, r.y2, r.x2, r.y1);
- pDC->Line(r.x2, r.y2, r.x1, r.y2);
- break;
- }
- case RAISED:
- {
- pDC->Colour(VHigh, 24);
- pDC->Line(r.x1, r.y1, r.x2-1, r.y1);
- pDC->Line(r.x1, r.y1, r.x1, r.y2-1);
- pDC->Colour(High, 24);
- pDC->Line(r.x1+1, r.y1+1, r.x2-1, r.y1+1);
- pDC->Line(r.x1+1, r.y1+1, r.x1+1, r.y2-1);
- pDC->Colour(Low, 24);
- pDC->Line(r.x2-1, r.y2-1, r.x2-1, r.y1+1);
- pDC->Line(r.x2-1, r.y2-1, r.x1+1, r.y2-1);
- pDC->Colour(VLow, 24);
- pDC->Line(r.x2, r.y2, r.x2, r.y1);
- pDC->Line(r.x2, r.y2, r.x1, r.y2);
- break;
- }
- case CHISEL:
- {
- pDC->Colour(Low, 24);
- pDC->Line(r.x1, r.y1, r.x2-1, r.y1);
- pDC->Line(r.x1, r.y1, r.x1, r.y2-1);
- pDC->Colour(VHigh, 24);
- pDC->Line(r.x1+1, r.y1+1, r.x2-2, r.y1+1);
- pDC->Line(r.x1+1, r.y1+1, r.x1+1, r.y2-2);
- pDC->Colour(Low, 24);
- pDC->Line(r.x2-1, r.y2-1, r.x2-1, r.y1+1);
- pDC->Line(r.x2-1, r.y2-1, r.x1+1, r.y2-1);
- pDC->Colour(VHigh, 24);
- pDC->Line(r.x2, r.y2, r.x2, r.y1);
- pDC->Line(r.x2, r.y2, r.x1, r.y2);
- break;
- }
- }
- r.Size(2, 2);
- pDC->Colour(Old);
- }
- void LgiThinBorder(GSurface *pDC, GRect &r, int Type)
- {
- if (!pDC) return;
- COLOUR Old = pDC->Colour();
- switch (Type)
- {
- case SUNKEN:
- {
- pDC->Colour(LC_LIGHT, 24);
- pDC->Line(r.x2, r.y2, r.x2, r.y1);
- pDC->Line(r.x2, r.y2, r.x1, r.y2);
- pDC->Colour(LC_LOW, 24);
- pDC->Line(r.x1, r.y1, r.x1, r.y2);
- pDC->Line(r.x1, r.y1, r.x2, r.y1);
- r.Size(1, 1);
- break;
- }
- case RAISED:
- {
- pDC->Colour(LC_LOW, 24);
- pDC->Line(r.x2, r.y2, r.x2, r.y1);
- pDC->Line(r.x2, r.y2, r.x1, r.y2);
- pDC->Colour(LC_LIGHT, 24);
- pDC->Line(r.x1, r.y1, r.x1, r.y2);
- pDC->Line(r.x1, r.y1, r.x2, r.y1);
- r.Size(1, 1);
- break;
- }
- }
- pDC->Colour(Old);
- }
- void LgiFlatBorder(GSurface *pDC, GRect &r, int Width)
- {
- pDC->Colour(LC_MED, 24);
- if (Width < 1 OR r.X() < (2 * Width) OR r.Y() < (2 * Width))
- {
- pDC->Rectangle(&r);
- r.ZOff(-1, -1);
- }
- else
- {
- pDC->Rectangle(r.x1, r.y1, r.x2, r.y1+Width-1);
- pDC->Rectangle(r.x1, r.y2-Width+1, r.x2, r.y2);
- pDC->Rectangle(r.x1, r.y1+Width, r.x1+Width-1, r.y2-Width);
- pDC->Rectangle(r.x2-Width+1, r.y1+Width, r.x2, r.y2-Width);
- r.Size(Width, Width);
- }
- }
- void LgiFillGradient(GSurface *pDC, GRect &r, bool Vert, GArray<GColourStop> &Stops)
- {
- int CurStop = 0;
- GColourStop *This = Stops.Length() > CurStop ? &Stops[CurStop] : 0;
- CurStop++;
- GColourStop *Next = Stops.Length() > CurStop ? &Stops[CurStop] : 0;
- int Limit = Vert ? r.Y() : r.X();
- for (int n=0; n<Limit; n++)
- {
- COLOUR c = Rgb32(0, 0, 0);
- float p = (float)n/Limit;
- if (This)
- {
- DoStop:
- if (!Next OR p <= This->Pos)
- {
- // Just this
- c = This->Colour;
- }
- else if (p > This->Pos AND p < Next->Pos)
- {
- // Interpolate between this and next
- float d = Next->Pos - This->Pos;
- float t = (Next->Pos - p) / d;
- float n = (p - This->Pos) / d;
- uint8 r = (R32(This->Colour) * t) + (R32(Next->Colour) * n);
- uint8 g = (G32(This->Colour) * t) + (G32(Next->Colour) * n);
- uint8 b = (B32(This->Colour) * t) + (B32(Next->Colour) * n);
- uint8 a = (A32(This->Colour) * t) + (A32(Next->Colour) * n);
- c = Rgba32(r, g, b, a);
- }
- else if (p >= Next->Pos)
- {
- // Get next colour stops
- This = Stops.Length() > CurStop ? &Stops[CurStop] : 0;
- CurStop++;
- Next = Stops.Length() > CurStop ? &Stops[CurStop] : 0;
- goto DoStop;
- }
- pDC->Colour(c, 32);
- if (Vert)
- pDC->Line(r.x1, r.y1 + n, r.x2, r.y1 + n);
- else
- pDC->Line(r.x1 + n, r.y1, r.x1 + n, r.y2);
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////////////
- // Other Gdc Stuff
- COLOUR RgbToHls(COLOUR Rgb24)
- {
- int nMax;
- int nMin;
- int R = R24(Rgb24);
- int G = G24(Rgb24);
- int B = B24(Rgb24);
- int H, L, S;
- bool Undefined = FALSE;
- nMax = max(R, max(G, B));
- nMin = min(R, min(G, B));
- L = (nMax + nMin) / 2;
- if (nMax == nMin)
- {
- H = HUE_UNDEFINED;
- S = 0;
- Undefined = TRUE;
- }
- else
- {
- double fHue;
- int nDelta;
- if (L < 128)
- {
- S = (uchar) ((255.0 * ((double)(nMax - nMin)) / (double)(nMax + nMin)) + 0.5);
- }
- else
- {
- S = (uchar) ((255.0 * ((double)(nMax - nMin)) / (double)(511 - nMax - nMin)) + 0.5);
- }
-
- nDelta = nMax - nMin;
-
- if (R == nMax)
- {
- fHue = ((double) (G - B)) / (double) nDelta;
- }
- else if (G == nMax)
- {
- fHue = 2.0 + ((double) (B - R)) / (double) nDelta;
- }
- else
- {
- fHue = 4.0 + ((double) (R - G)) / (double) nDelta;
- }
-
- fHue *= 60;
-
- if (fHue < 0.0)
- {
- fHue += 360.0;
- }
-
- H = (short) (fHue + 0.5);
- }
- return Hls32(H, L, S);
- }
- int HlsValue(double fN1, double fN2, double fHue)
- {
- int nValue;
-
- if (fHue > 360.0)
- {
- fHue -= 360.0;
- }
- else if (fHue < 0.0)
- {
- fHue += 360.0;
- }
- if (fHue < 60.0)
- {
- nValue = (int) ((fN1 + (fN2 - fN1) * fHue / 60.0) * 255.0 + 0.5);
- }
- else if (fHue < 180.0)
- {
- nValue = (int) ((fN2 * 255.0) + 0.5);
- }
- else if (fHue < 240.0)
- {
- nValue = (int) ((fN1 + (fN2 - fN1) * (240.0 - fHue) / 60.0) * 255.0 + 0.5);
- }
- else
- {
- nValue = (int) ((fN1 * 255.0) + 0.5);
- }
- return (nValue);
- }
- COLOUR HlsToRgb(COLOUR Hls)
- {
- int H = H32(Hls);
- int L = L32(Hls);
- int S = S32(Hls);
- int R, G, B;
- if (S == 0)
- {
- R = 0;
- G = 0;
- B = 0;
- }
- else
- {
- double fM1;
- double fM2;
- double fHue;
- double fLightness;
- double fSaturation;
- while (H >= 360)
- {
- H -= 360;
- }
-
- while (H < 0)
- {
- H += 360;
- }
-
- fHue = (double) H;
- fLightness = ((double) L) / 255.0;
- fSaturation = ((double) S) / 255.0;
-
- if (L < 128)
- {
- fM2 = fLightness * (1 + fSaturation);
- }
- else
- {
- fM2 = fLightness + fSaturation - (fLightness * fSaturation);
- }
-
- fM1 = 2.0 * fLightness - fM2;
- R = HlsValue(fM1, fM2, fHue + 120.0);
- G = HlsValue(fM1, fM2, fHue);
- B = HlsValue(fM1, fM2, fHue - 120.0);
- }
- return Rgb24(R, G, B);
- }
- GSurface *ConvertDC(GSurface *pDC, int Bits)
- {
- GSurface *pNew = new GMemDC;
- if (pNew AND pNew->Create(pDC->X(), pDC->Y(), Bits))
- {
- pNew->Blt(0, 0, pDC);
- DeleteObj(pDC);
- return pNew;
- }
- return pDC;
- }
- GColour GdcMixColour(GColour c1, GColour c2, float HowMuchC1)
- {
- float HowMuchC2 = 1.0 - HowMuchC1;
- int r = (c1.r()*HowMuchC1) + (c2.r()*HowMuchC2);
- int g = (c1.g()*HowMuchC1) + (c2.g()*HowMuchC2);
- int b = (c1.b()*HowMuchC1) + (c2.b()*HowMuchC2);
- int a = (c1.a()*HowMuchC1) + (c2.a()*HowMuchC2);
-
- return GColour(r, g, b, a);
- }
- COLOUR GdcMixColour(COLOUR c1, COLOUR c2, float HowMuchC1)
- {
- double HowMuchC2 = 1.0 - HowMuchC1;
- int r = (R24(c1)*HowMuchC1) + (R24(c2)*HowMuchC2);
- int g = (G24(c1)*HowMuchC1) + (G24(c2)*HowMuchC2);
- int b = (B24(c1)*HowMuchC1) + (B24(c2)*HowMuchC2);
- return Rgb24(r, g, b);
- }
- COLOUR GdcGreyScale(COLOUR c, int Bits)
- {
- COLOUR c24 = CBit(24, c, Bits);
- int r = (R24(c24) * 76) / 255;
- int g = (G24(c24) * 150) / 255;
- int b = (B24(c24) * 29) / 255;
-
- return r + g + b;
- }
- COLOUR CBit(int DstBits, COLOUR c, int SrcBits, GPalette *Pal)
- {
- if (SrcBits == DstBits)
- {
- return c;
- }
- else
- {
- COLOUR c24 = 0;
- switch (SrcBits)
- {
- case 8:
- {
- GdcRGB Grey, *p = 0;
- if (!Pal OR !(p = (*Pal)[c]))
- {
- Grey.R = Grey.G = Grey.B = c & 0xFF;
- p = &Grey;
- }
- switch (DstBits)
- {
- case 16:
- {
- return Rgb16(p->R, p->G, p->B);
- }
- case 24:
- {
- return Rgb24(p->R, p->G, p->B);
- }
- case 32:
- {
- return Rgb32(p->R, p->G, p->B);
- }
- }
- break;
- }
- case 15:
- {
- int R = R15(c);
- int G = G15(c);
- int B = B15(c);
- R = R | (R >> 5);
- G = G | (G >> 5);
- B = B | (B >> 5);
- switch (DstBits)
- {
- case 8:
- {
- if (Pal)
- {
- return Pal->MatchRgb(Rgb24(R, G, B));
- }
- break;
- }
- case 16:
- {
- return Rgb16(R, G, B);
- }
- case 24:
- {
- return Rgb24(R, G, B);
- }
- case 32:
- {
- return Rgb32(R, G, B);
- }
- }
- break;
- }
- case 16:
- {
- /*
- int R = ((c>>8)&0xF8) | ((c>>13)&0x7);
- int G = ((c>>3)&0xFC) | ((c>>9)&0x3);
- int B = ((c<<3)&0xF8) | ((c>>2)&0x7);
- */
- int R = (c >> 8) & 0xF8;
- int G = (c >> 3) & 0xFC;
- int B = (c << 3) & 0xF8;
- switch (DstBits)
- {
- case 8:
- {
- if (Pal)
- {
- return Pal->MatchRgb(Rgb24(R, G, B));
- }
- break;
- }
- case 15:
- {
- return Rgb16To15(c);
- }
- case 24:
- {
- return Rgb24(R, G, B);
- }
- case 32:
- {
- return Rgb32(R, G, B);
- }
- }
- break;
- }
- case 24:
- {
- switch (DstBits)
- {
- case 8:
- {
- if (Pal)
- {
- return Pal->MatchRgb(c);
- }
- break;
- }
- case 15:
- {
- return Rgb24To15(c);
- }
- case 16:
- {
- if (LgiGetOs() == LGI_OS_WINNT)
- {
- return Rgb24To16(c);
- }
- int r = max(R24(c) - 1, 0) >> 3;
- int g = max(G24(c) - 1, 0) >> 2;
- int b = max(B24(c) - 1, 0) >> 3;
- return (r << 11) | (g << 5) | (b);
- }
- case 32:
- {
- return Rgb24To32(c);
- }
- }
- break;
- }
- case 32:
- {
- switch (DstBits)
- {
- case 8:
- {
- if (Pal)
- {
- return Pal->MatchRgb(Rgb32To24(c));
- }
- break;
- }
- case 15:
- {
- return Rgb32To15(c);
- }
- case 16:
- {
- return Rgb32To16(c);
- }
- case 24:
- {
- return Rgb32To24(c);
- }
- }
- break;
- }
- }
- }
- return c;
- }