OANLINE.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. /*
  2. * Seven Kingdoms: Ancient Adversaries
  3. *
  4. * Copyright 1997,1998 Enlight Software Ltd.
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. *
  19. */
  20. // Filename : OANLINE.CPP
  21. // Description : animated line
  22. // Onwership : Gilbert
  23. #include <OANLINE.h>
  24. #include <OVGABUF.h>
  25. #include <ALL.h>
  26. #include <math.h>
  27. // ----------- Define color table
  28. unsigned char AnimLine::init_color_code[ANIMCOLOR_PERIOD][ANIMLINE_PERIOD] =
  29. {
  30. // { 0x90, 0x93, 0x98, 0x9c, 0x9f, 0x9c, 0x98, 0x93 },
  31. // { 0x90, 0x93, 0x97, 0x9a, 0x9d, 0x9a, 0x97, 0x93 },
  32. // { 0x90, 0x92, 0x95, 0x97, 0x9a, 0x97, 0x95, 0x92 },
  33. // { 0x90, 0x92, 0x95, 0x97, 0x9a, 0x97, 0x95, 0x92 },
  34. // { 0x90, 0x93, 0x97, 0x9a, 0x9d, 0x9a, 0x97, 0x93 },
  35. // { 0x90, 0x93, 0x98, 0x9c, 0x9f, 0x9c, 0x98, 0x93 }
  36. { 0xa6, 0xa5, 0xa4, 0xa4, 0x9c, 0xa4, 0xa4, 0xa5 },
  37. { 0xa7, 0xa6, 0xa5, 0xa4, 0x9c, 0xa4, 0xa5, 0xa6 },
  38. { 0xc7, 0xa7, 0xa6, 0x9c, 0x9f, 0x9c, 0xa6, 0xa7 },
  39. { 0x90, 0x93, 0x98, 0x9c, 0x9f, 0x9c, 0x98, 0x93 },
  40. { 0xc7, 0xa7, 0xa6, 0x9c, 0x9f, 0x9c, 0xa6, 0xa7 },
  41. { 0xa7, 0xa6, 0xa5, 0xa4, 0x9c, 0xa4, 0xa5, 0xa6 }
  42. };
  43. unsigned char AnimLine::series_color_code[ANIMCOLOR_SERIES][ANIMLINE_PERIOD] =
  44. {
  45. { 0x90, 0x93, 0x98, 0x9c, 0x9f, 0x9c, 0x98, 0x93 },
  46. // { 0xa6, 0xa5, 0xa4, 0x9c, 0x9f, 0x9c, 0xa4, 0xa5 },
  47. { 0xA0, 0xA1, 0xA2, 0xA3, 0xC3, 0xA3, 0xA2, 0xA0 },
  48. { 0xA0, 0xC3, 0xA0, 0xC3, 0xA0, 0xC3, 0xA0, 0xC3 },
  49. };
  50. // ----------- Begin of function AnimLine::init ----------//
  51. //
  52. // <short> x1, y1, x2, y2 defines corners of the display area
  53. //
  54. void AnimLine::init(short x1, short y1, short x2, short y2)
  55. {
  56. // set the boundary
  57. bound_x1 = x1;
  58. bound_y1 = y1;
  59. bound_x2 = x2;
  60. bound_y2 = y2;
  61. phase = 0;
  62. color_phase = 0;
  63. }
  64. // ----------- End of function AnimLine::init ----------//
  65. // ----------- Begin of function AnimLine::inc_phase ----------//
  66. //
  67. // called after each display cycle
  68. //
  69. void AnimLine::inc_phase()
  70. {
  71. phase = (phase == 0 ? ANIMLINE_PERIOD : phase) - 1;
  72. if( ++color_phase >= ANIMCOLOR_PERIOD*ANIMCOLOR_INNER_PERIOD )
  73. color_phase = 0;
  74. }
  75. // ----------- End of function AnimLine::inc_phase ----------//
  76. // ----------- Begin of function AnimLine::draw_line ----------//
  77. //
  78. // clip the line before calling basic_line, basic_hline or basic_vline to draw
  79. // animatedFlag = TRUE for animated line, FALSE for stable line
  80. //
  81. // <VgaBuf *>vgabuf destination vgabuf
  82. // <short> x1,y1,x2,y2 draw from (x1,y1) to (x2,y2) on the screen
  83. // [int] animatedFlag whether the colors of the line is cycle (default:1 = animated)
  84. // [int] effectFlag effect : -1=dimming B/W, 0=non-dimming B/W, 1=non-dimming series (default : 0)
  85. //
  86. void AnimLine::draw_line(VgaBuf *vgabuf, short x1, short y1, short x2, short y2, int animatedFlag, int effectFlag)
  87. {
  88. if( (x1 < bound_x1 && x2 < bound_x1) || ( x1 > bound_x2 && x2 > bound_x2) ||
  89. (y1 < bound_y1 && y2 < bound_y1) || ( y1 > bound_y2 && y2 > bound_y2) )
  90. return;
  91. unsigned char* colorCode;
  92. if( effectFlag == -1)
  93. colorCode = init_color_code[color_phase/ANIMCOLOR_INNER_PERIOD];
  94. else if( effectFlag >= 0 && effectFlag < ANIMCOLOR_SERIES)
  95. colorCode = series_color_code[effectFlag];
  96. else
  97. {
  98. err_here(); // invalid effectFlag
  99. colorCode = init_color_code[0];
  100. }
  101. if( x1 >= bound_x1 && x1 <= bound_x2 && x2 >= bound_x1 && x2 <= bound_x2 &&
  102. y1 >= bound_y1 && y1 <= bound_y2 && y2 >= bound_y1 && y2 <= bound_y2)
  103. {
  104. // already inside the screen
  105. if( y1 == y2)
  106. {
  107. basic_hline(vgabuf, x1, x2, y2, animatedFlag, colorCode);
  108. }
  109. else if( x1 == x2)
  110. {
  111. basic_vline(vgabuf, x1, y1, y2, animatedFlag, colorCode);
  112. }
  113. else
  114. {
  115. basic_line(vgabuf, x1, y1, x2, y2, animatedFlag, colorCode);
  116. }
  117. }
  118. else
  119. {
  120. if( y1 == y2)
  121. {
  122. // horizontal line
  123. if( y1 < bound_y1 || y1 > bound_y2)
  124. return;
  125. if( x1 < bound_x1)
  126. x1 = bound_x1;
  127. else if( x1 > bound_x2)
  128. x1 = bound_x2;
  129. if( x2 < bound_x1)
  130. x2 = bound_x1;
  131. else if (x2 > bound_x2)
  132. x2 = bound_x2;
  133. basic_hline(vgabuf, x1, x2, y1, animatedFlag, colorCode);
  134. }
  135. else if( x1 == x2)
  136. {
  137. // vertical line
  138. if( x1 < bound_x1 || x1 > bound_x2)
  139. return;
  140. if( y1 < bound_y1)
  141. y1 = bound_y1;
  142. else if( y1 > bound_y2)
  143. y1 = bound_y2;
  144. if( y2 < bound_y1)
  145. y2 = bound_y1;
  146. else if( y2 > bound_y2)
  147. y2 = bound_y2;
  148. basic_vline(vgabuf, x1, y1, y2, animatedFlag, colorCode);
  149. }
  150. else
  151. {
  152. // neither horizontal or vertical
  153. int x1a, y1a, x1b, y1b;
  154. int x2a, y2a, x2b, y2b;
  155. // find intersection points for the first point
  156. x1a = x1b = x1;
  157. y1a = y1b = y1;
  158. if( y1 < bound_y1)
  159. {
  160. y1a = bound_y1;
  161. x1a = top_intercept( x1, y1, x2, y2);
  162. }
  163. if( y1 > bound_y2)
  164. {
  165. y1a = bound_y2;
  166. x1a = bottom_intercept(x1, y1 ,x2, y2);
  167. }
  168. if( x1 < bound_x1)
  169. {
  170. x1b = bound_x1;
  171. y1b = left_intercept(x1, y1, x2, y2);
  172. }
  173. if( x1 > bound_x2)
  174. {
  175. x1b = bound_x2;
  176. y1b = right_intercept( x1, y1, x2, y2);
  177. }
  178. // find intersection points for the second point
  179. x2a = x2b = x2;
  180. y2a = y2b = y2;
  181. if( y2 < bound_y1)
  182. {
  183. y2a = bound_y1;
  184. x2a = top_intercept( x1, y1, x2, y2);
  185. }
  186. if( y2 > bound_y2)
  187. {
  188. y2a = bound_y2;
  189. x2a = bottom_intercept(x1, y1 ,x2, y2);
  190. }
  191. if( x2 < bound_x1)
  192. {
  193. x2b = bound_x1;
  194. y2b = left_intercept(x1, y1, x2, y2);
  195. }
  196. if( x2 > bound_x2)
  197. {
  198. x2b = bound_x2;
  199. y2b = right_intercept( x1, y1, x2, y2);
  200. }
  201. // replace x1, y1
  202. if( x1 < bound_x1 || x1 > bound_x2 || y1 < bound_y1 || y1 > bound_y2)
  203. {
  204. if( x1a < bound_x1 || x1a > bound_x2 || y1a < bound_y1 || y1a > bound_y2)
  205. {
  206. if( x1b < bound_x1 || x1b > bound_x2 || y1b < bound_y1 || y1b > bound_y2)
  207. {
  208. return;
  209. }
  210. else
  211. {
  212. x1 = x1b;
  213. y1 = y1b;
  214. }
  215. }
  216. else
  217. {
  218. x1 = x1a;
  219. y1 = y1a;
  220. }
  221. }
  222. // replace x2, y2
  223. if( x2 < bound_x1 || x2 > bound_x2 || y2 < bound_y1 || y2 > bound_y2)
  224. {
  225. if( x2a < bound_x1 || x2a > bound_x2 || y2a < bound_y1 || y2a > bound_y2)
  226. {
  227. if( x2b < bound_x1 || x2b > bound_x2 || y2b < bound_y1 || y2b > bound_y2)
  228. {
  229. return;
  230. }
  231. else
  232. {
  233. x2 = x2b;
  234. y2 = y2b;
  235. }
  236. }
  237. else
  238. {
  239. x2 = x2a;
  240. y2 = y2a;
  241. }
  242. }
  243. // a segment may be horizontal or vertical, check again
  244. // if( y1 == y2)
  245. // basic_hline(vgabuf, x1, x2, y1, animatedFlag);
  246. // else if( x1 == x2)
  247. // basic_vline(vgabuf, x1, y1, y2, animatedFlag);
  248. // else
  249. basic_line(vgabuf, x1, y1, x2, y2, animatedFlag, colorCode);
  250. }
  251. }
  252. }
  253. // ----------- End of function AnimLine::draw_line ----------//
  254. // ----------- Begin of function AnimLine::thick_line ----------//
  255. //
  256. // draw a thicker line
  257. //
  258. // <VgaBuf *>vgabuf destination vgabuf
  259. // <short> x1,y1,x2,y2 draw from (x1,y1) to (x2,y2) on the screen
  260. // [int] animatedFlag whether the colors of the line is cycle (default:1 = animated)
  261. // [int] effectFlag effect : -1=dimming B/W, 0=non-dimming B/W, 1=non-dimming series (default : 0)
  262. //
  263. void AnimLine::thick_line(VgaBuf *vgabuf, short x1, short y1, short x2, short y2, int animatedFlag, int effectFlag)
  264. {
  265. if( abs(x2-x1) > abs(y2-y1) )
  266. {
  267. // likely to be horizontal, draw top, bottom and centre
  268. draw_line( vgabuf, x1, y1-1, x2, y2-1, animatedFlag, effectFlag);
  269. draw_line( vgabuf, x1, y1+1, x2, y2+1, animatedFlag, effectFlag);
  270. }
  271. else
  272. {
  273. // likely to be vertical, draw left right and centre
  274. draw_line( vgabuf, x1-1, y1, x2-1, y2, animatedFlag, effectFlag);
  275. draw_line( vgabuf, x1+1, y1, x2+1, y2, animatedFlag, effectFlag);
  276. }
  277. draw_line( vgabuf, x1, y1, x2, y2, animatedFlag, effectFlag);
  278. }
  279. // ----------- End of function AnimLine::thick_line ----------//
  280. // ----------- Begin of function AnimLine::basic_line ----------//
  281. //
  282. // draw a clipped line
  283. //
  284. void AnimLine::basic_line(VgaBuf *vgabuf, short x1, short y1, short x2, short y2, int animatedFlag,
  285. unsigned char *colorCode)
  286. {
  287. err_when( x1 < bound_x1 || x1 > bound_x2 );
  288. err_when( x2 < bound_x1 || x2 > bound_x2 );
  289. err_when( y1 < bound_y1 || y1 > bound_y2 );
  290. err_when( y2 < bound_y1 || y2 > bound_y2 );
  291. int dx = x2 - x1;
  292. int dy = y2 - y1;
  293. if( dy == 0)
  294. {
  295. basic_hline(vgabuf, x1, x2, y1, animatedFlag, colorCode);
  296. return;
  297. }
  298. if( dx == 0)
  299. {
  300. basic_vline(vgabuf, x1, y1, y2, animatedFlag, colorCode);
  301. return;
  302. }
  303. int d;
  304. int inc_x = dx > 0 ? 1 : -1;
  305. int inc_y = dy > 0 ? 1 : -1;
  306. int lPitch = dy > 0 ? vgabuf->buf_pitch() : -vgabuf->buf_pitch();
  307. unsigned char *bufPtr = (unsigned char *) vgabuf->buf_ptr(x1,y1);
  308. short linePhase;
  309. err_when( dx == 0 || dy == 0);
  310. if( abs(dy) <= abs(dx) )
  311. {
  312. // draw gentle line
  313. // use x as independent variable
  314. dx = abs(dx);
  315. dy = abs(dy);
  316. d = 2 * dy - dx;
  317. int x = x1-inc_x;
  318. linePhase = animatedFlag ? phase : 0;
  319. do
  320. {
  321. x += inc_x;
  322. *bufPtr = colorCode[linePhase];
  323. if(++linePhase >= ANIMLINE_PERIOD )
  324. linePhase = 0;
  325. bufPtr += inc_x;
  326. if( d >= 0)
  327. {
  328. // y increase by 1
  329. bufPtr += lPitch;
  330. d += 2 * (dy - dx);
  331. }
  332. else
  333. {
  334. // y remain unchange;
  335. d += 2 * dy;
  336. }
  337. } while ( x != x2);
  338. }
  339. else
  340. {
  341. // draw steep line
  342. // use y as independent variable
  343. dx = abs(dx);
  344. dy = abs(dy);
  345. d = 2 * dx - dy;
  346. int y = y1 - inc_y;
  347. linePhase = animatedFlag ? phase : 0;
  348. do
  349. {
  350. y += inc_y;
  351. *bufPtr = colorCode[linePhase];
  352. if(++linePhase >= ANIMLINE_PERIOD )
  353. linePhase = 0;
  354. bufPtr += lPitch;
  355. if( d >= 0)
  356. {
  357. // x increase by 1
  358. bufPtr += inc_x;
  359. d += 2 * (dx - dy);
  360. }
  361. else
  362. {
  363. // x remain unchange;
  364. d += 2 * dx;
  365. }
  366. } while ( y != y2);
  367. }
  368. }
  369. // ----------- End of function AnimLine::basic_line ----------//
  370. // ----------- Begin of function AnimLine::basic_hline ----------//
  371. //
  372. // draw a clipped horizontal line
  373. //
  374. void AnimLine::basic_hline(VgaBuf *vgabuf, short x1, short x2, short y1, int animatedFlag,
  375. unsigned char *colorCode)
  376. {
  377. err_when( x1 < bound_x1 || x1 > bound_x2 );
  378. err_when( x2 < bound_x1 || x2 > bound_x2 );
  379. err_when( y1 < bound_y1 || y1 > bound_y2 );
  380. short linePhase = animatedFlag ? phase : 0;
  381. unsigned char *bufPtr = (unsigned char *)vgabuf->buf_ptr(x1, y1);
  382. if( x1 <= x2)
  383. {
  384. // from left to right
  385. for(short x = x1; x <= x2; ++x, ++bufPtr)
  386. {
  387. *bufPtr = colorCode[linePhase];
  388. if(++linePhase >= ANIMLINE_PERIOD )
  389. linePhase = 0;
  390. }
  391. }
  392. else
  393. {
  394. // from right to left
  395. for( short x = x1; x >= x2; --x, --bufPtr)
  396. {
  397. *bufPtr = colorCode[linePhase];
  398. if(++linePhase >= ANIMLINE_PERIOD )
  399. linePhase = 0;
  400. }
  401. }
  402. }
  403. // ----------- End of function AnimLine::basic_hline ----------//
  404. // ----------- Begin of function AnimLine::basic_vline ----------//
  405. //
  406. // draw a clipped vertical line
  407. //
  408. void AnimLine::basic_vline(VgaBuf *vgabuf, short x1, short y1, short y2, int animatedFlag,
  409. unsigned char *colorCode)
  410. {
  411. err_when( x1 < bound_x1 || x1 > bound_x2 );
  412. err_when( y1 < bound_y1 || y1 > bound_y2 );
  413. err_when( y2 < bound_y1 || y2 > bound_y2 );
  414. short linePhase = animatedFlag ? phase : 0;
  415. unsigned char *bufPtr = (unsigned char *) vgabuf->buf_ptr(x1, y1);
  416. int lPitch = vgabuf->buf_pitch();
  417. if( y1 <= y2)
  418. {
  419. // from top to bottom
  420. for(short y = y1; y <= y2; ++y, bufPtr += lPitch)
  421. {
  422. *bufPtr = colorCode[linePhase];
  423. if(++linePhase >= ANIMLINE_PERIOD )
  424. linePhase = 0;
  425. }
  426. }
  427. else
  428. {
  429. // from bottom to top
  430. for( short y = y1; y >= y2; --y, bufPtr -= lPitch)
  431. {
  432. *bufPtr = colorCode[linePhase];
  433. if(++linePhase >= ANIMLINE_PERIOD )
  434. linePhase = 0;
  435. }
  436. }
  437. }
  438. // ----------- End of function AnimLine::basic_vline ----------//
  439. // ----------- Begin of function AnimLine::get_series_color_array ----------//
  440. unsigned char *AnimLine::get_series_color_array(int effectFlag)
  441. {
  442. unsigned char *colorCode;
  443. if( effectFlag == -1)
  444. colorCode = init_color_code[color_phase/ANIMCOLOR_INNER_PERIOD];
  445. else if( effectFlag >= 0 && effectFlag < ANIMCOLOR_SERIES)
  446. colorCode = series_color_code[effectFlag];
  447. else
  448. {
  449. err_here(); // invalid effectFlag
  450. colorCode = init_color_code[0];
  451. }
  452. return colorCode;
  453. }
  454. // ----------- End of function AnimLine::get_series_color_array ----------//
  455. // ----------- Begin of function AnimLine::top_intercept ----------//
  456. short AnimLine::top_intercept( short x1, short y1, short x2, short y2)
  457. {
  458. return (bound_y1-y1) * (x2-x1) / (y2-y1) + x1;
  459. }
  460. // ----------- End of function AnimLine::top_intercept ----------//
  461. // ----------- Begin of function AnimLine::bottom_intercept ----------//
  462. short AnimLine::bottom_intercept( short x1, short y1, short x2, short y2)
  463. {
  464. return (bound_y2-y1) * (x2-x1) / (y2-y1) + x1;
  465. }
  466. // ----------- End of function AnimLine::bottom_intercept ----------//
  467. // ----------- Begin of function AnimLine::left_intercept ----------//
  468. short AnimLine::left_intercept( short x1, short y1, short x2, short y2)
  469. {
  470. return (bound_x1-x1) * (y2-y1) / (x2-x1) + y1;
  471. }
  472. // ----------- End of function AnimLine::left_intercept ----------//
  473. // ----------- Begin of function AnimLine::right_intercept ----------//
  474. short AnimLine::right_intercept( short x1, short y1, short x2, short y2)
  475. {
  476. return (bound_x2-x1) * (y2-y1) / (x2-x1) + y1;
  477. }
  478. // ----------- End of function AnimLine::right_intercept ----------//