image16.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. /********************************************************************** <BR>
  2. This file is part of Crack dot Com's free source code release of
  3. Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
  4. information about compiling & licensing issues visit this URL</a>
  5. <PRE> If that doesn't help, contact Jonathan Clark at
  6. golgotha_source@usa.net (Subject should have "GOLG" in it)
  7. ***********************************************************************/
  8. #include "image/image16.hh"
  9. #include "memory/malloc.hh"
  10. #include "palette/pal.hh"
  11. #include "image/context.hh"
  12. #include <string.h>
  13. inline int iabs(int val) { return val>0?val:-val; }
  14. i4_color i4_image16::get_pixel(i4_coord x, i4_coord y)
  15. {
  16. return i4_pal_man.convert_to_32(*paddr(x,y), pal);
  17. }
  18. void i4_image16::put_pixel(i4_coord x, i4_coord y, w32 color)
  19. {
  20. w16 *addr=paddr(x,y);
  21. *addr=i4_pal_man.convert_32_to(color, &pal->source);
  22. }
  23. i4_image16::i4_image16(w16 _w, w16 _h, const i4_pal *_pal)
  24. {
  25. w=_w;
  26. h=_h;
  27. bpl=_w*2;
  28. set_pal(_pal);
  29. data=i4_malloc(w*h*2, "");
  30. }
  31. i4_image16::i4_image16(w16 _w, w16 _h, const i4_pal *_pal,
  32. void *_data, int _bpl)
  33. {
  34. data=_data;
  35. bpl=_bpl;
  36. pal=_pal;
  37. w=_w;
  38. h=_h;
  39. dont_free_data=i4_T;
  40. }
  41. i4_image16::~i4_image16()
  42. {
  43. if (!dont_free_data)
  44. i4_free(data);
  45. }
  46. void i4_image16::line(i4_coord ox1, i4_coord oy1,
  47. i4_coord ox2, i4_coord oy2,
  48. i4_color color, i4_draw_context_class &context)
  49. {
  50. i4_coord x1,y1,x2,y2;
  51. i4_coord cx1,cy1,cx2,cy2;
  52. i4_bool skip;
  53. w16 tcolor=i4_pal_man.convert_32_to(color, &pal->source);
  54. for (i4_rect_list_class::area_iter c=context.clip.list.begin();c!=context.clip.list.end();++c)
  55. {
  56. x1=ox1;
  57. y1=oy1;
  58. x2=ox2;
  59. y2=oy2;
  60. skip=i4_F;
  61. i4_coord i,xc,yc,er,n,m,xi,yi,xcxi,ycyi,xcyi;
  62. unsigned dcy,dcx;
  63. // check to make sure that both endpoint are on the screen
  64. cx1=c->x1;
  65. cy1=c->y1;
  66. cx2=c->x2;
  67. cy2=c->y2;
  68. // check to see if the line is completly clipped off
  69. if (!((x1<cx1 && x2<cx1) || (x1>cx2 && x2>cx2) ||
  70. (y1<cy1 && y2<cy1) || (y1>cy2 && y2>cy2)))
  71. {
  72. if (x1>x2) // make sure that x1 is to the left
  73. {
  74. i=x1; x1=x2; x2=i; // if not swap points
  75. i=y1; y1=y2; y2=i;
  76. }
  77. // clip the left side
  78. if (x1<cx1)
  79. {
  80. int my=(y2-y1);
  81. int mx=(x2-x1),b;
  82. if (!mx) skip=i4_T;
  83. if (my)
  84. {
  85. b=y1-(y2-y1)*x1/mx;
  86. y1=my*cx1/mx+b;
  87. x1=cx1;
  88. }
  89. else x1=cx1;
  90. }
  91. // clip the right side
  92. if (x2>cx2)
  93. {
  94. int my=(y2-y1);
  95. int mx=(x2-x1),b;
  96. if (!mx) skip=i4_T;
  97. else if (my)
  98. {
  99. b=y1-(y2-y1)*x1/mx;
  100. y2=my*cx2/mx+b;
  101. x2=cx2;
  102. }
  103. else x2=cx2;
  104. }
  105. if (y1>y2) // make sure that y1 is on top
  106. {
  107. i=x1; x1=x2; x2=i; // if not swap points
  108. i=y1; y1=y2; y2=i;
  109. }
  110. // clip the bottom
  111. if (y2>cy2)
  112. {
  113. int mx=(x2-x1);
  114. int my=(y2-y1),b;
  115. if (!my)
  116. skip=i4_T;
  117. else if (mx)
  118. {
  119. b=y1-(y2-y1)*x1/mx;
  120. x2=(cy2-b)*mx/my;
  121. y2=cy2;
  122. }
  123. else y2=cy2;
  124. }
  125. // clip the top
  126. if (y1<cy1)
  127. {
  128. int mx=(x2-x1);
  129. int my=(y2-y1),b;
  130. if (!my)
  131. skip=i4_T;
  132. else if (mx)
  133. {
  134. b=y1-(y2-y1)*x1/mx;
  135. x1=(cy1-b)*mx/my;
  136. y1=cy1;
  137. }
  138. else y1=cy1;
  139. }
  140. // see if it got cliped into the box, out out
  141. if (x1<cx1 || x2<cx1 || x1>cx2 || x2>cx2 || y1<cy1 || y2 <cy1 || y1>cy2 || y2>cy2)
  142. skip=i4_T;
  143. if (x1>x2)
  144. { xc=x2; xi=x1; }
  145. else { xi=x2; xc=x1; }
  146. if (!skip)
  147. {
  148. // assume y1<=y2 from above swap operation
  149. yi=y2; yc=y1;
  150. add_dirty(xc,yc,xi,yi,context);
  151. dcx=x1+context.xoff; dcy=y1+context.yoff;
  152. xc=(x2-x1); yc=(y2-y1);
  153. if (xc<0) xi=-1; else xi=1;
  154. if (yc<0) yi=-1; else yi=1;
  155. n=iabs(xc); m=iabs(yc);
  156. ycyi=iabs(2*yc*xi);
  157. er=0;
  158. if (n>m)
  159. {
  160. xcxi=iabs(2*xc*xi);
  161. for (i=0;i<=n;i++)
  162. {
  163. *paddr(dcx, dcy)=tcolor;
  164. if (er>0)
  165. {
  166. dcy+=yi;
  167. er-=xcxi;
  168. }
  169. er+=ycyi;
  170. dcx+=xi;
  171. }
  172. }
  173. else
  174. {
  175. xcyi=iabs(2*xc*yi);
  176. for (i=0;i<=m;i++)
  177. {
  178. *paddr(dcx, dcy)=tcolor;
  179. if (er>0)
  180. {
  181. dcx+=xi;
  182. er-=ycyi;
  183. }
  184. er+=xcyi;
  185. dcy+=yi;
  186. }
  187. }
  188. }
  189. }
  190. }
  191. }
  192. void i4_image16::put_part(i4_image_class *to,
  193. i4_coord _x, i4_coord _y,
  194. i4_coord x1, i4_coord y1, i4_coord x2, i4_coord y2,
  195. i4_draw_context_class &context)
  196. {
  197. const i4_pixel_format *from_format=&get_pal()->source;
  198. const i4_pixel_format *to_format=&to->get_pal()->source;
  199. if ((to_format->pixel_depth!=I4_16BIT ||
  200. to_format->red_mask != from_format->red_mask ||
  201. to_format->green_mask != from_format->green_mask ||
  202. to_format->blue_mask != from_format->blue_mask) &&
  203. (from_format->alpha_mask==0 || to_format->alpha_mask))
  204. // depths aren't the same do it the slow way
  205. i4_image_class::put_part(to, _x, _y, x1,y1,x2,y2, context);
  206. else
  207. {
  208. for (i4_rect_list_class::area_iter c=context.clip.list.begin();
  209. c!=context.clip.list.end();
  210. ++c)
  211. {
  212. i4_coord lx1,ly1,lx2,ly2,x=_x,y=_y;
  213. if (x1<0) { lx1=0; _x+=-x1; } else lx1=x1;
  214. if (y1<0) { ly1=0; _y+=-y1; } else ly1=y1;
  215. if (x2>=width()) lx2=width()-1; else lx2=x2;
  216. if (y2>=height()) ly2=height()-1; else ly2=y2;
  217. if (!(lx1>lx2 || ly1>ly2))
  218. {
  219. if (x<c->x1)
  220. { lx1+=(c->x1-x); x=c->x1; }
  221. if (y<c->y1)
  222. { ly1+=(c->y1-y); y=c->y1; }
  223. if (x+lx2-lx1+1>c->x2)
  224. lx2=c->x2-x+lx1;
  225. if (y+ly2-ly1+1>c->y2)
  226. ly2=c->y2-y+ly1;
  227. w16 *source=paddr(lx1, ly1);
  228. w16 *dest=((i4_image16 *)to)->paddr(x + context.xoff,
  229. y + context.yoff);
  230. int copy_width=((lx2-lx1)+1)*2;
  231. if (!(lx1>lx2 || ly1>ly2))
  232. {
  233. to->add_dirty(x,y,x+(lx2-lx1+1),y+(ly2-ly1+1),context);
  234. while (ly1<=ly2)
  235. {
  236. memcpy(dest, source, copy_width);
  237. dest=((w16 *)((w8 *)dest + to->bpl));
  238. source=((w16 *)((w8 *)source + bpl));
  239. ly1++;
  240. }
  241. }
  242. }
  243. }
  244. }
  245. }
  246. void i4_image16::put_part_one_pixel_at_a_time(i4_image_class *to,
  247. i4_coord _x, i4_coord _y,
  248. i4_coord x1, i4_coord y1,
  249. i4_coord x2, i4_coord y2,
  250. i4_draw_context_class &context)
  251. {
  252. const i4_pixel_format *from_format=&get_pal()->source;
  253. const i4_pixel_format *to_format=&to->get_pal()->source;
  254. if ((to_format->pixel_depth!=I4_16BIT ||
  255. to_format->red_mask != from_format->red_mask ||
  256. to_format->green_mask != from_format->green_mask ||
  257. to_format->blue_mask != from_format->blue_mask) &&
  258. (from_format->alpha_mask==0 || to_format->alpha_mask))
  259. // depths aren't the same do it the slow way
  260. i4_image_class::put_part(to, _x, _y, x1,y1,x2,y2, context);
  261. else
  262. {
  263. for (i4_rect_list_class::area_iter c=context.clip.list.begin();
  264. c!=context.clip.list.end();
  265. ++c)
  266. {
  267. i4_coord lx1,ly1,lx2,ly2,x=_x,y=_y;
  268. if (x1<0) { lx1=0; _x+=-x1; } else lx1=x1;
  269. if (y1<0) { ly1=0; _y+=-y1; } else ly1=y1;
  270. if (x2>=width()) lx2=width()-1; else lx2=x2;
  271. if (y2>=height()) ly2=height()-1; else ly2=y2;
  272. if (!(lx1>lx2 || ly1>ly2))
  273. {
  274. if (x<c->x1)
  275. { lx1+=(c->x1-x); x=c->x1; }
  276. if (y<c->y1)
  277. { ly1+=(c->y1-y); y=c->y1; }
  278. if (x+lx2-lx1+1>c->x2)
  279. lx2=c->x2-x+lx1;
  280. if (y+ly2-ly1+1>c->y2)
  281. ly2=c->y2-y+ly1;
  282. w16 *source=paddr(lx1, ly1);
  283. w16 *dest=((i4_image16 *)to)->paddr(x + context.xoff,
  284. y + context.yoff);
  285. int copy_width=((lx2-lx1)+1)*2;
  286. if (!(lx1>lx2 || ly1>ly2))
  287. {
  288. to->add_dirty(x,y,x+(lx2-lx1+1),y+(ly2-ly1+1),context);
  289. while (ly1<=ly2)
  290. {
  291. for (int fx=0; fx<copy_width/2; fx++)
  292. dest[fx]=source[fx];
  293. dest=((w16 *)((w8 *)dest + to->bpl));
  294. source=((w16 *)((w8 *)source + bpl));
  295. ly1++;
  296. }
  297. }
  298. }
  299. }
  300. }
  301. }
  302. void i4_image16::put_part_trans(i4_image_class *to,
  303. i4_coord _x, i4_coord _y,
  304. i4_coord x1, i4_coord y1, i4_coord x2, i4_coord y2,
  305. i4_color trans_color,
  306. i4_draw_context_class &context)
  307. {
  308. const i4_pixel_format *from_format=&get_pal()->source;
  309. const i4_pixel_format *to_format=&to->get_pal()->source;
  310. if ((to_format->pixel_depth!=I4_16BIT ||
  311. to_format->red_mask != from_format->red_mask ||
  312. to_format->green_mask != from_format->green_mask ||
  313. to_format->blue_mask != from_format->blue_mask) &&
  314. (from_format->alpha_mask==0 || to_format->alpha_mask))
  315. // depths aren't the same do it the slow way
  316. i4_image_class::put_part(to, _x, _y, x1,y1,x2,y2, context);
  317. else
  318. {
  319. i4_color tcolor=i4_pal_man.convert_32_to(trans_color, &pal->source);
  320. for (i4_rect_list_class::area_iter c=context.clip.list.begin();
  321. c!=context.clip.list.end();++c)
  322. {
  323. i4_coord lx1,ly1,lx2,ly2,x=_x,y=_y;
  324. if (x1<0) { lx1=0; _x+=-x1; } else lx1=x1;
  325. if (y1<0) { ly1=0; _y+=-y1; } else ly1=y1;
  326. if (x2>=width()) lx2=width()-1; else lx2=x2;
  327. if (y2>=height()) ly2=height()-1; else ly2=y2;
  328. if (!(lx1>lx2 || ly1>ly2))
  329. {
  330. if (x<c->x1)
  331. { lx1+=(c->x1-x); x=c->x1; }
  332. if (y<c->y1)
  333. { ly1+=(c->y1-y); y=c->y1; }
  334. if (x+lx2-lx1+1>c->x2)
  335. lx2=c->x2-x+lx1;
  336. if (y+ly2-ly1+1>c->y2)
  337. ly2=c->y2-y+ly1;
  338. if (!(lx1>lx2 || ly1>ly2))
  339. {
  340. to->add_dirty(x,y,x+(lx2-lx1+1),y+(ly2-ly1+1),context);
  341. w16 *source=paddr(lx1, ly1);
  342. w16 *dest=((i4_image16 *)to)->paddr(x + context.xoff,
  343. y + context.yoff);
  344. int w=(lx2-lx1+1);
  345. for (; ly1<=ly2; ly1++)
  346. {
  347. for (int j=0; j<w; j++)
  348. {
  349. w16 c=source[j];
  350. if (c!=tcolor)
  351. dest[j]=c;
  352. }
  353. source=(w16 *)((w8 *)source + bpl);
  354. dest=(w16 *)((w8 *)dest + to->bpl);
  355. }
  356. }
  357. }
  358. }
  359. }
  360. }
  361. void i4_image16::bar(i4_coord x1, i4_coord y1,
  362. i4_coord x2, i4_coord y2,
  363. i4_color color, i4_draw_context_class &context)
  364. {
  365. w16 tcolor=i4_pal_man.convert_32_to(color, &pal->source);
  366. for (i4_rect_list_class::area_iter c=context.clip.list.begin();c!=context.clip.list.end();++c)
  367. {
  368. i4_coord lx1,ly1,lx2,ly2;
  369. if (x1<c->x1) lx1=c->x1; else lx1=x1;
  370. if (y1<c->y1) ly1=c->y1; else ly1=y1;
  371. if (x2>c->x2) lx2=c->x2; else lx2=x2;
  372. if (y2>c->y2) ly2=c->y2; else ly2=y2;
  373. if (!(lx1>lx2 || ly1>ly2))
  374. {
  375. w16 *d=paddr(lx1 + context.xoff, ly1+context.yoff);
  376. int count=lx2-lx1+1;
  377. add_dirty(lx1,ly1,lx2,ly2,context);
  378. for (;ly1<=ly2; ly1++)
  379. {
  380. for (int x=0; x<count; x++)
  381. d[x]=tcolor;
  382. d=(w16 *)((w8 *)d + bpl);
  383. }
  384. }
  385. }
  386. }