fpcanvas.inc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 2003 by the Free Pascal development team
  5. TFPCustomCanvas implementation.
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. { TFPCustomCanvas }
  13. constructor TFPCustomCanvas.Create;
  14. begin
  15. inherited create;
  16. FClipRect := Rect(-1,-1,-1,-1);
  17. FClipping := false;
  18. FRemovingHelpers := false;
  19. FHelpers := TList.Create;
  20. FDefaultFont := CreateDefaultFont;
  21. FDefaultPen := CreateDefaultPen;
  22. FDefaultBrush := CreateDefaultBrush;
  23. end;
  24. destructor TFPCustomCanvas.Destroy;
  25. begin
  26. FRemovingHelpers := True;
  27. FDefaultFont.Free;
  28. FDefaultBrush.Free;
  29. FDefaultPen.Free;
  30. RemoveHelpers;
  31. FHelpers.Free;
  32. FRemovingHelpers := False;
  33. inherited;
  34. end;
  35. procedure TFPCustomCanvas.CheckHelper (AHelper:TFPCanvasHelper);
  36. var r : integer;
  37. begin
  38. if AHelper = FPen then
  39. FPen := nil
  40. else if AHelper = FFont then
  41. FFont := nil
  42. else if AHelper = FBrush then
  43. FBrush := nil;
  44. if not FRemovingHelpers then
  45. begin
  46. if AHelper = FDefaultFont then
  47. FDefaultFont := CreateDefaultFont
  48. else if AHelper = FDefaultPen then
  49. FDefaultPen := CreateDefaultPen
  50. else if AHelper = FDefaultBrush then
  51. FDefaultBrush := CreateDefaultBrush;
  52. end;
  53. r := FHelpers.IndexOf (AHelper);
  54. if (r >= 0) then
  55. FHelpers.delete (r);
  56. end;
  57. procedure TFPCustomCanvas.RemoveHelpers;
  58. var r : integer;
  59. OldState : boolean;
  60. begin
  61. for r := FHelpers.count-1 downto 0 do
  62. with TFPCanvasHelper(FHelpers[r]) do
  63. if FCanvas = self then
  64. if FFixedCanvas then
  65. DeallocateResources
  66. else
  67. FCanvas := nil;
  68. FHelpers.Clear;
  69. end;
  70. procedure TFPCustomCanvas.AddHelper (AHelper : TFPCanvasHelper);
  71. var r : integer;
  72. begin
  73. r := FHelpers.IndexOf (AHelper);
  74. if r < 0 then
  75. FHelpers.Add (AHelper);
  76. end;
  77. function TFPCustomCanvas.CreateDefaultFont : TFPCustomFont;
  78. begin
  79. result := DoCreateDefaultFont;
  80. if not assigned (result) then
  81. raise TFPCanvasException.CreateFmt (ErrCouldNotCreate, [EPen])
  82. else
  83. begin
  84. result.AllocateResources (self);
  85. FHelpers.Add (result);
  86. end;
  87. end;
  88. function TFPCustomCanvas.CreateDefaultPen : TFPCustomPen;
  89. begin
  90. result := DoCreateDefaultPen;
  91. if not assigned (result) then
  92. raise TFPCanvasException.CreateFmt (ErrCouldNotCreate, [EPen])
  93. else
  94. begin
  95. result.AllocateResources (self);
  96. FHelpers.Add (result);
  97. end;
  98. end;
  99. function TFPCustomCanvas.CreateDefaultBrush : TFPCustomBrush;
  100. begin
  101. result := DoCreateDefaultBrush;
  102. if not assigned (result) then
  103. raise TFPCanvasException.CreateFmt (ErrCouldNotCreate, [EPen])
  104. else
  105. begin
  106. result.AllocateResources (self);
  107. FHelpers.Add (result);
  108. end;
  109. end;
  110. function TFPCustomCanvas.CreateFont : TFPCustomFont;
  111. begin
  112. result := DoCreateDefaultFont;
  113. end;
  114. function TFPCustomCanvas.CreatePen : TFPCustomPen;
  115. begin
  116. result := DoCreateDefaultPen;
  117. end;
  118. function TFPCustomCanvas.CreateBrush : TFPCustomBrush;
  119. begin
  120. result := DoCreateDefaultBrush;
  121. end;
  122. function TFPCustomCanvas.AllowFont (AFont : TFPCustomFont) : boolean;
  123. begin
  124. if AFont is TFPCustomDrawFont then
  125. result := true
  126. else
  127. result := DoAllowFont (AFont);
  128. end;
  129. procedure TFPCustomCanvas.SetFont (AValue:TFPCustomFont);
  130. begin
  131. if (AValue <> FFont) and AllowFont(AValue) then
  132. begin
  133. AValue.AllocateResources (self);
  134. FFont := AValue;
  135. AddHelper (AValue);
  136. end;
  137. end;
  138. function TFPCustomCanvas.GetFont : TFPCustomFont;
  139. begin
  140. if assigned (FFont) then
  141. result := FFont
  142. else
  143. result := FDefaultFont;
  144. end;
  145. function TFPCustomCanvas.DoAllowFont (AFont : TFPCustomFont) : boolean;
  146. begin
  147. result := false;
  148. end;
  149. function TFPCustomCanvas.AllowBrush (ABrush : TFPCustomBrush) : boolean;
  150. begin
  151. if ABrush is TFPCustomDrawBrush then
  152. result := true
  153. else
  154. result := DoAllowBrush (ABrush);
  155. end;
  156. procedure TFPCustomCanvas.SetBrush (AValue:TFPCustomBrush);
  157. begin
  158. if (AValue <> FBrush) and AllowBrush(AValue) then
  159. begin
  160. AValue.AllocateResources (self);
  161. FBrush := AValue;
  162. AddHelper (AValue);
  163. end;
  164. end;
  165. function TFPCustomCanvas.GetBrush : TFPCustomBrush;
  166. begin
  167. if assigned (FBrush) then
  168. result := FBrush
  169. else
  170. result := FDefaultBrush
  171. end;
  172. function TFPCustomCanvas.DoAllowBrush (ABrush : TFPCustomBrush) : boolean;
  173. begin
  174. result := false;
  175. end;
  176. function TFPCustomCanvas.AllowPen (APen : TFPCustomPen) : boolean;
  177. begin
  178. if APen is TFPCustomDrawPen then
  179. result := true
  180. else
  181. result := DoAllowPen (APen);
  182. end;
  183. procedure TFPCustomCanvas.SetPen (AValue:TFPCustomPen);
  184. begin
  185. if (AValue <> FPen) and AllowPen (AValue) then
  186. begin
  187. AValue.AllocateResources (self);
  188. FPen := AValue;
  189. AddHelper (AValue);
  190. end;
  191. end;
  192. function TFPCustomCanvas.GetPen : TFPCustomPen;
  193. begin
  194. if assigned (FPen) then
  195. result := FPen
  196. else
  197. result := FDefaultPen;
  198. end;
  199. function TFPCustomCanvas.DoAllowPen (APen : TFPCustomPen) : boolean;
  200. begin
  201. result := false;
  202. end;
  203. procedure TFPCustomCanvas.DoLockCanvas;
  204. begin
  205. end;
  206. procedure TFPCustomCanvas.DoUnlockCanvas;
  207. begin
  208. end;
  209. procedure TFPCustomCanvas.LockCanvas;
  210. begin
  211. if FLocks = 0 then
  212. DoLockCanvas;
  213. inc (FLocks);
  214. end;
  215. procedure TFPCustomCanvas.UnlockCanvas;
  216. begin
  217. if FLocks > 0 then
  218. begin
  219. dec (FLocks);
  220. if FLocks = 0 then
  221. DoUnlockCanvas;
  222. end
  223. else
  224. raise TFPCanvasException.Create (ErrNoLock);
  225. end;
  226. procedure TFPCustomCanvas.TextOut (x,y:integer;text:string);
  227. begin
  228. if Font is TFPCustomDrawFont then
  229. TFPCustomDrawFont(Font).DrawText(x,y, text)
  230. else
  231. DoTextOut (x,y, text);
  232. end;
  233. procedure TFPCustomCanvas.GetTextSize (text:string; var w,h:integer);
  234. begin
  235. if Font is TFPCustomDrawFont then
  236. TFPCustomDrawFont(Font).GetTextSize (text, w, h)
  237. else
  238. DoGetTextSize (Text, w, h);
  239. end;
  240. function TFPCustomCanvas.GetTextHeight (text:string) : integer;
  241. begin
  242. if Font is TFPCustomDrawFont then
  243. result := TFPCustomDrawFont(Font).GetTextHeight (text)
  244. else
  245. result := DoGetTextHeight (Text);
  246. end;
  247. function TFPCustomCanvas.GetTextWidth (text:string) : integer;
  248. begin
  249. if Font is TFPCustomDrawFont then
  250. result := TFPCustomDrawFont(Font).GetTextWidth (text)
  251. else
  252. result := DoGetTextWidth (Text);
  253. end;
  254. procedure TFPCustomCanvas.DoMoveTo (x,y:integer);
  255. begin
  256. end;
  257. procedure TFPCustomCanvas.DoLineTo (x,y:integer);
  258. begin
  259. DoLine (FCurrent.X,FCurrent.y, x,y);
  260. end;
  261. procedure TFPCustomCanvas.MoveTo (x,y:integer);
  262. begin
  263. FCurrent.x := x;
  264. FCurrent.y := y;
  265. DoMoveTo (x,y);
  266. end;
  267. procedure TFPCustomCanvas.MoveTo (p:TPoint);
  268. begin
  269. FCurrent := p;
  270. DoMoveTo (p.x,p.y);
  271. end;
  272. procedure TFPCustomCanvas.LineTo (x,y:integer);
  273. begin
  274. if Pen.Style <> psClear then
  275. if Pen is TFPCustomDrawPen then
  276. TFPCustomDrawPen(Pen).DrawLine (FCurrent.x, FCurrent.y, x, y)
  277. else
  278. DoLineTo (x,y);
  279. FCurrent.x := x;
  280. FCurrent.y := y;
  281. end;
  282. procedure TFPCustomCanvas.LineTo (p:TPoint);
  283. begin
  284. LineTo (p.x, p.y);
  285. end;
  286. procedure TFPCustomCanvas.Line (x1,y1,x2,y2:integer);
  287. begin
  288. if Pen.Style <> psClear then
  289. if Pen is TFPCustomDrawPen then
  290. TFPCustomDrawPen(Pen).DrawLine (x1,y1, x2,y2)
  291. else
  292. DoLine (x1,y1, x2,y2);
  293. FCurrent.x := x2;
  294. FCurrent.y := y2;
  295. end;
  296. procedure TFPCustomCanvas.Line (p1,p2:TPoint);
  297. begin
  298. Line (p1.x,p1.y,p2.x,p2.y);
  299. end;
  300. procedure TFPCustomCanvas.Line (const points:TRect);
  301. begin
  302. with points do
  303. Line (left,top, right,bottom);
  304. end;
  305. procedure TFPCustomCanvas.Polyline (Const points:array of TPoint);
  306. begin
  307. if Pen.Style <> psClear then
  308. if Pen is TFPCustomDrawPen then
  309. TFPCustomDrawPen(Pen).Polyline (points,false)
  310. else
  311. DoPolyline (points);
  312. FCurrent := points[high(points)];
  313. end;
  314. procedure TFPCustomCanvas.Clear;
  315. var r : TRect;
  316. begin
  317. if Brush.Style <> bsClear then
  318. begin
  319. if Brush is TFPCustomDrawBrush then
  320. TFPCustomDrawBrush(Brush).Rectangle(0,0, width, height)
  321. else
  322. begin
  323. r := Rect(0,0, width, height);
  324. DoRectangleFill (r);
  325. end;
  326. end;
  327. end;
  328. procedure TFPCustomCanvas.Erase;
  329. var
  330. x,y:Integer;
  331. begin
  332. for x:=0 to Width-1 do
  333. for y:=0 to Height-1 do
  334. Colors[x,y]:=colTransparent;
  335. end;
  336. procedure TFPCustomCanvas.DoRectangleAndFill (const Bounds:TRect);
  337. begin
  338. DoRectangleFill (Bounds);
  339. DoRectangle (Bounds);
  340. end;
  341. procedure TFPCustomCanvas.DoEllipseAndFill (const Bounds:TRect);
  342. begin
  343. DoEllipseFill (Bounds);
  344. DoEllipse (Bounds);
  345. end;
  346. procedure TFPCustomCanvas.DoPolygonAndFill (const points:array of TPoint);
  347. begin
  348. DoPolygonFill (points);
  349. DoPolygon (points);
  350. end;
  351. procedure TFPCustomCanvas.Ellipse (const Bounds:TRect);
  352. var p,b,dp,db,pb : boolean;
  353. begin
  354. p := Pen.style <> psClear;
  355. b := Brush.style <> bsClear;
  356. if p and (Pen is TFPCustomDrawPen) then
  357. begin
  358. p := false;
  359. dp := true;
  360. end;
  361. if b and (Brush is TFPCustomDrawBrush) then
  362. begin
  363. b := false;
  364. db := true;
  365. end;
  366. if p and b then
  367. begin
  368. p := false;
  369. b := false;
  370. pb := true;
  371. end;
  372. if pb then
  373. DoEllipseAndFill (bounds)
  374. else
  375. begin
  376. if p then
  377. DoEllipse (bounds)
  378. else
  379. with bounds do
  380. TFPCustomDrawPen(Pen).Ellipse (left,top,right,bottom);
  381. if b then
  382. DoEllipseFill (bounds)
  383. else
  384. with bounds do
  385. TFPCustomDrawBrush(Brush).Ellipse (left,top,right,bottom);
  386. end;
  387. end;
  388. procedure TFPCustomCanvas.Ellipse (left,top,right,bottom:integer);
  389. begin
  390. Ellipse (Rect(left,top,right,bottom));
  391. end;
  392. procedure TFPCustomCanvas.EllipseC (x,y:integer; rx,ry:longword);
  393. begin
  394. Ellipse (Rect(x-rx,y-ry,x+rx,y+ry));
  395. end;
  396. procedure TFPCustomCanvas.Rectangle (left,top,right,bottom:integer);
  397. begin
  398. Rectangle (Rect(left,top,right,bottom));
  399. end;
  400. procedure TFPCustomCanvas.Rectangle (const Bounds:TRect);
  401. var p,b,dp,db,pb : boolean;
  402. begin
  403. p := Pen.style <> psClear;
  404. b := Brush.style <> bsClear;
  405. if p and (pen is TFPCustomDrawPen) then
  406. begin
  407. p := false;
  408. dp := true;
  409. end;
  410. if b and (brush is TFPCustomDrawBrush) then
  411. begin
  412. b := false;
  413. db := true;
  414. end;
  415. if p and b then
  416. begin
  417. p := false;
  418. b := false;
  419. pb := true;
  420. end;
  421. if pb then
  422. DoRectangleAndFill (bounds)
  423. else
  424. begin
  425. if p then
  426. DoRectangle (bounds)
  427. else
  428. with bounds do
  429. TFPCustomDrawPen(Pen).Rectangle (left,top,right,bottom);
  430. if b then
  431. DoRectangleFill (bounds)
  432. else
  433. with bounds do
  434. TFPCustomDrawBrush(Brush).Rectangle (left,top,right,bottom);
  435. end;
  436. end;
  437. procedure TFPCustomCanvas.FloodFill (x,y:integer);
  438. begin
  439. if Brush.Style <> bsClear then
  440. begin
  441. if Brush is TFPCustomDrawBrush then
  442. TFPCustomDrawBrush (Brush).FloodFill (x,y)
  443. else
  444. DoFloodFill (x,y);
  445. end;
  446. end;
  447. procedure TFPCustomCanvas.Polygon (const points:array of TPoint);
  448. var p,b,dp,db,pb : boolean;
  449. begin
  450. p := Pen.style <> psClear;
  451. b := Brush.style <> bsClear;
  452. if p and (pen is TFPCustomDrawPen) then
  453. begin
  454. p := false;
  455. dp := true;
  456. end;
  457. if b and (brush is TFPCustomDrawBrush) then
  458. begin
  459. b := false;
  460. db := true;
  461. end;
  462. if p and b then
  463. begin
  464. p := false;
  465. b := false;
  466. pb := true;
  467. end;
  468. if pb then
  469. DoPolygonAndFill (points)
  470. else
  471. begin
  472. if p then
  473. DoPolygon (points)
  474. else
  475. TFPCustomDrawPen(Pen).Polyline (points, true);
  476. if b then
  477. DoPolygonFill (points)
  478. else
  479. TFPCustomDrawBrush(Brush).Polygon (points);
  480. end;
  481. end;
  482. procedure TFPCustomCanvas.CopyRect (x,y:integer; canvas:TFPCustomCanvas; SourceRect:TRect);
  483. var xx,r,t : integer;
  484. begin
  485. SortRect (SourceRect);
  486. with SourceRect do
  487. for r := left to right do
  488. begin
  489. xx := r - left + x;
  490. for t := bottom to top do
  491. colors[xx,(t - bottom + y)] := canvas.colors[r,t];
  492. end;
  493. end;
  494. procedure TFPCustomCanvas.Draw (x,y:integer; image:TFPCustomImage);
  495. var xx,xi,yi,xm,ym,r,t : integer;
  496. begin
  497. xm := x + image.width-1;
  498. if xm >= width then
  499. xm := width - 1;
  500. ym := y + image.height-1;
  501. if ym >= height then
  502. ym := height - 1;
  503. xi := x;
  504. yi := y;
  505. if clipping then
  506. CheckRectClipping (ClipRect, xi,yi, xm,ym);
  507. for r := xi to xm do
  508. begin
  509. xx := r - x;
  510. for t := yi to ym do
  511. colors [r,t] := image.colors[xx,t-y];
  512. end;
  513. end;