fppixlcanv.pp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2003 by the Free Pascal development team
  4. TPixelCanvas class.
  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. {$mode objfpc}{$h+}
  12. unit FPPixlCanv;
  13. interface
  14. uses classes, FPImage, FPCanvas, PixTools, ellipses;
  15. type
  16. { need still to be implemented in descendants :
  17. GetColor / SetColor
  18. Get/Set Width/Height
  19. }
  20. PixelCanvasException = class (TFPCanvasException);
  21. TFPPixelCanvas = class (TFPCustomCanvas)
  22. private
  23. FHashWidth : word;
  24. FRelativeBI : boolean;
  25. protected
  26. function DoCreateDefaultFont : TFPCustomFont; override;
  27. function DoCreateDefaultPen : TFPCustomPen; override;
  28. function DoCreateDefaultBrush : TFPCustomBrush; override;
  29. procedure DoTextOut (x,y:integer;text:string); override;
  30. procedure DoGetTextSize (text:string; var w,h:integer); override;
  31. function DoGetTextHeight (text:string) : integer; override;
  32. function DoGetTextWidth (text:string) : integer; override;
  33. procedure DoRectangle (const Bounds:TRect); override;
  34. procedure DoRectangleFill (const Bounds:TRect); override;
  35. procedure DoEllipseFill (const Bounds:TRect); override;
  36. procedure DoEllipse (const Bounds:TRect); override;
  37. procedure DoPolygonFill (const points:array of TPoint); override;
  38. procedure DoPolygon (const points:array of TPoint); override;
  39. procedure DoPolyline (const points:array of TPoint); override;
  40. procedure DoFloodFill (x,y:integer); override;
  41. procedure DoLine (x1,y1,x2,y2:integer); override;
  42. public
  43. constructor create;
  44. property HashWidth : word read FHashWidth write FHashWidth;
  45. property RelativeBrushImage : boolean read FRelativeBI write FRelativeBI;
  46. end;
  47. const
  48. PenPatterns : array[psDash..psDashDotDot] of TPenPattern =
  49. ($EEEEEEEE, $AAAAAAAA, $E4E4E4E4, $EAEAEAEA);
  50. sErrNoImage:string = 'No brush image specified';
  51. sErrNotAvailable:string = 'Not availlable';
  52. implementation
  53. uses Clipping;
  54. const
  55. DefaultHashWidth = 15;
  56. procedure NotImplemented;
  57. begin
  58. raise PixelCanvasException.Create(sErrNotAvailable);
  59. end;
  60. constructor TFPPixelCanvas.Create;
  61. begin
  62. inherited;
  63. FHashWidth := DefaultHashWidth;
  64. end;
  65. function TFPPixelCanvas.DoCreateDefaultFont : TFPCustomFont;
  66. begin
  67. result := TFPEmptyFont.Create;
  68. with result do
  69. begin
  70. Size := 10;
  71. FPColor := colBlack;
  72. end;
  73. end;
  74. function TFPPixelCanvas.DoCreateDefaultPen : TFPCustomPen;
  75. begin
  76. result := TFPEmptyPen.Create;
  77. with result do
  78. begin
  79. FPColor := colBlack;
  80. width := 1;
  81. pattern := 0;
  82. Style := psSolid;
  83. Mode := pmCopy;
  84. end;
  85. end;
  86. function TFPPixelCanvas.DoCreateDefaultBrush : TFPCustomBrush;
  87. begin
  88. result := TFPEmptyBrush.Create;
  89. with result do
  90. begin
  91. Style := bsClear;
  92. end;
  93. end;
  94. procedure TFPPixelCanvas.DoTextOut (x,y:integer;text:string);
  95. begin
  96. NotImplemented;
  97. end;
  98. procedure TFPPixelCanvas.DoGetTextSize (text:string; var w,h:integer);
  99. begin
  100. NotImplemented;
  101. end;
  102. function TFPPixelCanvas.DoGetTextHeight (text:string) : integer;
  103. begin
  104. result := -1;
  105. NotImplemented;
  106. end;
  107. function TFPPixelCanvas.DoGetTextWidth (text:string) : integer;
  108. begin
  109. result := -1;
  110. NotImplemented;
  111. end;
  112. procedure TFPPixelCanvas.DoRectangle (const Bounds:TRect);
  113. var pattern : longword;
  114. procedure CheckLine (x1,y1, x2,y2 : integer);
  115. begin
  116. if clipping then
  117. CheckLineClipping (ClipRect, x1,y1, x2,y2);
  118. if x1 >= 0 then
  119. DrawSolidLine (self, x1,y1, x2,y2, Pen.FPColor)
  120. end;
  121. procedure CheckPLine (x1,y1, x2,y2 : integer);
  122. begin
  123. if clipping then
  124. CheckLineClipping (ClipRect, x1,y1, x2,y2);
  125. if x1 >= 0 then
  126. DrawPatternLine (self, x1,y1, x2,y2, pattern, Pen.FPColor)
  127. end;
  128. var b : TRect;
  129. r : integer;
  130. begin
  131. b := bounds;
  132. if pen.style = psSolid then
  133. for r := 1 to pen.width do
  134. begin
  135. with b do
  136. begin
  137. CheckLine (left,top,left,bottom);
  138. CheckLine (left,bottom,right,bottom);
  139. CheckLine (right,bottom,right,top);
  140. CheckLine (right,top,left,top);
  141. end;
  142. DecRect (b);
  143. end
  144. else if pen.style <> psClear then
  145. begin
  146. if pen.style = psPattern then
  147. pattern := Pen.pattern
  148. else
  149. pattern := PenPatterns[pen.style];
  150. with b do
  151. begin
  152. CheckPLine (left,top,left,bottom);
  153. CheckPLine (left,bottom,right,bottom);
  154. CheckPLine (right,bottom,right,top);
  155. CheckPLine (right,top,left,top);
  156. end;
  157. end;
  158. end;
  159. procedure TFPPixelCanvas.DoRectangleFill (const Bounds:TRect);
  160. var b : TRect;
  161. begin
  162. b := Bounds;
  163. SortRect (b);
  164. if clipping then
  165. CheckRectClipping (ClipRect, B);
  166. with b do
  167. case Brush.style of
  168. bsSolid : FillRectangleColor (self, left,top, right,bottom);
  169. bsPattern : FillRectanglePattern (self, left,top, right,bottom, brush.pattern);
  170. bsImage :
  171. if assigned (brush.image) then
  172. if FRelativeBI then
  173. FillRectangleImageRel (self, left,top, right,bottom, brush.image)
  174. else
  175. FillRectangleImage (self, left,top, right,bottom, brush.image)
  176. else
  177. raise PixelCanvasException.Create (sErrNoImage);
  178. bsBDiagonal : FillRectangleHashDiagonal (self, b, FHashWidth);
  179. bsFDiagonal : FillRectangleHashBackDiagonal (self, b, FHashWidth);
  180. bsCross :
  181. begin
  182. FillRectangleHashHorizontal (self, b, FHashWidth);
  183. FillRectangleHashVertical (self, b, FHashWidth);
  184. end;
  185. bsDiagCross :
  186. begin
  187. FillRectangleHashDiagonal (self, b, FHashWidth);
  188. FillRectangleHashBackDiagonal (self, b, FHashWidth);
  189. end;
  190. bsHorizontal : FillRectangleHashHorizontal (self, b, FHashWidth);
  191. bsVertical : FillRectangleHashVertical (self, b, FHashWidth);
  192. end;
  193. end;
  194. procedure TFPPixelCanvas.DoEllipseFill (const Bounds:TRect);
  195. begin
  196. case Brush.style of
  197. bsSolid : FillEllipseColor (self, Bounds, Brush.FPColor);
  198. bsPattern : FillEllipsePattern (self, Bounds, brush.pattern, Brush.FPColor);
  199. bsImage :
  200. if assigned (brush.image) then
  201. if FRelativeBI then
  202. FillEllipseImageRel (self, Bounds, brush.image)
  203. else
  204. FillEllipseImage (self, Bounds, brush.image)
  205. else
  206. raise PixelCanvasException.Create (sErrNoImage);
  207. bsBDiagonal : FillEllipseHashDiagonal (self, Bounds, FHashWidth, Brush.FPColor);
  208. bsFDiagonal : FillEllipseHashBackDiagonal (self, Bounds, FHashWidth, Brush.FPColor);
  209. bsCross : FillEllipseHashCross (self, Bounds, FHashWidth, Brush.FPColor);
  210. bsDiagCross : FillEllipseHashDiagCross (self, Bounds, FHashWidth, Brush.FPColor);
  211. bsHorizontal : FillEllipseHashHorizontal (self, Bounds, FHashWidth, Brush.FPColor);
  212. bsVertical : FillEllipseHashVertical (self, Bounds, FHashWidth, Brush.FPColor);
  213. end;
  214. end;
  215. procedure TFPPixelCanvas.DoEllipse (const Bounds:TRect);
  216. begin
  217. with pen do
  218. case style of
  219. psSolid :
  220. if pen.width > 1 then
  221. DrawSolidEllipse (self, Bounds, width, FPColor)
  222. else
  223. DrawSolidEllipse (self, Bounds, FPColor);
  224. psPattern:
  225. DrawPatternEllipse (self, Bounds, pattern, FPColor);
  226. psDash, psDot, psDashDot, psDashDotDot :
  227. DrawPatternEllipse (self, Bounds, PenPatterns[Style], FPColor);
  228. end;
  229. end;
  230. procedure TFPPixelCanvas.DoPolygonFill (const points:array of TPoint);
  231. begin //TODO: how to find a point inside the polygon ?
  232. end;
  233. procedure TFPPixelCanvas.DoFloodFill (x,y:integer);
  234. begin
  235. case Brush.style of
  236. bsSolid : FillFloodColor (self, x,y);
  237. bsPattern : FillFloodPattern (self, x,y, brush.pattern);
  238. bsImage :
  239. if assigned (brush.image) then
  240. if FRelativeBI then
  241. FillFloodImageRel (self, x,y, brush.image)
  242. else
  243. FillFloodImage (self, x,y, brush.image)
  244. else
  245. raise PixelCanvasException.Create (sErrNoImage);
  246. bsBDiagonal : FillFloodHashDiagonal (self, x,y, FHashWidth);
  247. bsFDiagonal : FillFloodHashBackDiagonal (self, x,y, FHashWidth);
  248. bsCross : FillFloodHashCross (self, x,y, FHashWidth);
  249. bsDiagCross : FillFloodHashDiagCross (self, x,y, FHashWidth);
  250. bsHorizontal : FillFloodHashHorizontal (self, x,y, FHashWidth);
  251. bsVertical : FillFloodHashVertical (self, x,y, FHashWidth);
  252. end;
  253. end;
  254. procedure TFPPixelCanvas.DoPolygon (const points:array of TPoint);
  255. var i,a, r : integer;
  256. p : TPoint;
  257. begin
  258. i := low(points);
  259. a := high(points);
  260. p := points[i];
  261. for r := i+1 to a do
  262. begin
  263. DoLine (p.x, p.y, points[r].x, points[r].y);
  264. p := points[r];
  265. end;
  266. DoLine (p.x,p.y, points[i].x,points[i].y);
  267. end;
  268. procedure TFPPixelCanvas.DoPolyline (const points:array of TPoint);
  269. var i,a, r : integer;
  270. p : TPoint;
  271. begin
  272. i := low(points);
  273. a := high(points);
  274. p := points[i];
  275. for r := i+1 to a do
  276. begin
  277. DoLine (p.x, p.y, points[r].x, points[r].y);
  278. p := points[r];
  279. end;
  280. end;
  281. procedure TFPPixelCanvas.DoLine (x1,y1,x2,y2:integer);
  282. procedure DrawOneLine (xx1,yy1, xx2,yy2:integer);
  283. begin
  284. if Clipping then
  285. CheckLineClipping (ClipRect, xx1,yy1, xx2,yy2);
  286. DrawSolidLine (self, xx1,yy1, xx2,yy2, Pen.FPColor);
  287. end;
  288. procedure SolidThickLine;
  289. var w1, w2, r : integer;
  290. MoreHor : boolean;
  291. begin
  292. // determine lines above and under
  293. w1 := pen.width div 2;
  294. w2 := w1;
  295. if w1+w2 = pen.width then
  296. dec (w1);
  297. // determine slanting
  298. MoreHor := (abs(x2-x1) < abs(y2-y1));
  299. if MoreHor then
  300. begin // add lines left/right
  301. for r := 1 to w1 do
  302. DrawOneLine (x1-r,y1, x2-r,y2);
  303. for r := 1 to w2 do
  304. DrawOneLine (x1+r,y1, x2+r,y2);
  305. end
  306. else
  307. begin // add lines above/under
  308. for r := 1 to w1 do
  309. DrawOneLine (x1,y1-r, x2,y2-r);
  310. for r := 1 to w2 do
  311. DrawOneLine (x1,y1+r, x2,y2+r);
  312. end;
  313. end;
  314. begin
  315. if Clipping then
  316. CheckLineClipping (ClipRect, x1,y1, x2,y2);
  317. case Pen.style of
  318. psSolid :
  319. begin
  320. DrawSolidLine (self, x1,y1, x2,y2, Pen.FPColor);
  321. if pen.width > 1 then
  322. SolidThickLine;
  323. end;
  324. psPattern:
  325. DrawPatternLine (self, x1,y1, x2,y2, pen.pattern);
  326. // Patterned lines have width always at 1
  327. psDash, psDot, psDashDot, psDashDotDot :
  328. DrawPatternLine (self, x1,y1, x2,y2, PenPatterns[Pen.Style]);
  329. end;
  330. end;
  331. end.