PageRenderTime 52ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/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
  1. #include "Lgi.h"
  2. /////////////////////////////////////////////////////////////////////////////
  3. // Mem ops
  4. void Add64(ulong *DestH, ulong *DestL, ulong SrcH, ulong SrcL)
  5. {
  6. *DestH += SrcH + (*DestL & SrcL & 0x80000000) ? 1 : 0;
  7. *DestL += SrcL;
  8. }
  9. void MemSet(void *d, int c, uint s)
  10. {
  11. if (d AND s > 0) memset(d, c, s);
  12. }
  13. void MemCpy(void *d, void *s, uint l)
  14. {
  15. if (d AND s AND l > 0) memcpy(d, s, l);
  16. }
  17. void MemAnd(void *d, void *s, uint l)
  18. {
  19. uchar *D = (uchar*) d;
  20. uchar *S = (uchar*) s;
  21. if (D AND S)
  22. {
  23. for (; l > 0; l--)
  24. {
  25. *D++ &= *S++;
  26. }
  27. }
  28. }
  29. void MemXor(void *d, void *s, uint l)
  30. {
  31. uchar *D = (uchar*) d;
  32. uchar *S = (uchar*) s;
  33. if (D AND S)
  34. {
  35. for (; l > 0; l--)
  36. {
  37. *D++ ^= *S++;
  38. }
  39. }
  40. }
  41. void MemOr(void *d, void *s, uint l)
  42. {
  43. uchar *D = (uchar*) d;
  44. uchar *S = (uchar*) s;
  45. if (D AND S)
  46. {
  47. for (; l > 0; l--)
  48. {
  49. *D++ |= *S++;
  50. }
  51. }
  52. }
  53. //////////////////////////////////////////////////////////////////////
  54. // Drawing functions
  55. void LgiDrawBox(GSurface *pDC, GRect &r, bool Sunken, bool Fill)
  56. {
  57. if (Fill)
  58. {
  59. pDC->Colour(LC_MED, 24);
  60. pDC->Rectangle(r.x1+1, r.y1+1, r.x2-1, r.y2-1);
  61. }
  62. pDC->Colour((Sunken) ? LC_LIGHT : LC_LOW, 24);
  63. pDC->Line(r.x2, r.y2, r.x2, r.y1);
  64. pDC->Line(r.x2, r.y2, r.x1, r.y2);
  65. pDC->Colour((Sunken) ? LC_LOW : LC_LIGHT, 24);
  66. pDC->Line(r.x1, r.y1, r.x1, r.y2);
  67. pDC->Line(r.x1, r.y1, r.x2, r.y1);
  68. }
  69. void LgiWideBorder(GSurface *pDC, GRect &r, int Type)
  70. {
  71. if (!pDC) return;
  72. COLOUR Old = pDC->Colour();
  73. COLOUR VLow = LC_SHADOW;
  74. COLOUR Low = LC_LOW;
  75. COLOUR High = LC_HIGH;
  76. COLOUR VHigh = LC_LIGHT;
  77. switch (Type)
  78. {
  79. case SUNKEN:
  80. {
  81. pDC->Colour(Low, 24);
  82. pDC->Line(r.x1, r.y1, r.x2-1, r.y1);
  83. pDC->Line(r.x1, r.y1, r.x1, r.y2-1);
  84. pDC->Colour(VLow, 24);
  85. pDC->Line(r.x1+1, r.y1+1, r.x2-2, r.y1+1);
  86. pDC->Line(r.x1+1, r.y1+1, r.x1+1, r.y2-2);
  87. pDC->Colour(High, 24);
  88. pDC->Line(r.x2-1, r.y2-1, r.x2-1, r.y1+1);
  89. pDC->Line(r.x2-1, r.y2-1, r.x1+1, r.y2-1);
  90. pDC->Colour(VHigh, 24);
  91. pDC->Line(r.x2, r.y2, r.x2, r.y1);
  92. pDC->Line(r.x2, r.y2, r.x1, r.y2);
  93. break;
  94. }
  95. case RAISED:
  96. {
  97. pDC->Colour(VHigh, 24);
  98. pDC->Line(r.x1, r.y1, r.x2-1, r.y1);
  99. pDC->Line(r.x1, r.y1, r.x1, r.y2-1);
  100. pDC->Colour(High, 24);
  101. pDC->Line(r.x1+1, r.y1+1, r.x2-1, r.y1+1);
  102. pDC->Line(r.x1+1, r.y1+1, r.x1+1, r.y2-1);
  103. pDC->Colour(Low, 24);
  104. pDC->Line(r.x2-1, r.y2-1, r.x2-1, r.y1+1);
  105. pDC->Line(r.x2-1, r.y2-1, r.x1+1, r.y2-1);
  106. pDC->Colour(VLow, 24);
  107. pDC->Line(r.x2, r.y2, r.x2, r.y1);
  108. pDC->Line(r.x2, r.y2, r.x1, r.y2);
  109. break;
  110. }
  111. case CHISEL:
  112. {
  113. pDC->Colour(Low, 24);
  114. pDC->Line(r.x1, r.y1, r.x2-1, r.y1);
  115. pDC->Line(r.x1, r.y1, r.x1, r.y2-1);
  116. pDC->Colour(VHigh, 24);
  117. pDC->Line(r.x1+1, r.y1+1, r.x2-2, r.y1+1);
  118. pDC->Line(r.x1+1, r.y1+1, r.x1+1, r.y2-2);
  119. pDC->Colour(Low, 24);
  120. pDC->Line(r.x2-1, r.y2-1, r.x2-1, r.y1+1);
  121. pDC->Line(r.x2-1, r.y2-1, r.x1+1, r.y2-1);
  122. pDC->Colour(VHigh, 24);
  123. pDC->Line(r.x2, r.y2, r.x2, r.y1);
  124. pDC->Line(r.x2, r.y2, r.x1, r.y2);
  125. break;
  126. }
  127. }
  128. r.Size(2, 2);
  129. pDC->Colour(Old);
  130. }
  131. void LgiThinBorder(GSurface *pDC, GRect &r, int Type)
  132. {
  133. if (!pDC) return;
  134. COLOUR Old = pDC->Colour();
  135. switch (Type)
  136. {
  137. case SUNKEN:
  138. {
  139. pDC->Colour(LC_LIGHT, 24);
  140. pDC->Line(r.x2, r.y2, r.x2, r.y1);
  141. pDC->Line(r.x2, r.y2, r.x1, r.y2);
  142. pDC->Colour(LC_LOW, 24);
  143. pDC->Line(r.x1, r.y1, r.x1, r.y2);
  144. pDC->Line(r.x1, r.y1, r.x2, r.y1);
  145. r.Size(1, 1);
  146. break;
  147. }
  148. case RAISED:
  149. {
  150. pDC->Colour(LC_LOW, 24);
  151. pDC->Line(r.x2, r.y2, r.x2, r.y1);
  152. pDC->Line(r.x2, r.y2, r.x1, r.y2);
  153. pDC->Colour(LC_LIGHT, 24);
  154. pDC->Line(r.x1, r.y1, r.x1, r.y2);
  155. pDC->Line(r.x1, r.y1, r.x2, r.y1);
  156. r.Size(1, 1);
  157. break;
  158. }
  159. }
  160. pDC->Colour(Old);
  161. }
  162. void LgiFlatBorder(GSurface *pDC, GRect &r, int Width)
  163. {
  164. pDC->Colour(LC_MED, 24);
  165. if (Width < 1 OR r.X() < (2 * Width) OR r.Y() < (2 * Width))
  166. {
  167. pDC->Rectangle(&r);
  168. r.ZOff(-1, -1);
  169. }
  170. else
  171. {
  172. pDC->Rectangle(r.x1, r.y1, r.x2, r.y1+Width-1);
  173. pDC->Rectangle(r.x1, r.y2-Width+1, r.x2, r.y2);
  174. pDC->Rectangle(r.x1, r.y1+Width, r.x1+Width-1, r.y2-Width);
  175. pDC->Rectangle(r.x2-Width+1, r.y1+Width, r.x2, r.y2-Width);
  176. r.Size(Width, Width);
  177. }
  178. }
  179. void LgiFillGradient(GSurface *pDC, GRect &r, bool Vert, GArray<GColourStop> &Stops)
  180. {
  181. int CurStop = 0;
  182. GColourStop *This = Stops.Length() > CurStop ? &Stops[CurStop] : 0;
  183. CurStop++;
  184. GColourStop *Next = Stops.Length() > CurStop ? &Stops[CurStop] : 0;
  185. int Limit = Vert ? r.Y() : r.X();
  186. for (int n=0; n<Limit; n++)
  187. {
  188. COLOUR c = Rgb32(0, 0, 0);
  189. float p = (float)n/Limit;
  190. if (This)
  191. {
  192. DoStop:
  193. if (!Next OR p <= This->Pos)
  194. {
  195. // Just this
  196. c = This->Colour;
  197. }
  198. else if (p > This->Pos AND p < Next->Pos)
  199. {
  200. // Interpolate between this and next
  201. float d = Next->Pos - This->Pos;
  202. float t = (Next->Pos - p) / d;
  203. float n = (p - This->Pos) / d;
  204. uint8 r = (R32(This->Colour) * t) + (R32(Next->Colour) * n);
  205. uint8 g = (G32(This->Colour) * t) + (G32(Next->Colour) * n);
  206. uint8 b = (B32(This->Colour) * t) + (B32(Next->Colour) * n);
  207. uint8 a = (A32(This->Colour) * t) + (A32(Next->Colour) * n);
  208. c = Rgba32(r, g, b, a);
  209. }
  210. else if (p >= Next->Pos)
  211. {
  212. // Get next colour stops
  213. This = Stops.Length() > CurStop ? &Stops[CurStop] : 0;
  214. CurStop++;
  215. Next = Stops.Length() > CurStop ? &Stops[CurStop] : 0;
  216. goto DoStop;
  217. }
  218. pDC->Colour(c, 32);
  219. if (Vert)
  220. pDC->Line(r.x1, r.y1 + n, r.x2, r.y1 + n);
  221. else
  222. pDC->Line(r.x1 + n, r.y1, r.x1 + n, r.y2);
  223. }
  224. }
  225. }
  226. //////////////////////////////////////////////////////////////////////////////////
  227. // Other Gdc Stuff
  228. COLOUR RgbToHls(COLOUR Rgb24)
  229. {
  230. int nMax;
  231. int nMin;
  232. int R = R24(Rgb24);
  233. int G = G24(Rgb24);
  234. int B = B24(Rgb24);
  235. int H, L, S;
  236. bool Undefined = FALSE;
  237. nMax = max(R, max(G, B));
  238. nMin = min(R, min(G, B));
  239. L = (nMax + nMin) / 2;
  240. if (nMax == nMin)
  241. {
  242. H = HUE_UNDEFINED;
  243. S = 0;
  244. Undefined = TRUE;
  245. }
  246. else
  247. {
  248. double fHue;
  249. int nDelta;
  250. if (L < 128)
  251. {
  252. S = (uchar) ((255.0 * ((double)(nMax - nMin)) / (double)(nMax + nMin)) + 0.5);
  253. }
  254. else
  255. {
  256. S = (uchar) ((255.0 * ((double)(nMax - nMin)) / (double)(511 - nMax - nMin)) + 0.5);
  257. }
  258. nDelta = nMax - nMin;
  259. if (R == nMax)
  260. {
  261. fHue = ((double) (G - B)) / (double) nDelta;
  262. }
  263. else if (G == nMax)
  264. {
  265. fHue = 2.0 + ((double) (B - R)) / (double) nDelta;
  266. }
  267. else
  268. {
  269. fHue = 4.0 + ((double) (R - G)) / (double) nDelta;
  270. }
  271. fHue *= 60;
  272. if (fHue < 0.0)
  273. {
  274. fHue += 360.0;
  275. }
  276. H = (short) (fHue + 0.5);
  277. }
  278. return Hls32(H, L, S);
  279. }
  280. int HlsValue(double fN1, double fN2, double fHue)
  281. {
  282. int nValue;
  283. if (fHue > 360.0)
  284. {
  285. fHue -= 360.0;
  286. }
  287. else if (fHue < 0.0)
  288. {
  289. fHue += 360.0;
  290. }
  291. if (fHue < 60.0)
  292. {
  293. nValue = (int) ((fN1 + (fN2 - fN1) * fHue / 60.0) * 255.0 + 0.5);
  294. }
  295. else if (fHue < 180.0)
  296. {
  297. nValue = (int) ((fN2 * 255.0) + 0.5);
  298. }
  299. else if (fHue < 240.0)
  300. {
  301. nValue = (int) ((fN1 + (fN2 - fN1) * (240.0 - fHue) / 60.0) * 255.0 + 0.5);
  302. }
  303. else
  304. {
  305. nValue = (int) ((fN1 * 255.0) + 0.5);
  306. }
  307. return (nValue);
  308. }
  309. COLOUR HlsToRgb(COLOUR Hls)
  310. {
  311. int H = H32(Hls);
  312. int L = L32(Hls);
  313. int S = S32(Hls);
  314. int R, G, B;
  315. if (S == 0)
  316. {
  317. R = 0;
  318. G = 0;
  319. B = 0;
  320. }
  321. else
  322. {
  323. double fM1;
  324. double fM2;
  325. double fHue;
  326. double fLightness;
  327. double fSaturation;
  328. while (H >= 360)
  329. {
  330. H -= 360;
  331. }
  332. while (H < 0)
  333. {
  334. H += 360;
  335. }
  336. fHue = (double) H;
  337. fLightness = ((double) L) / 255.0;
  338. fSaturation = ((double) S) / 255.0;
  339. if (L < 128)
  340. {
  341. fM2 = fLightness * (1 + fSaturation);
  342. }
  343. else
  344. {
  345. fM2 = fLightness + fSaturation - (fLightness * fSaturation);
  346. }
  347. fM1 = 2.0 * fLightness - fM2;
  348. R = HlsValue(fM1, fM2, fHue + 120.0);
  349. G = HlsValue(fM1, fM2, fHue);
  350. B = HlsValue(fM1, fM2, fHue - 120.0);
  351. }
  352. return Rgb24(R, G, B);
  353. }
  354. GSurface *ConvertDC(GSurface *pDC, int Bits)
  355. {
  356. GSurface *pNew = new GMemDC;
  357. if (pNew AND pNew->Create(pDC->X(), pDC->Y(), Bits))
  358. {
  359. pNew->Blt(0, 0, pDC);
  360. DeleteObj(pDC);
  361. return pNew;
  362. }
  363. return pDC;
  364. }
  365. GColour GdcMixColour(GColour c1, GColour c2, float HowMuchC1)
  366. {
  367. float HowMuchC2 = 1.0 - HowMuchC1;
  368. int r = (c1.r()*HowMuchC1) + (c2.r()*HowMuchC2);
  369. int g = (c1.g()*HowMuchC1) + (c2.g()*HowMuchC2);
  370. int b = (c1.b()*HowMuchC1) + (c2.b()*HowMuchC2);
  371. int a = (c1.a()*HowMuchC1) + (c2.a()*HowMuchC2);
  372. return GColour(r, g, b, a);
  373. }
  374. COLOUR GdcMixColour(COLOUR c1, COLOUR c2, float HowMuchC1)
  375. {
  376. double HowMuchC2 = 1.0 - HowMuchC1;
  377. int r = (R24(c1)*HowMuchC1) + (R24(c2)*HowMuchC2);
  378. int g = (G24(c1)*HowMuchC1) + (G24(c2)*HowMuchC2);
  379. int b = (B24(c1)*HowMuchC1) + (B24(c2)*HowMuchC2);
  380. return Rgb24(r, g, b);
  381. }
  382. COLOUR GdcGreyScale(COLOUR c, int Bits)
  383. {
  384. COLOUR c24 = CBit(24, c, Bits);
  385. int r = (R24(c24) * 76) / 255;
  386. int g = (G24(c24) * 150) / 255;
  387. int b = (B24(c24) * 29) / 255;
  388. return r + g + b;
  389. }
  390. COLOUR CBit(int DstBits, COLOUR c, int SrcBits, GPalette *Pal)
  391. {
  392. if (SrcBits == DstBits)
  393. {
  394. return c;
  395. }
  396. else
  397. {
  398. COLOUR c24 = 0;
  399. switch (SrcBits)
  400. {
  401. case 8:
  402. {
  403. GdcRGB Grey, *p = 0;
  404. if (!Pal OR !(p = (*Pal)[c]))
  405. {
  406. Grey.R = Grey.G = Grey.B = c & 0xFF;
  407. p = &Grey;
  408. }
  409. switch (DstBits)
  410. {
  411. case 16:
  412. {
  413. return Rgb16(p->R, p->G, p->B);
  414. }
  415. case 24:
  416. {
  417. return Rgb24(p->R, p->G, p->B);
  418. }
  419. case 32:
  420. {
  421. return Rgb32(p->R, p->G, p->B);
  422. }
  423. }
  424. break;
  425. }
  426. case 15:
  427. {
  428. int R = R15(c);
  429. int G = G15(c);
  430. int B = B15(c);
  431. R = R | (R >> 5);
  432. G = G | (G >> 5);
  433. B = B | (B >> 5);
  434. switch (DstBits)
  435. {
  436. case 8:
  437. {
  438. if (Pal)
  439. {
  440. return Pal->MatchRgb(Rgb24(R, G, B));
  441. }
  442. break;
  443. }
  444. case 16:
  445. {
  446. return Rgb16(R, G, B);
  447. }
  448. case 24:
  449. {
  450. return Rgb24(R, G, B);
  451. }
  452. case 32:
  453. {
  454. return Rgb32(R, G, B);
  455. }
  456. }
  457. break;
  458. }
  459. case 16:
  460. {
  461. /*
  462. int R = ((c>>8)&0xF8) | ((c>>13)&0x7);
  463. int G = ((c>>3)&0xFC) | ((c>>9)&0x3);
  464. int B = ((c<<3)&0xF8) | ((c>>2)&0x7);
  465. */
  466. int R = (c >> 8) & 0xF8;
  467. int G = (c >> 3) & 0xFC;
  468. int B = (c << 3) & 0xF8;
  469. switch (DstBits)
  470. {
  471. case 8:
  472. {
  473. if (Pal)
  474. {
  475. return Pal->MatchRgb(Rgb24(R, G, B));
  476. }
  477. break;
  478. }
  479. case 15:
  480. {
  481. return Rgb16To15(c);
  482. }
  483. case 24:
  484. {
  485. return Rgb24(R, G, B);
  486. }
  487. case 32:
  488. {
  489. return Rgb32(R, G, B);
  490. }
  491. }
  492. break;
  493. }
  494. case 24:
  495. {
  496. switch (DstBits)
  497. {
  498. case 8:
  499. {
  500. if (Pal)
  501. {
  502. return Pal->MatchRgb(c);
  503. }
  504. break;
  505. }
  506. case 15:
  507. {
  508. return Rgb24To15(c);
  509. }
  510. case 16:
  511. {
  512. if (LgiGetOs() == LGI_OS_WINNT)
  513. {
  514. return Rgb24To16(c);
  515. }
  516. int r = max(R24(c) - 1, 0) >> 3;
  517. int g = max(G24(c) - 1, 0) >> 2;
  518. int b = max(B24(c) - 1, 0) >> 3;
  519. return (r << 11) | (g << 5) | (b);
  520. }
  521. case 32:
  522. {
  523. return Rgb24To32(c);
  524. }
  525. }
  526. break;
  527. }
  528. case 32:
  529. {
  530. switch (DstBits)
  531. {
  532. case 8:
  533. {
  534. if (Pal)
  535. {
  536. return Pal->MatchRgb(Rgb32To24(c));
  537. }
  538. break;
  539. }
  540. case 15:
  541. {
  542. return Rgb32To15(c);
  543. }
  544. case 16:
  545. {
  546. return Rgb32To16(c);
  547. }
  548. case 24:
  549. {
  550. return Rgb32To24(c);
  551. }
  552. }
  553. break;
  554. }
  555. }
  556. }
  557. return c;
  558. }