fill.ppi 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1993,97 by the Free Pascal development team.
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$ifopt S+}
  12. {$define StackCkeckOn}
  13. {$endif opt S+}
  14. procedure floodfill(x,y:integer; border:longint);
  15. var bordercol : longint;
  16. fillcol,fillbkcol : longint;
  17. viewport : viewporttype;
  18. offset : longint;
  19. test_bkfill : boolean;
  20. {$S+}
  21. { Fill is very recursive !! }
  22. { And it fails sometimes !! }
  23. procedure fill(x,y:integer);
  24. var start,ende,xx : integer;
  25. col : longint;
  26. begin
  27. {$ifdef GraphDebug}
  28. if (x>viewport.x2) or (x<viewport.x1) or
  29. (y>viewport.y2) or (y<viewport.y1) then
  30. begin
  31. Writeln(stderr,'Wrong value in Fill(',x,',',y,')');
  32. exit;
  33. end;
  34. {$endif def GraphDebug}
  35. xx:=x; col:=getpixeli(xx,y);
  36. {$ifdef GraphDebug}
  37. Writeln(stderr,'Fill ',x,' ',y,' ',hexstr(col,8));
  38. {$endif def GraphDebug}
  39. if (col=bordercol) or (col=fillcol) or
  40. (test_bkfill and (col=fillbkcol)) then
  41. exit;
  42. while (col<>bordercol) and (xx > viewport.x1) and
  43. (col<>fillcol) and (not test_bkfill or (col<>fillbkcol))
  44. do begin
  45. xx:=xx-1; col:=getpixeli(xx,y);
  46. end;
  47. if (col<>bordercol) and (col<>fillcol) and
  48. (not test_bkfill or (col<>fillbkcol)) then
  49. start:=xx
  50. else
  51. start:=xx+1;
  52. xx:=x;
  53. col:=getpixeli(xx,y);
  54. while (col<>bordercol) and (xx < viewport.x2) and (col<>fillcol)
  55. and (not test_bkfill or (col<>fillbkcol))
  56. do begin
  57. xx:=xx+1; col:=getpixeli(xx,y);
  58. end;
  59. if (col<>bordercol) and (col<>fillcol) and
  60. (not test_bkfill or (col<>fillbkcol)) then
  61. ende:=xx
  62. else
  63. ende:=xx-1;
  64. {$ifdef GraphDebug}
  65. Writeln(stderr,'Pattern ',start,' ',ende,' ',y);
  66. {$endif def GraphDebug}
  67. patternline(start,ende,y);
  68. {$ifdef GraphDebug}
  69. Writeln(stderr,'Fill after Patterline ',x,' ',y,' ',hexstr(getpixel(x,y),8));
  70. {$endif def GraphDebug}
  71. offset:=(y * _maxy + start) shr 8;
  72. if (y > viewport.y1)
  73. then begin
  74. xx:=start;
  75. repeat
  76. col:=getpixeli(xx,y-1);
  77. if (col<>bordercol) and (col<>fillcol) and
  78. (not test_bkfill or (col<>fillbkcol))
  79. then begin
  80. fill(xx,y-1);
  81. break;
  82. end;
  83. xx:=xx+1;
  84. until xx > ende;
  85. end;
  86. if (y<viewport.y2) then
  87. begin
  88. xx:=start;
  89. repeat
  90. col:=getpixeli(xx,y+1);
  91. if (col<>bordercol) and (col<>fillcol) and
  92. (not test_bkfill or (col<>fillbkcol)) then
  93. fill(xx,y+1);
  94. xx:=xx+1;
  95. until xx > ende;
  96. end;
  97. end;
  98. begin
  99. {$ifdef GraphDebug}
  100. Writeln(stderr,'FloodFill start ',x,' ',y);
  101. {$endif def GraphDebug}
  102. {$ifdef NOFILL}
  103. exit;
  104. {$endif NOFILL}
  105. {fillchar(buffermem^,buffersize,0);
  106. not used !! }
  107. if aktviewport.clip then viewport:=aktviewport else viewport:=aktscreen;
  108. { reject invalid points !! }
  109. viewport.x2:=viewport.x2-viewport.x1;
  110. viewport.y2:=viewport.y2-viewport.y1;
  111. viewport.x1:=0;
  112. viewport.y1:=0;
  113. if (x>viewport.x2) or (x<viewport.x1) or
  114. (y>viewport.y2) or (y<viewport.y1) then
  115. begin
  116. {$ifdef GraphDebug}
  117. Writeln(stderr,'Error Wrong values for FloodFill');
  118. Writeln(stderr,'xmax ',viewport.x2);
  119. Writeln(stderr,'ymax ',viewport.y2);
  120. {$endif def GraphDebug}
  121. exit;
  122. end;
  123. bordercol:=convert(border) and ColorMask;
  124. fillcol:=aktfillsettings.color and ColorMask;
  125. fillbkCol:=aktfillbkcolor and ColorMask;
  126. if aktfillsettings.pattern=emptyfill then
  127. begin
  128. fillcol:=fillbkcol;
  129. test_bkfill:=false;
  130. end
  131. else if aktfillsettings.pattern=solidfill then
  132. test_bkfill:=false
  133. else
  134. test_bkfill:=true;
  135. {$ifdef GraphDebug}
  136. Writeln(stderr,'FloodFill(',x,',',y,') Fillcol ',hexstr(unconvert(fillcol),8));
  137. Writeln(stderr,' bordercol ',hexstr(unconvert(bordercol),8),
  138. ' fillbkcol ',hexstr(unconvert(fillbkcol),8));
  139. {$endif def GraphDebug}
  140. fill(x,y);
  141. end;
  142. {$ifndef StackCkeckOn}
  143. {$S-} { return to normal state }
  144. {$else }
  145. {$undef StackCheckOn}
  146. {$endif }
  147. procedure GetFillSettings(var Fillinfo:Fillsettingstype);
  148. begin
  149. _graphresult:=grOk;
  150. if not isgraphmode then
  151. begin
  152. _graphresult:=grnoinitgraph;
  153. exit;
  154. end;
  155. Fillinfo:=aktfillsettings;
  156. Fillinfo.color:=unconvert(aktfillsettings.color);
  157. end;
  158. procedure GetFillPattern(var FillPattern:FillPatternType);
  159. begin
  160. _graphresult:=grOk;
  161. if not isgraphmode then
  162. begin
  163. _graphresult:=grnoinitgraph;
  164. exit;
  165. end;
  166. FillPattern:=aktfillpattern;
  167. end;
  168. procedure SetFillPattern(pattern : FillPatternType;color : longint);
  169. begin
  170. _graphresult:=grOk;
  171. if not isgraphmode then
  172. begin
  173. _graphresult:=grnoinitgraph;
  174. exit;
  175. end;
  176. fillpattern[12]:=pattern;
  177. SetFillStyle(12,color);
  178. end;
  179. procedure SetFillStyle(pattern : word ;color : longint);
  180. var i,j:Integer;
  181. mask:Byte;
  182. begin
  183. _graphresult:=grOk;
  184. if not isgraphmode then
  185. begin
  186. _graphresult:=grnoinitgraph;
  187. exit;
  188. end;
  189. { g�ltige Paramter ? }
  190. if (pattern<0) or (pattern>12) then
  191. begin
  192. _graphresult:=grError;
  193. exit;
  194. end;
  195. { Muster laden }
  196. aktfillpattern:=fillpattern[pattern];
  197. aktfillsettings.pattern:=pattern;
  198. aktfillsettings.color:=convert(color);
  199. aktfillbkcolor:=aktbackcolor;
  200. i:=1; j:=0;
  201. repeat
  202. mask:=$80;
  203. repeat
  204. if (aktfillpattern[i] and mask) = 0
  205. then PatternBuffer[j]:=aktbackcolor else PatternBuffer[j]:=aktfillsettings.color;
  206. mask:=mask shr 1;
  207. j:=j+1;
  208. until mask=0;
  209. i:=i+1;
  210. until i > 8;
  211. end;
  212. procedure GetLineSettings(var LineInfo : LineSettingsType);
  213. begin
  214. _graphresult:=grOk;
  215. if not isgraphmode then
  216. begin
  217. _graphresult:=grnoinitgraph;
  218. exit;
  219. end;
  220. lineinfo:=aktlineinfo;
  221. end;
  222. { this procedure is rather confuse
  223. but I admit that I wrote it by try-error !! PM }
  224. procedure FillPoly(points : word;var polypoints);
  225. {$R-}
  226. type PointTypeArray = Array[0..0] of PointType;
  227. { Used to find the horizontal lines that
  228. must be filled }
  229. TLineSegmentInfo = Record
  230. {range for check }
  231. ymin,ymax,
  232. { line equation consts }
  233. xcoef,ycoef,_const,
  234. lastvalue : longint;
  235. use_in_line : boolean;
  236. End;
  237. LineSegmentInfoArray = Array[0..0] of TLineSegmentInfo;
  238. var
  239. xmin,xmax,ymin,ymax : longint;
  240. x1,x2,y1,y2,y,xdeb : longint;
  241. i,j,curx,cury : longint;
  242. newvalue : longint;
  243. LineInfo : ^LineSegmentInfoArray;
  244. PreviousInside,inside,side : boolean;
  245. viewport : viewporttype;
  246. begin
  247. GetMem(LineInfo,(points+1)*SizeOf(TlineSegmentInfo));
  248. xmax:=$80000000;xmin:=$7fffffff;
  249. ymax:=$80000000;ymin:=$7fffffff;
  250. for i:=0 to points-1 do
  251. begin
  252. if i=points-1 then
  253. j:=0
  254. else
  255. j:=i+1;
  256. x1:=PointTypeArray(polypoints)[i].x;
  257. y1:=PointTypeArray(polypoints)[i].y;
  258. x2:=PointTypeArray(polypoints)[j].x;
  259. y2:=PointTypeArray(polypoints)[j].y;
  260. if x1>xmax then
  261. xmax:=x1;
  262. if x1<xmin then
  263. xmin:=x1;
  264. if y1>ymax then
  265. ymax:=y1;
  266. if y1<ymin then
  267. ymin:=y1;
  268. if y1<y2 then
  269. begin
  270. LineInfo^[i].ymin:=y1;
  271. LineInfo^[i].ymax:=y2;
  272. end
  273. else
  274. begin
  275. LineInfo^[i].ymin:=y2;
  276. LineInfo^[i].ymax:=y1;
  277. end;
  278. LineInfo^[i].xcoef:=y2-y1;
  279. LineInfo^[i].ycoef:=x1-x2;
  280. LineInfo^[i]._const:=y1*x2-x1*y2;
  281. end; { setting of LineInfo }
  282. side:=true;
  283. for i:=0 to points-1 do
  284. begin
  285. cury:=LineInfo^[i].ymin;
  286. newvalue:=LineInfo^[i].xcoef*(xmin-1)+
  287. LineInfo^[i].ycoef*cury+LineInfo^[i]._const;
  288. if (newvalue<0) then
  289. side:=not side;
  290. end;
  291. if aktviewport.clip then viewport:=aktviewport else viewport:=aktscreen;
  292. { reject invalid points !! }
  293. viewport.x2:=viewport.x2-viewport.x1;
  294. viewport.y2:=viewport.y2-viewport.y1;
  295. viewport.x1:=0;
  296. viewport.y1:=0;
  297. {$ifdef GraphDebug}
  298. Writeln(stderr,'Rectangle (',xmin,',',ymin,'),(',xmax,',',ymax,')');
  299. {$endif def GraphDebug}
  300. if xmin<0 then xmin:=0;
  301. if ymin<0 then ymin:=0;
  302. if xmax>viewport.x2 then xmax:=viewport.x2;
  303. if ymax>viewport.y2 then ymax:=viewport.y2;
  304. {$ifdef GraphDebug}
  305. Writeln(stderr,'Rectangle (',xmin,',',ymin,'),(',xmax,',',ymax,')');
  306. {$endif def GraphDebug}
  307. for cury:=ymin to ymax do
  308. begin
  309. xdeb:=xmin;
  310. PreviousInside:=true;
  311. for i:=0 to points-1 do
  312. begin
  313. if cury<LineInfo^[i].ymin then
  314. y:=LineInfo^[i].ymin
  315. else if cury>LineInfo^[i].ymax then
  316. y:=LineInfo^[i].ymax
  317. else
  318. y:=cury;
  319. newvalue:=LineInfo^[i].xcoef*(xmin-1)+
  320. LineInfo^[i].ycoef*y+LineInfo^[i]._const;
  321. LineInfo^[i].lastvalue:=newvalue;
  322. if (newvalue<0) then
  323. PreviousInside:=not PreviousInside;
  324. if (cury<LineInfo^[i].ymin) or (cury>=LineInfo^[i].ymax) then
  325. LineInfo^[i].use_in_line:=false
  326. else
  327. LineInfo^[i].use_in_line:=true;
  328. end;
  329. PreviousInside:=(side<>PreviousInside);
  330. inside:=PreviousInside;
  331. for curx:=xmin to xmax do
  332. begin
  333. for i:=0 to points-1 do
  334. if LineInfo^[i].use_in_line then
  335. begin
  336. newvalue:=LineInfo^[i].lastvalue+LineInfo^[i].xcoef;
  337. if ((LineInfo^[i].lastvalue<0) and (newvalue>=0)) or
  338. ((LineInfo^[i].lastvalue>0) and (newvalue<=0)) then
  339. begin
  340. inside:=not inside;
  341. {$ifdef GraphDebug}
  342. Writeln(stderr,'Line ',i,' crossed (',curx,',',cury,')');
  343. Writeln(stderr,'Line x*',LineInfo^[i].xcoef,'+y*',
  344. LineInfo^[i].ycoef,'+',LineInfo^[i]._const,'=0');
  345. Writeln(stderr,'Old ',LineInfo^[i].lastvalue,' new ',newvalue);
  346. {$endif def GraphDebug}
  347. end;
  348. LineInfo^[i].lastvalue:=newvalue;
  349. end;
  350. if inside<>PreviousInside then
  351. if inside then
  352. xdeb:=curx
  353. else
  354. begin
  355. patternline(xdeb,curx,cury);
  356. {$ifdef GraphDebug}
  357. Writeln(stderr,'Pattern (',xdeb,',',curx,') at ',cury);
  358. {$endif def GraphDebug}
  359. end;
  360. PreviousInside:=inside;
  361. end;
  362. if inside then
  363. begin
  364. patternline(xdeb,xmax,cury);
  365. {$ifdef GraphDebug}
  366. Writeln(stderr,'Pattern (',xdeb,',',xmax,') at ',cury);
  367. {$endif def GraphDebug}
  368. end;
  369. end;
  370. FreeMem(LineInfo,(points+1)*SizeOf(TlineSegmentInfo));
  371. { simply call drawpoly instead (PM) }
  372. DrawPoly(points,polypoints);
  373. end;
  374. {
  375. $Log$
  376. Revision 1.8 1998-11-25 22:59:24 pierre
  377. * fillpoly works
  378. Revision 1.7 1998/11/25 13:04:44 pierre
  379. + added multi page support
  380. Revision 1.6 1998/11/20 18:42:07 pierre
  381. * many bugs related to floodfill and ellipse fixed
  382. Revision 1.5 1998/11/19 15:09:37 pierre
  383. * several bugfixes for sector/ellipse/floodfill
  384. + graphic driver mode const in interface G800x600x256...
  385. + added backput mode as in linux graph.pp
  386. (clears the background of textoutput)
  387. Revision 1.4 1998/11/19 09:48:48 pierre
  388. + added some functions missing like sector ellipse getarccoords
  389. (the filling of sector and ellipse is still buggy
  390. I use floodfill but sometimes the starting point
  391. is outside !!)
  392. * fixed a bug in floodfill for patterns
  393. (still has problems !!)
  394. Revision 1.3 1998/11/18 13:23:34 pierre
  395. * floodfill got into an infinite loop !!
  396. + added partial support for fillpoly
  397. (still wrong if the polygon is not convex)
  398. Simply make a floodfill from the barycenter !
  399. * some 24BPP code changed (still does not work for my S3VBE program !)
  400. Revision 1.2 1998/11/18 09:31:33 pierre
  401. * changed color scheme
  402. all colors are in RGB format if more than 256 colors
  403. + added 24 and 32 bits per pixel mode
  404. (compile with -dDEBUG)
  405. 24 bit mode with banked still as problems on pixels across
  406. the bank boundary, but works in LinearFrameBufferMode
  407. Look at install/demo/nmandel.pp
  408. Revision 1.1.1.1 1998/03/25 11:18:42 root
  409. * Restored version
  410. Revision 1.3 1998/01/26 11:57:57 michael
  411. + Added log at the end
  412. Working file: rtl/dos/ppi/fill.ppi
  413. description:
  414. ----------------------------
  415. revision 1.2
  416. date: 1997/12/01 12:21:29; author: michael; state: Exp; lines: +13 -1
  417. + added copyright reference in header.
  418. ----------------------------
  419. revision 1.1
  420. date: 1997/11/27 08:33:51; author: michael; state: Exp;
  421. Initial revision
  422. ----------------------------
  423. revision 1.1.1.1
  424. date: 1997/11/27 08:33:51; author: michael; state: Exp; lines: +0 -0
  425. FPC RTL CVS start
  426. =============================================================================
  427. }