fpcanvas.inc 13 KB

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