fpcanvas.inc 13 KB

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