WMGraphicUtilities.Mod 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. MODULE WMGraphicUtilities; (** AUTHOR "TF"; PURPOSE "Tools using WMGraphics"; *)
  2. IMPORT
  3. WMGraphics, WMRectangles, Strings;
  4. TYPE
  5. EllipsePixelsFiller* = PROCEDURE(CONST canvas : WMGraphics.Canvas; rect : WMRectangles.Rectangle; dx, dy : LONGINT; lineColor, fillColor : WMGraphics.Color; mode : LONGINT);
  6. (* factor in 1/256, alpha remains unchanged *)
  7. PROCEDURE ScaleColor*(color : LONGINT; factor : LONGINT): LONGINT;
  8. VAR r, g, b, a : LONGINT;
  9. BEGIN
  10. WMGraphics.ColorToRGBA(color, r, g, b, a);
  11. r := Strings.Min(r * factor DIV 256, 255);
  12. g := Strings.Min(g * factor DIV 256, 255);
  13. b := Strings.Min(b * factor DIV 256, 255);
  14. RETURN WMGraphics.RGBAToColor(r, g, b, a)
  15. END ScaleColor;
  16. (** linear interpolation percent in [0..256] *)
  17. PROCEDURE InterpolateLinear*(a, b, percent : LONGINT) : LONGINT;
  18. BEGIN
  19. RETURN ((a * (256 - percent)) + b * percent) DIV 256
  20. END InterpolateLinear;
  21. (* interpolate between two colors; percent [0..256]*)
  22. PROCEDURE InterpolateColorLinear*(cl0, cl1, percent : LONGINT) : LONGINT;
  23. VAR r0, g0, b0, a0, r1, g1, b1, a1: LONGINT;
  24. BEGIN
  25. WMGraphics.ColorToRGBA(cl0, r0, g0, b0, a0);
  26. WMGraphics.ColorToRGBA(cl1, r1, g1, b1, a1);
  27. RETURN WMGraphics.RGBAToColor(InterpolateLinear(r0, r1, percent),
  28. InterpolateLinear(g0, g1, percent),
  29. InterpolateLinear(b0, b1, percent),
  30. InterpolateLinear(a0, a1, percent))
  31. END InterpolateColorLinear;
  32. (** Draw a 3d effect border *)
  33. PROCEDURE DrawBevel*(canvas : WMGraphics.Canvas; rect : WMRectangles.Rectangle; borderWidth : LONGINT; down : BOOLEAN; color, mode : LONGINT);
  34. VAR i, ul, dr : LONGINT;
  35. BEGIN
  36. IF down THEN ul := ScaleColor(color, 128); dr := ScaleColor(color, 256 + 128)
  37. ELSE dr := ScaleColor(color, 128); ul := ScaleColor(color, 256 + 128)
  38. END;
  39. FOR i := 0 TO borderWidth - 1 DO
  40. canvas.Fill(WMRectangles.MakeRect(rect.l + i , rect.t + i, rect.r - i, rect.t + i + 1), ul, mode);
  41. canvas.Fill(WMRectangles.MakeRect(rect.l + i, rect.t + i + 1, rect.l + i + 1, rect.b - i), ul, mode);
  42. canvas.Fill(WMRectangles.MakeRect(rect.l + 1 + i, rect.b - 1 - i, rect.r - i, rect.b - i), dr, mode);
  43. canvas.Fill(WMRectangles.MakeRect(rect.r - 1 - i, rect.t + 1 + i, rect.r - i, rect.b - i - 1), dr, mode)
  44. END
  45. END DrawBevel;
  46. (** Draw a 3d effect panel *)
  47. PROCEDURE DrawBevelPanel*(canvas : WMGraphics.Canvas; rect : WMRectangles.Rectangle; borderWidth : LONGINT; down : BOOLEAN; color, mode : LONGINT);
  48. BEGIN
  49. canvas.Fill(WMRectangles.ResizeRect(rect, -1), color, mode);
  50. DrawBevel(canvas, rect, borderWidth, down, color, mode)
  51. END DrawBevelPanel;
  52. PROCEDURE FillGradientHorizontal*(canvas : WMGraphics.Canvas; rect : WMRectangles.Rectangle; clLeft, clRight, mode : LONGINT);
  53. VAR dist, cl, i, f : LONGINT;
  54. BEGIN
  55. dist := rect.r - rect.l;
  56. FOR i := 0 TO dist - 1 DO
  57. f := ENTIER(256 * i / dist);
  58. cl := InterpolateColorLinear(clLeft, clRight, f);
  59. canvas.Fill(WMRectangles.MakeRect(rect.l + i, rect.t, rect.l + i + 1, rect.b), cl, mode)
  60. END;
  61. END FillGradientHorizontal;
  62. PROCEDURE FillGradientVertical*(canvas : WMGraphics.Canvas; rect : WMRectangles.Rectangle; clTop, clBottom, mode : LONGINT);
  63. VAR dist, cl, i, f : LONGINT;
  64. BEGIN
  65. dist := rect.b - rect.t;
  66. FOR i := 0 TO dist - 1 DO
  67. f := ENTIER(256 * i / dist);
  68. cl := InterpolateColorLinear(clTop, clBottom, f);
  69. canvas.Fill(WMRectangles.MakeRect(rect.l, rect.t + i, rect.r, rect.t + i + 1), cl, mode)
  70. END;
  71. END FillGradientVertical;
  72. PROCEDURE FillRoundHorizontalBar*(canvas : WMGraphics.Canvas; rect : WMRectangles.Rectangle; down : BOOLEAN; color, mode : LONGINT);
  73. VAR cl2, d : LONGINT;
  74. BEGIN
  75. cl2 := ScaleColor(color, 200);
  76. IF down THEN d := (rect.b - rect.t) * 5 DIV 16;
  77. ELSE d := (rect.b - rect.t) * 11 DIV 16
  78. END;
  79. FillGradientVertical(canvas, WMRectangles.MakeRect(rect.l, rect.t, rect.r, rect.t + d), color, cl2, WMGraphics.ModeCopy);
  80. FillGradientVertical(canvas, WMRectangles.MakeRect(rect.l, rect.t + d, rect.r, rect.b), cl2, color, WMGraphics.ModeCopy);
  81. END FillRoundHorizontalBar;
  82. PROCEDURE FillRoundVerticalBar*(canvas : WMGraphics.Canvas; rect : WMRectangles.Rectangle; down : BOOLEAN; color, mode : LONGINT);
  83. VAR cl2, d : LONGINT;
  84. BEGIN
  85. cl2 := ScaleColor(color, 200);
  86. IF down THEN d := (rect.r - rect.l) * 5 DIV 16;
  87. ELSE d := (rect.r - rect.l) * 11 DIV 16
  88. END;
  89. FillGradientHorizontal(canvas, WMRectangles.MakeRect(rect.l, rect.t, rect.l + d, rect.b), color, cl2, WMGraphics.ModeCopy);
  90. FillGradientHorizontal(canvas, WMRectangles.MakeRect(rect.l + d, rect.t, rect.r, rect.b), cl2, color, WMGraphics.ModeCopy);
  91. END FillRoundVerticalBar;
  92. PROCEDURE DrawRect*(canvas : WMGraphics.Canvas; r : WMRectangles.Rectangle; color : WMGraphics.Color; mode : LONGINT);
  93. BEGIN
  94. canvas.Fill(WMRectangles.MakeRect(r.l, r.t, r.r, r.t + 1), color, mode);
  95. canvas.Fill(WMRectangles.MakeRect(r.l, r.t, r.l + 1, r.b), color, mode);
  96. canvas.Fill(WMRectangles.MakeRect(r.l, r.b - 1, r.r, r.b), color, mode);
  97. canvas.Fill(WMRectangles.MakeRect(r.r - 1, r.t, r.r, r.b), color, mode)
  98. END DrawRect;
  99. PROCEDURE RectGlassShade*(canvas : WMGraphics.Canvas; rect : WMRectangles.Rectangle; borderWidth : LONGINT; down : BOOLEAN);
  100. VAR i, ul, dr, da, w : LONGINT;
  101. BEGIN
  102. IF borderWidth <= 0 THEN RETURN END;
  103. IF down THEN ul := 090H; dr := LONGINT(0FFFFFF90H)
  104. ELSE dr := 090H; ul := LONGINT(0FFFFFF90H)
  105. END;
  106. da := 90H DIV borderWidth;
  107. FOR i := 0 TO borderWidth - 1 DO
  108. (* top *)
  109. canvas.Fill(WMRectangles.MakeRect(rect.l + i , rect.t + i, rect.r - i, rect.t + i + 1), ul, WMGraphics.ModeSrcOverDst);
  110. (* left *)
  111. canvas.Fill(WMRectangles.MakeRect(rect.l + i, rect.t + i + 1, rect.l + i + 1, rect.b - i), ul, WMGraphics.ModeSrcOverDst);
  112. (* bottom *)
  113. canvas.Fill(WMRectangles.MakeRect(rect.l + 1 + i, rect.b - 1 - i, rect.r - i, rect.b - i), dr, WMGraphics.ModeSrcOverDst);
  114. (* right *)
  115. canvas.Fill(WMRectangles.MakeRect(rect.r - 1 - i, rect.t + 1 + i, rect.r - i, rect.b - i - 1), dr, WMGraphics.ModeSrcOverDst);
  116. DEC(ul, da); DEC(dr, da)
  117. END;
  118. i := 3; ul := LONGINT(0FFFFFF40H); w := 5;
  119. canvas.Fill(WMRectangles.MakeRect(rect.l + i , rect.t + i, rect.l + i + w, rect.t + i + 2), ul, WMGraphics.ModeSrcOverDst);
  120. canvas.Fill(WMRectangles.MakeRect(rect.l + i, rect.t + i, rect.l + i + 2, rect.t + i + w), ul, WMGraphics.ModeSrcOverDst);
  121. END RectGlassShade;
  122. PROCEDURE ExtRectGlassShade*(canvas : WMGraphics.Canvas; rect : WMRectangles.Rectangle; openSides : SET; borderWidth : LONGINT; down : BOOLEAN);
  123. VAR i, ul, dr, da, w, a, b, c, d : LONGINT;
  124. BEGIN
  125. IF borderWidth <= 0 THEN RETURN END;
  126. IF down THEN ul := 090H; dr := LONGINT(0FFFFFF90H)
  127. ELSE dr := 090H; ul := LONGINT(0FFFFFF90H)
  128. END;
  129. da := 90H DIV borderWidth;
  130. FOR i := 0 TO borderWidth - 1 DO
  131. IF (0 IN openSides) THEN a := 0 ELSE a := i END;
  132. IF (1 IN openSides) THEN b := 0 ELSE b := i + 1 END;
  133. IF (2 IN openSides) THEN c := 0 ELSE c := i END;
  134. IF (3 IN openSides) THEN d := 0 ELSE d := i + 1 END;
  135. (* top *)
  136. IF ~(0 IN openSides) THEN canvas.Fill(WMRectangles.MakeRect(rect.l + b , rect.t + i, rect.r - d, rect.t + i + 1), ul, WMGraphics.ModeSrcOverDst) END;
  137. (* left *)
  138. IF ~(1 IN openSides) THEN canvas.Fill(WMRectangles.MakeRect(rect.l + i, rect.t + a, rect.l + i + 1, rect.b - c), ul, WMGraphics.ModeSrcOverDst) END;
  139. (* bottom *)
  140. IF ~(2 IN openSides) THEN canvas.Fill(WMRectangles.MakeRect(rect.l + b, rect.b - 1 - i, rect.r - d, rect.b - i), dr, WMGraphics.ModeSrcOverDst) END;
  141. (* right *)
  142. IF ~(3 IN openSides) THEN canvas.Fill(WMRectangles.MakeRect(rect.r - 1 - i, rect.t + a, rect.r - i, rect.b - c), dr, WMGraphics.ModeSrcOverDst) END;
  143. DEC(ul, da); DEC(dr, da)
  144. END;
  145. i := 3; ul := LONGINT(0FFFFFF40H); w := 5;
  146. (* canvas.Fill(WMRectangles.MakeRect(rect.l + i , rect.t + i, rect.l + i + w, rect.t + i + 2), ul, WMGraphics.ModeSrcOverDst);
  147. canvas.Fill(WMRectangles.MakeRect(rect.l + i, rect.t + i, rect.l + i + 2, rect.t + i + w), ul, WMGraphics.ModeSrcOverDst);
  148. *)
  149. END ExtRectGlassShade;
  150. (** repeats img in x-direction and scales it in y-direction to fill the specified rectangle *)
  151. PROCEDURE RepeatImageHorizontal*(canvas : WMGraphics.Canvas; x, y, dx, dy : LONGINT; img : WMGraphics.Image);
  152. VAR i : LONGINT;
  153. BEGIN
  154. i := dx DIV img.width + 1;
  155. canvas.SetClipRect(WMRectangles.MakeRect(0, 0, x+dx, canvas.clipRect.b));
  156. WHILE i > 0 DO
  157. canvas.ScaleImage(img,
  158. WMRectangles.MakeRect(0, 0, img.width, img.height),
  159. WMRectangles.MakeRect(x, y, x+img.width, y+dy),
  160. WMGraphics.ModeSrcOverDst, 10);
  161. INC(x, img.width);
  162. DEC(i)
  163. END;
  164. END RepeatImageHorizontal;
  165. (** repeats img as often as necessairy to fill an area with height dy starting at (x,y) *)
  166. PROCEDURE RepeatImageVertical*(canvas : WMGraphics.Canvas; x, y, dx, dy : LONGINT; img : WMGraphics.Image);
  167. VAR i : LONGINT;
  168. BEGIN
  169. i := dy DIV img.height + 1;
  170. canvas.SetClipRect(WMRectangles.MakeRect(0, 0, canvas.clipRect.r, y+dy));
  171. WHILE i > 0 DO
  172. canvas.ScaleImage(img,
  173. WMRectangles.MakeRect(0, 0, img.width, img.height),
  174. WMRectangles.MakeRect(x, y, x+dx, y+img.height),
  175. WMGraphics.ModeSrcOverDst, 10);
  176. INC(y, img.height);
  177. DEC(i)
  178. END
  179. END RepeatImageVertical;
  180. PROCEDURE Circle*(CONST c: WMGraphics.Canvas; CX, CY, R : LONGINT);
  181. VAR
  182. X, Y : LONGINT;
  183. XChange, YChange : LONGINT;
  184. RadiusError : LONGINT;
  185. BEGIN
  186. X := R;
  187. Y := 0;
  188. XChange := 1- 2*R;
  189. YChange := 1;
  190. RadiusError := 0;
  191. WHILE ( X>= Y ) DO
  192. c.Fill(WMGraphics.MakeRectangle(CX+X, CY+Y,CX+X+1,CY+Y+1),c.color,1);
  193. c.Fill(WMGraphics.MakeRectangle(CX-X, CY+Y,CX-X+1, CY+Y+1),c.color,1);
  194. c.Fill(WMGraphics.MakeRectangle(CX-X, CY-Y,CX-X+1, CY-Y+1),c.color,1);
  195. c.Fill(WMGraphics.MakeRectangle(CX+X, CY-Y,CX+X+1, CY-Y+1),c.color,1);
  196. c.Fill(WMGraphics.MakeRectangle(CX+Y, CY+X,CX+Y+1,CY+X+1),c.color,1);
  197. c.Fill(WMGraphics.MakeRectangle(CX-Y, CY+X,CX-Y+1, CY+X+1),c.color,1);
  198. c.Fill(WMGraphics.MakeRectangle(CX-Y, CY-X,CX-Y+1, CY-X+1),c.color,1);
  199. c.Fill(WMGraphics.MakeRectangle(CX+Y, CY-X,CX+Y+1, CY-X+1),c.color,1);
  200. INC(Y);
  201. INC(RadiusError, YChange);
  202. INC(YChange,2);
  203. IF ( 2*RadiusError + XChange > 0 ) THEN
  204. DEC(X);
  205. INC(RadiusError, XChange);
  206. INC(XChange,2);
  207. END;
  208. END;
  209. END Circle;
  210. (* Bresenham Type Algorithm For Drawing Ellipses *)
  211. PROCEDURE Ellipse*(CONST c: WMGraphics.Canvas; CX, CY, XRadius, YRadius : LONGINT);
  212. VAR
  213. X, Y : LONGINT;
  214. XChange, YChange : LONGINT;
  215. EllipseError : LONGINT;
  216. TwoASquare, TwoBSquare : LONGINT;
  217. StoppingX, StoppingY : LONGINT;
  218. BEGIN
  219. TwoASquare := 2*XRadius*XRadius;
  220. TwoBSquare := 2*YRadius*YRadius;
  221. X := XRadius;
  222. Y := 0;
  223. XChange := YRadius*YRadius*(1-2*XRadius);
  224. YChange := XRadius*XRadius;
  225. EllipseError := 0;
  226. StoppingX := TwoBSquare*XRadius;
  227. StoppingY := 0;
  228. WHILE ( StoppingX>= StoppingY ) DO (* 1st set of points, y>1 *)
  229. c.Fill(WMGraphics.MakeRectangle(CX+X, CY+Y-1,CX+X+1,CY+Y+1),c.color,1); (*point in quadrant 1*)
  230. c.Fill(WMGraphics.MakeRectangle(CX-X, CY+Y-1,CX-X+1, CY+Y+1),c.color,1); (*point in quadrant 2*)
  231. c.Fill(WMGraphics.MakeRectangle(CX-X, CY-Y-1,CX-X+1, CY-Y+1),c.color,1); (*point in quadrant 3*)
  232. c.Fill(WMGraphics.MakeRectangle(CX+X, CY-Y-1,CX+X+1, CY-Y+1),c.color,1); (*point in quadrant 4*)
  233. INC(Y);
  234. INC(StoppingY, TwoASquare);
  235. INC(EllipseError, YChange);
  236. INC(YChange,TwoASquare);
  237. IF ((2*EllipseError + XChange) > 0 ) THEN
  238. DEC(X);
  239. DEC(StoppingX, TwoBSquare);
  240. INC(EllipseError, XChange);
  241. INC(XChange,TwoBSquare)
  242. END;
  243. END;
  244. (* 1st point set is done; start the 2nd set of points *)
  245. X := 0;
  246. Y := YRadius;
  247. XChange := YRadius*YRadius;
  248. YChange := XRadius*XRadius*(1-2*YRadius);
  249. EllipseError := 0;
  250. StoppingX := 0;
  251. StoppingY := TwoASquare*YRadius;
  252. WHILE ( StoppingX<= StoppingY ) DO (*2nd set of points, y < 1*)
  253. c.Fill(WMGraphics.MakeRectangle(CX+X, CY+Y,CX+X+1,CY+Y+1),c.color,1); (*point in quadrant 1*)
  254. c.Fill(WMGraphics.MakeRectangle(CX-X, CY+Y,CX-X+1, CY+Y+1),c.color,1); (*point in quadrant 2*)
  255. c.Fill(WMGraphics.MakeRectangle(CX-X, CY-Y,CX-X+1, CY-Y+1),c.color,1); (*point in quadrant 3*)
  256. c.Fill(WMGraphics.MakeRectangle(CX+X, CY-Y,CX+X+1, CY-Y+1),c.color,1); (*point in quadrant 4*)
  257. INC(X);
  258. INC(StoppingX, TwoBSquare);
  259. INC(EllipseError, XChange);
  260. INC(XChange,TwoBSquare);
  261. IF ((2*EllipseError + YChange) > 0 ) THEN
  262. DEC(Y);
  263. DEC(StoppingY, TwoASquare);
  264. INC(EllipseError, YChange);
  265. INC(YChange,TwoASquare)
  266. END;
  267. END;
  268. END Ellipse;
  269. PROCEDURE DrawRoundRect*(CONST canvas : WMGraphics.Canvas; rect : WMRectangles.Rectangle; rx, ry : LONGINT; lineColor : WMGraphics.Color; mode : LONGINT);
  270. VAR innerRect : WMRectangles.Rectangle;
  271. BEGIN
  272. IF (lineColor = WMGraphics.Transparent) THEN RETURN END;
  273. IF (rect.r <= rect.l) OR (rect.b <= rect.t) OR (rx <= 0) OR (ry <= 0) THEN RETURN END;
  274. (* Set coordinates to reflect the centers of 4 quarter circles *)
  275. innerRect := rect;
  276. INC(innerRect.l, rx); INC(innerRect.t, ry); DEC(innerRect.r, rx); DEC(innerRect.b, ry);
  277. IF (innerRect.r < innerRect.l) OR (innerRect.b < innerRect.t) THEN RETURN END;
  278. EllipseBresenham(canvas, innerRect, rx, ry, DrawEllipsePixels, lineColor, WMGraphics.Transparent, mode);
  279. INC(innerRect.l, 1); INC(innerRect.t, 1); DEC(innerRect.r, 1); DEC(innerRect.b, 1);
  280. canvas.Fill(WMRectangles.MakeRect(innerRect.l, rect.t, innerRect.r, rect.t + 1), lineColor, mode);
  281. canvas.Fill(WMRectangles.MakeRect(rect.l, innerRect.t, rect.l + 1, innerRect.b), lineColor, mode);
  282. canvas.Fill(WMRectangles.MakeRect(innerRect.l, rect.b - 1, innerRect.r, rect.b), lineColor, mode);
  283. canvas.Fill(WMRectangles.MakeRect(rect.r-1, innerRect.t, rect.r, innerRect.b), lineColor, mode);
  284. END DrawRoundRect;
  285. PROCEDURE FillRoundRect*(CONST canvas : WMGraphics.Canvas; rect : WMRectangles.Rectangle; rx, ry : LONGINT; lineColor, fillColor : WMGraphics.Color; mode : LONGINT);
  286. VAR innerRect : WMRectangles.Rectangle;
  287. BEGIN
  288. IF (lineColor = fillColor) & (lineColor = WMGraphics.Transparent) THEN RETURN END;
  289. IF (rect.r <= rect.l) OR (rect.b <= rect.t) OR (rx <= 0) OR (ry <= 0) THEN RETURN END;
  290. (* Set coordinates to reflect the centers of 4 quarter circles *)
  291. innerRect := rect;
  292. INC(innerRect.l, rx); INC(innerRect.t, ry); DEC(innerRect.r, rx); DEC(innerRect.b, ry);
  293. IF (innerRect.r < innerRect.l) OR (innerRect.b < innerRect.t) THEN RETURN END;
  294. (*IF lineColor = WMGraphics.Transparent THEN lineColor := fillColor; END;*)
  295. IF (lineColor # fillColor) & (lineColor # WMGraphics.Transparent) THEN (* draw rect *)
  296. DEC(rect.r); (* skip for filling part *)
  297. canvas.Fill(WMRectangles.MakeRect(innerRect.l, rect.t, innerRect.r, rect.t + 1), lineColor, mode);
  298. canvas.Fill(WMRectangles.MakeRect(rect.l, innerRect.t + 1, rect.l+1, innerRect.b - 1), lineColor, mode);
  299. canvas.Fill(WMRectangles.MakeRect(innerRect.l, rect.b - 1, innerRect.r, rect.b), lineColor, mode);
  300. canvas.Fill(WMRectangles.MakeRect(rect.r, innerRect.t + 1, rect.r+1, innerRect.b - 1), lineColor, mode);
  301. INC(rect.l); (* skip for filling part *)
  302. END;
  303. IF fillColor = WMGraphics.Transparent THEN (* draw round corners *)
  304. EllipseBresenham(canvas, innerRect, rx, ry, DrawEllipsePixels, lineColor, fillColor, mode);
  305. ELSE (* filling part -- fill round corners, fill center rect *)
  306. canvas.Fill(WMRectangles.MakeRect(rect.l, innerRect.t + 1, rect.r, innerRect.b-1), fillColor, mode);
  307. EllipseBresenham(canvas, innerRect, rx, ry, FillSolidEllipsePixels, lineColor, fillColor, mode);
  308. END;
  309. END FillRoundRect;
  310. PROCEDURE DrawEllipsePixels(CONST canvas : WMGraphics.Canvas; rect : WMRectangles.Rectangle; dx, dy : LONGINT; lineColor, unused : WMGraphics.Color; mode : LONGINT);
  311. BEGIN
  312. IF lineColor # WMGraphics.Transparent THEN
  313. canvas.Fill(WMRectangles.MakeRect(rect.l-dx, rect.t-dy, rect.l-dx+1, rect.t-dy+1), lineColor, mode);
  314. canvas.Fill(WMRectangles.MakeRect(rect.r+dx-1, rect.t-dy, rect.r+dx, rect.t-dy+1), lineColor, mode);
  315. canvas.Fill(WMRectangles.MakeRect(rect.l-dx, rect.b+dy-1, rect.l-dx+1, rect.b+dy), lineColor, mode);
  316. canvas.Fill(WMRectangles.MakeRect(rect.r+dx-1, rect.b+dy-1, rect.r+dx, rect.b+dy), lineColor, mode);
  317. END;
  318. END DrawEllipsePixels;
  319. PROCEDURE FillSolidEllipsePixels(CONST canvas : WMGraphics.Canvas; rect : WMRectangles.Rectangle; dx, dy : LONGINT; lineColor, fillColor : WMGraphics.Color; mode : LONGINT);
  320. BEGIN
  321. IF (lineColor # fillColor) & (lineColor # WMGraphics.Transparent) THEN
  322. DEC( rect.r ); DEC( rect.b ); (* skip for filling part *)
  323. canvas.Fill(WMRectangles.MakeRect(rect.l-dx, rect.t-dy, rect.l-dx+1, rect.t-dy+1), lineColor, mode);
  324. canvas.Fill(WMRectangles.MakeRect(rect.r+dx, rect.t-dy, rect.r+dx+1, rect.t-dy+1), lineColor, mode);
  325. canvas.Fill(WMRectangles.MakeRect(rect.l-dx, rect.b+dy, rect.l-dx+1, rect.b+dy+1), lineColor, mode);
  326. canvas.Fill(WMRectangles.MakeRect(rect.r+dx, rect.b+dy, rect.r+dx+1, rect.b+dy+1), lineColor, mode);
  327. INC( rect.l ); (* skip for filling part *)
  328. END;
  329. IF fillColor # WMGraphics.Transparent THEN (* filling part *)
  330. canvas.Fill(WMRectangles.MakeRect(rect.l-dx, rect.t-dy, rect.r+dx, rect.t-dy+1), fillColor, mode);
  331. canvas.Fill(WMRectangles.MakeRect(rect.l-dx, rect.b+dy, rect.r+dx, rect.b+dy+1), fillColor, mode);
  332. END;
  333. END FillSolidEllipsePixels;
  334. PROCEDURE EllipseBresenham(CONST canvas : WMGraphics.Canvas; innerRect : WMRectangles.Rectangle; rx, ry : LONGINT; drawPoints : EllipsePixelsFiller; lineColor, fillColor : WMGraphics.Color; mode : LONGINT);
  335. VAR
  336. X, Y, prevDistance : LONGINT;
  337. XChange, YChange : LONGINT;
  338. RadiusError : LONGINT;
  339. TwoASquare, TwoBSquare : LONGINT;
  340. StoppingX, StoppingY : LONGINT;
  341. BEGIN
  342. RadiusError := 0;
  343. IF lineColor = WMGraphics.Transparent THEN lineColor := fillColor; END;
  344. IF rx = ry THEN (* circle *)
  345. X := rx;
  346. prevDistance := rx;
  347. Y := 0;
  348. XChange := 1 - 2 * rx;
  349. YChange := 1;
  350. drawPoints(canvas, innerRect, X, Y, lineColor, fillColor, mode); (* start points *)
  351. WHILE ( Y < X ) DO
  352. IF (X = prevDistance) THEN (* skip fill *)
  353. drawPoints(canvas, innerRect, Y, X, lineColor, WMGraphics.Transparent, mode);
  354. ELSE
  355. drawPoints(canvas, innerRect, Y, X, lineColor, fillColor, mode);
  356. END;
  357. prevDistance := X; (* save value *)
  358. INC(RadiusError, YChange);
  359. INC(YChange,2);
  360. IF (2*RadiusError + XChange > 0) THEN
  361. DEC(X);
  362. INC(RadiusError, XChange);
  363. INC(XChange,2);
  364. END;
  365. INC(Y);
  366. drawPoints(canvas, innerRect, X, Y, lineColor, fillColor, mode);
  367. END;
  368. ELSE
  369. X := rx;
  370. Y := 0;
  371. TwoASquare := 2*rx*rx;
  372. TwoBSquare := 2*ry*ry;
  373. XChange := ry*ry*(1-2*rx);
  374. YChange := rx*rx;
  375. StoppingX := TwoBSquare*rx;
  376. StoppingY := 0;
  377. WHILE ( StoppingX >= StoppingY ) DO (* 1st set of points, y > 1 *)
  378. drawPoints(canvas, innerRect, X, Y, lineColor, fillColor, mode);
  379. INC(StoppingY, TwoASquare);
  380. INC(RadiusError, YChange);
  381. INC(YChange,TwoASquare);
  382. IF ((2*RadiusError + XChange) > 0 ) THEN
  383. DEC(X);
  384. DEC(StoppingX, TwoBSquare);
  385. INC(RadiusError, XChange);
  386. INC(XChange,TwoBSquare);
  387. END;
  388. INC(Y);
  389. END;
  390. (* 1st point set is done; start the 2nd set of points *)
  391. X := 0;
  392. Y := ry;
  393. prevDistance := ry;
  394. XChange := ry*ry;
  395. YChange := rx*rx*(1-2*ry);
  396. RadiusError := 0;
  397. StoppingX := 0;
  398. StoppingY := TwoASquare*ry;
  399. WHILE ( StoppingX < StoppingY ) DO (*2nd set of points, y < 1*)
  400. IF (Y = prevDistance) THEN (* skip fill *)
  401. drawPoints(canvas, innerRect, X, Y, lineColor, WMGraphics.Transparent, mode);
  402. ELSE
  403. drawPoints(canvas, innerRect, X, Y, lineColor, fillColor, mode);
  404. END;
  405. prevDistance := Y;
  406. INC(StoppingX, TwoBSquare);
  407. INC(RadiusError, XChange);
  408. INC(XChange,TwoBSquare);
  409. IF ((2*RadiusError + YChange) > 0 ) THEN
  410. DEC(Y);
  411. DEC(StoppingY, TwoASquare);
  412. INC(RadiusError, YChange);
  413. INC(YChange,TwoASquare);
  414. END;
  415. INC(X);
  416. END;
  417. END;
  418. END EllipseBresenham;
  419. END WMGraphicUtilities.