GR32_Backends_LCL_Carbon.pas 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. unit GR32_Backends_LCL_Carbon;
  2. (* ***** BEGIN LICENSE BLOCK *****
  3. * Version: MPL 1.1 or LGPL 2.1 with linking exception
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. * http://www.mozilla.org/MPL/
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. *
  15. * Alternatively, the contents of this file may be used under the terms of the
  16. * Free Pascal modified version of the GNU Lesser General Public License
  17. * Version 2.1 (the "FPC modified LGPL License"), in which case the provisions
  18. * of this license are applicable instead of those above.
  19. * Please see the file LICENSE.txt for additional information concerning this
  20. * license.
  21. *
  22. * The Original Code is Backend Extension for Graphics32
  23. *
  24. * The Initial Developer of the Original Code is
  25. * Felipe Monteiro de Carvalho <[email protected]>
  26. *
  27. * Portions created by the Initial Developer are Copyright (C) 2007-2012
  28. * the Initial Developer. All Rights Reserved.
  29. *
  30. * Contributor(s):
  31. *
  32. * ***** END LICENSE BLOCK ***** *)
  33. interface
  34. {$include GR32.inc}
  35. uses
  36. { RTL and LCL }
  37. LCLIntf, LCLType, types, Controls, SysUtils, Classes, Graphics,
  38. { Carbon bindings }
  39. MacOSAll,
  40. { Carbon lcl interface }
  41. CarbonCanvas, CarbonPrivate,
  42. { Graphics 32 }
  43. GR32,
  44. GR32_Backends,
  45. GR32_Containers;
  46. const
  47. STR_GenericRGBProfilePath = '/System/Library/ColorSync/Profiles/Generic RGB Profile.icc';
  48. type
  49. { TLCLBackend }
  50. TLCLBackend = class(TCustomBackend,
  51. IPaintSupport, IDeviceContextSupport,
  52. ITextSupport, IFontSupport, ICanvasSupport)
  53. private
  54. FFont: TFont;
  55. FCanvas: TCanvas;
  56. FOnFontChange: TNotifyEvent;
  57. FOnCanvasChange: TNotifyEvent;
  58. { Carbon specific variables }
  59. Stride: Integer;
  60. FWidth, FHeight: Cardinal;
  61. FProfile: CMProfileRef;
  62. FColorSpace: CGColorSpaceRef;
  63. FContext: CGContextRef;
  64. FCanvasHandle: TCarbonDeviceContext;
  65. { Functions to easely generate carbon structures }
  66. function GetCarbonRect(Left, Top, Width, Height: Integer): MacOSAll.Rect;
  67. function GetCGRect(Left, Top, Width, Height: Integer): MacOSAll.CGRect; overload;
  68. function GetCGRect(SrcRect: TRect): MacOSAll.CGRect; overload;
  69. protected
  70. { BITS_GETTER }
  71. function GetBits: PColor32Array; override;
  72. procedure InitializeSurface(NewWidth, NewHeight: Integer; ClearBuffer: Boolean); override;
  73. procedure FinalizeSurface; override;
  74. public
  75. constructor Create; override;
  76. destructor Destroy; override;
  77. procedure Changed; override;
  78. function Empty: Boolean; override;
  79. public
  80. { IPaintSupport }
  81. procedure ImageNeeded;
  82. procedure CheckPixmap;
  83. procedure DoPaint(ABuffer: TBitmap32; AInvalidRects: TRectList; ACanvas: TCanvas); overload;
  84. procedure DoPaint(ABuffer: TBitmap32; const AInvalidRect: TRect; ACanvas: TCanvas); overload;
  85. { IDeviceContextSupport }
  86. function GetHandle: HDC;
  87. procedure Draw(const DstRect, SrcRect: TRect; hSrc: HDC); overload;
  88. procedure DrawTo(hDst: HDC; DstX, DstY: Integer); overload;
  89. procedure DrawTo(hDst: HDC; const DstRect, SrcRect: TRect); overload;
  90. property Handle: HDC read GetHandle;
  91. { ITextSupport }
  92. procedure Textout(X, Y: Integer; const Text: string); overload;
  93. procedure Textout(X, Y: Integer; const ClipRect: TRect; const Text: string); overload;
  94. procedure Textout(var DstRect: TRect; const Flags: Cardinal; const Text: string); overload;
  95. function TextExtent(const Text: string): TSize;
  96. { IFontSupport }
  97. function GetOnFontChange: TNotifyEvent;
  98. procedure SetOnFontChange(Handler: TNotifyEvent);
  99. function GetFont: TFont;
  100. procedure SetFont(const Font: TFont);
  101. procedure UpdateFont;
  102. property Font: TFont read GetFont write SetFont;
  103. property OnFontChange: TNotifyEvent read FOnFontChange write FOnFontChange;
  104. { IInteroperabilitySupport }
  105. function CopyFrom(Graphic: TGraphic): Boolean; overload;
  106. { ICanvasSupport }
  107. function GetCanvasChange: TNotifyEvent;
  108. procedure SetCanvasChange(Handler: TNotifyEvent);
  109. function GetCanvas: TCanvas;
  110. procedure DeleteCanvas;
  111. function CanvasAllocated: Boolean;
  112. property Canvas: TCanvas read GetCanvas;
  113. property OnCanvasChange: TNotifyEvent read GetCanvasChange write SetCanvasChange;
  114. end;
  115. implementation
  116. uses
  117. GR32_LowLevel;
  118. var
  119. StockFont: TFont;
  120. { TLCLBackend }
  121. function TLCLBackend.GetCarbonRect(Left, Top, Width, Height: Integer): MacOSAll.Rect;
  122. begin
  123. Result.Left := Left;
  124. Result.Top := Top;
  125. Result.Right := Left + Width;
  126. Result.Bottom := Top + Height;
  127. end;
  128. function TLCLBackend.GetCGRect(Left, Top, Width, Height: Integer): MacOSAll.CGRect;
  129. begin
  130. Result.Origin.X := Left;
  131. Result.Origin.Y := Top;
  132. Result.Size.Width := Width;
  133. Result.Size.Height := Height;
  134. end;
  135. function TLCLBackend.GetCGRect(SrcRect: TRect): MacOSAll.CGRect;
  136. begin
  137. Result.Origin.X := SrcRect.Left;
  138. Result.Origin.Y := SrcRect.Top;
  139. Result.Size.Width := SrcRect.Right - SrcRect.Left;
  140. Result.Size.Height := SrcRect.Bottom - SrcRect.Top;
  141. end;
  142. constructor TLCLBackend.Create;
  143. var
  144. loc: CMProfileLocation;
  145. status: OSStatus;
  146. begin
  147. {$IFDEF VerboseGR32Carbon}
  148. WriteLn('[TLCLBackend.Create]', ' Self: ', IntToHex(PtrUInt(Self), 8));
  149. {$ENDIF}
  150. inherited;
  151. { Creates a standard font }
  152. FFont := TFont.Create;
  153. { Creates a generic color profile }
  154. loc.locType := cmPathBasedProfile;
  155. loc.u.pathLoc.path := STR_GenericRGBProfilePath;
  156. status := CMOpenProfile(FProfile, loc);
  157. if status <> noErr then raise Exception.Create('Couldn''t create the generic profile');
  158. { Creates a generic color space }
  159. FColorSpace := CGColorSpaceCreateWithPlatformColorSpace(FProfile);
  160. if FColorSpace = nil then raise Exception.Create('Couldn''t create the generic RGB color space');
  161. end;
  162. destructor TLCLBackend.Destroy;
  163. begin
  164. {$IFDEF VerboseGR32Carbon}
  165. WriteLn('[TLCLBackend.Destroy]',
  166. ' Self: ', IntToHex(PtrUInt(Self), 8));
  167. {$ENDIF}
  168. { Deallocates the standard font }
  169. FFont.Free;
  170. { Closes the profile }
  171. CMCloseProfile(FProfile);
  172. inherited;
  173. end;
  174. function TLCLBackend.GetBits: PColor32Array;
  175. begin
  176. Result := FBits;
  177. end;
  178. procedure TLCLBackend.InitializeSurface(NewWidth, NewHeight: Integer; ClearBuffer: Boolean);
  179. begin
  180. {$IFDEF VerboseGR32Carbon}
  181. WriteLn('[TLCLBackend.InitializeSurface] BEGIN',
  182. ' Self: ', IntToHex(PtrUInt(Self), 8),
  183. ' NewWidth: ', NewWidth,
  184. ' NewHeight: ', NewHeight
  185. );
  186. {$ENDIF}
  187. { We allocate our own memory for the image }
  188. Stride := NewWidth * 4;
  189. FBits := System.GetMem(NewHeight * Stride);
  190. if FBits = nil then
  191. raise Exception.Create('[TLCLBackend.InitializeSurface] ERROR FBits = nil');
  192. { Creates a device context for our raw image area }
  193. FContext := CGBitmapContextCreate(FBits,
  194. NewWidth, NewHeight, 8, Stride, FColorSpace,
  195. kCGImageAlphaNoneSkipFirst or kCGBitmapByteOrder32Little);
  196. if FContext = nil then
  197. raise Exception.Create('[TLCLBackend.InitializeSurface] ERROR FContext = nil');
  198. { flip and offset CTM to upper left corner }
  199. CGContextTranslateCTM(FContext, 0, NewHeight);
  200. CGContextScaleCTM(FContext, 1, -1);
  201. FWidth := NewWidth;
  202. FHeight := NewHeight;
  203. { clear the image }
  204. if ClearBuffer then
  205. FillLongword(FBits[0], NewWidth * NewHeight, clBlack32);
  206. {$IFDEF VerboseGR32Carbon}
  207. WriteLn('[TLCLBackend.InitializeSurface] END');
  208. {$ENDIF}
  209. end;
  210. procedure TLCLBackend.FinalizeSurface;
  211. begin
  212. {$IFDEF VerboseGR32Carbon}
  213. WriteLn('[TLCLBackend.FinalizeSurface]',
  214. ' Self: ', IntToHex(PtrUInt(Self), 8));
  215. {$ENDIF}
  216. if Assigned(FBits) then System.FreeMem(FBits);
  217. FBits := nil;
  218. if Assigned(FContext) then CGContextRelease(FContext);
  219. FContext := nil;
  220. end;
  221. procedure TLCLBackend.Changed;
  222. begin
  223. inherited;
  224. end;
  225. function TLCLBackend.Empty: Boolean;
  226. begin
  227. Result := (FContext = nil) or (FBits = nil);
  228. end;
  229. { IPaintSupport }
  230. procedure TLCLBackend.ImageNeeded;
  231. begin
  232. end;
  233. procedure TLCLBackend.CheckPixmap;
  234. begin
  235. end;
  236. procedure TLCLBackend.DoPaint(ABuffer: TBitmap32; AInvalidRects: TRectList; ACanvas: TCanvas);
  237. var
  238. ImageRef: CGImageRef;
  239. begin
  240. {$IFDEF VerboseGR32Carbon}
  241. WriteLn('[TLCLBackend.DoPaint]',
  242. ' Self: ', IntToHex(PtrUInt(Self), 8));
  243. {$ENDIF}
  244. { CGContextDrawImage is also possible, but it doesn't flip the image }
  245. ImageRef := CGBitmapContextCreateImage(FContext);
  246. try
  247. HIViewDrawCGImage(
  248. TCarbonDeviceContext(ACanvas.Handle).CGContext,
  249. GetCGRect(0, 0, FWidth, FHeight), imageRef);
  250. finally
  251. if Assigned(ImageRef) then
  252. CGImageRelease(ImageRef);
  253. end;
  254. end;
  255. procedure TLCLBackend.DoPaint(ABuffer: TBitmap32; const AInvalidRect: TRect; ACanvas: TCanvas);
  256. begin
  257. DoPaint(ABuffer, nil, ACanvas);
  258. end;
  259. { IDeviceContextSupport }
  260. function TLCLBackend.GetHandle: HDC;
  261. begin
  262. {$IFDEF VerboseGR32Carbon}
  263. WriteLn('[TLCLBackend.GetHandle]',
  264. ' Self: ', IntToHex(PtrUInt(Self), 8));
  265. {$ENDIF}
  266. if not Assigned(FCanvas) then GetCanvas;
  267. Result := FCanvas.Handle;
  268. end;
  269. procedure TLCLBackend.Draw(const DstRect, SrcRect: TRect; hSrc: HDC);
  270. var
  271. original, subsection: CGImageRef;
  272. CGDstRect, CGSrcRect: CGRect;
  273. ExternalContext: CGContextRef;
  274. begin
  275. {$IFDEF VerboseGR32Carbon}
  276. WriteLn('[TLCLBackend.Draw]',
  277. ' Self: ', IntToHex(PtrUInt(Self), 8));
  278. {$ENDIF}
  279. // Gets the external context
  280. if (hSrc = 0) then Exit;
  281. ExternalContext := TCarbonDeviceContext(hSrc).CGContext;
  282. // Converts the rectangles to CoreGraphics rectangles
  283. CGDstRect := GetCGRect(DstRect);
  284. CGSrcRect := GetCGRect(SrcRect);
  285. // Gets an image handle that represents the subsection
  286. original := CGBitmapContextCreateImage(ExternalContext);
  287. subsection := CGImageCreateWithImageInRect(original, CGSrcRect);
  288. CGImageRelease(original);
  289. { We need to make adjustments to the CTM so the painting is done correctly }
  290. CGContextSaveGState(FContext);
  291. try
  292. CGContextTranslateCTM(FContext, 0, FOwner.Height);
  293. CGContextScaleCTM(FContext, 1, -1);
  294. CGContextTranslateCTM(FContext, 0, -CGDstRect.origin.y);
  295. CGDstRect.origin.y := 0;
  296. { Draw the subsection }
  297. CGContextDrawImage(FContext, CGDstRect, subsection);
  298. finally
  299. { reset the CTM to the old values }
  300. CGContextRestoreGState(FContext);
  301. end;
  302. // Release the subsection
  303. CGImageRelease(subsection);
  304. end;
  305. procedure TLCLBackend.DrawTo(hDst: HDC; DstX, DstY: Integer);
  306. var
  307. DstRect, SrcRect: TRect;
  308. begin
  309. {$IFDEF VerboseGR32Carbon}
  310. WriteLn('[TLCLBackend.DrawTo]',
  311. ' Self: ', IntToHex(PtrUInt(Self), 8));
  312. {$ENDIF}
  313. DstRect.Left := DstX;
  314. DstRect.Top := DstY;
  315. DstRect.Right := FOwner.Width + DstX;
  316. DstRect.Bottom := FOwner.Height + DstY;
  317. SrcRect.Left := 0;
  318. SrcRect.Top := 0;
  319. SrcRect.Right := FOwner.Width;
  320. SrcRect.Bottom := FOwner.Height;
  321. DrawTo(hDst, DstRect, SrcRect);
  322. end;
  323. procedure TLCLBackend.DrawTo(hDst: HDC; const DstRect, SrcRect: TRect);
  324. var
  325. original, subsection: CGImageRef;
  326. CGDstRect, CGSrcRect: CGRect;
  327. ExternalContext: CGContextRef;
  328. begin
  329. {$IFDEF VerboseGR32Carbon}
  330. WriteLn('[TLCLBackend.DrawTo with rects]',
  331. ' Self: ', IntToHex(PtrUInt(Self), 8));
  332. {$ENDIF}
  333. // Gets the external context
  334. if (hDst = 0) then Exit;
  335. ExternalContext := TCarbonDeviceContext(hDst).CGContext;
  336. // Converts the rectangles to CoreGraphics rectangles
  337. CGDstRect := GetCGRect(DstRect);
  338. CGSrcRect := GetCGRect(SrcRect);
  339. // Gets an image handle that represents the subsection
  340. original := CGBitmapContextCreateImage(FContext);
  341. subsection := CGImageCreateWithImageInRect(original, CGSrcRect);
  342. CGImageRelease(original);
  343. { We need to make adjustments to the CTM so the painting is done correctly }
  344. CGContextSaveGState(ExternalContext);
  345. try
  346. CGContextTranslateCTM(ExternalContext, 0, FOwner.Height);
  347. CGContextScaleCTM(ExternalContext, 1, -1);
  348. CGContextTranslateCTM(ExternalContext, 0, -CGDstRect.origin.y);
  349. CGDstRect.origin.y := 0;
  350. { Draw the subsection }
  351. CGContextDrawImage(ExternalContext, CGDstRect, subsection);
  352. finally
  353. { reset the CTM to the old values }
  354. CGContextRestoreGState(ExternalContext);
  355. end;
  356. // Release the subsection
  357. CGImageRelease(subsection);
  358. end;
  359. { ITextSupport }
  360. procedure TLCLBackend.Textout(X, Y: Integer; const Text: string);
  361. begin
  362. {$IFDEF VerboseGR32Carbon}
  363. WriteLn('[TLCLBackend.Textout]', ' Self: ', IntToHex(PtrUInt(Self), 8));
  364. {$ENDIF}
  365. if not Assigned(FCanvas) then GetCanvas;
  366. UpdateFont;
  367. if not FOwner.MeasuringMode then
  368. FCanvas.TextOut(X, Y, Text);
  369. FOwner.Changed;
  370. end;
  371. procedure TLCLBackend.Textout(X, Y: Integer; const ClipRect: TRect; const Text: string);
  372. begin
  373. {$IFDEF VerboseGR32Carbon}
  374. WriteLn('[TLCLBackend.Textout with ClipRect]', ' Self: ',
  375. IntToHex(PtrUInt(Self), 8));
  376. {$ENDIF}
  377. if not Assigned(FCanvas) then GetCanvas;
  378. UpdateFont;
  379. LCLIntf.ExtTextOut(FCanvas.Handle, X, Y, ETO_CLIPPED, @ClipRect, PChar(Text),
  380. Length(Text), nil);
  381. end;
  382. procedure TLCLBackend.Textout(var DstRect: TRect; const Flags: Cardinal; const Text: string);
  383. begin
  384. {$IFDEF VerboseGR32Carbon}
  385. WriteLn('[TLCLBackend.Textout with Flags]',
  386. ' Self: ', IntToHex(PtrUInt(Self), 8));
  387. {$ENDIF}
  388. if not Assigned(FCanvas) then GetCanvas;
  389. UpdateFont;
  390. LCLIntf.DrawText(FCanvas.Handle, PChar(Text), Length(Text), DstRect, Flags);
  391. end;
  392. function TLCLBackend.TextExtent(const Text: string): TSize;
  393. begin
  394. {$IFDEF VerboseGR32Carbon}
  395. WriteLn('[TLCLBackend.TextExtent]',
  396. ' Self: ', IntToHex(PtrUInt(Self), 8));
  397. {$ENDIF}
  398. if not Assigned(FCanvas) then GetCanvas;
  399. UpdateFont;
  400. Result := FCanvas.TextExtent(Text);
  401. end;
  402. { IFontSupport }
  403. function TLCLBackend.GetOnFontChange: TNotifyEvent;
  404. begin
  405. {$IFDEF VerboseGR32Carbon}
  406. WriteLn('[TLCLBackend.GetOnFontChange]',
  407. ' Self: ', IntToHex(PtrUInt(Self), 8));
  408. {$ENDIF}
  409. Result := FFont.OnChange;
  410. end;
  411. procedure TLCLBackend.SetOnFontChange(Handler: TNotifyEvent);
  412. begin
  413. {$IFDEF VerboseGR32Carbon}
  414. WriteLn('[TLCLBackend.SetOnFontChange]',
  415. ' Self: ', IntToHex(PtrUInt(Self), 8));
  416. {$ENDIF}
  417. FFont.OnChange := Handler;
  418. end;
  419. function TLCLBackend.GetFont: TFont;
  420. begin
  421. {$IFDEF VerboseGR32Carbon}
  422. WriteLn('[TLCLBackend.GetFont]',
  423. ' Self: ', IntToHex(PtrUInt(Self), 8));
  424. {$ENDIF}
  425. Result := FFont;
  426. end;
  427. procedure TLCLBackend.SetFont(const Font: TFont);
  428. begin
  429. {$IFDEF VerboseGR32Carbon}
  430. WriteLn('[TLCLBackend.SetFont]',
  431. ' Self: ', IntToHex(PtrUInt(Self), 8));
  432. {$ENDIF}
  433. FFont.Assign(Font);
  434. end;
  435. procedure TLCLBackend.UpdateFont;
  436. begin
  437. {$IFDEF VerboseGR32Carbon}
  438. WriteLn('[TLCLBackend.UpdateFont]',
  439. ' Self: ', IntToHex(PtrUInt(Self), 8));
  440. {$ENDIF}
  441. FFont.OnChange := FOnFontChange;
  442. if Assigned(FCanvas) then FCanvas.Font := FFont;
  443. end;
  444. { IInteroperabilitySupport }
  445. type
  446. TGraphicAccess = class(TGraphic);
  447. function TLCLBackend.CopyFrom(Graphic: TGraphic): Boolean;
  448. begin
  449. TGraphicAccess(Graphic).Draw(Canvas, MakeRect(0, 0, FCanvas.Width, FCanvas.Height));
  450. end;
  451. { ICanvasSupport }
  452. function TLCLBackend.GetCanvasChange: TNotifyEvent;
  453. begin
  454. {$IFDEF VerboseGR32Carbon}
  455. WriteLn('[TLCLBackend.GetCanvasChange]',
  456. ' Self: ', IntToHex(PtrUInt(Self), 8));
  457. {$ENDIF}
  458. Result := FOnCanvasChange;
  459. end;
  460. procedure TLCLBackend.SetCanvasChange(Handler: TNotifyEvent);
  461. begin
  462. {$IFDEF VerboseGR32Carbon}
  463. WriteLn('[TLCLBackend.SetCanvasChange]',
  464. ' Self: ', IntToHex(PtrUInt(Self), 8));
  465. {$ENDIF}
  466. FOnCanvasChange := Handler;
  467. end;
  468. function TLCLBackend.GetCanvas: TCanvas;
  469. begin
  470. {$IFDEF VerboseGR32Carbon}
  471. WriteLn('[TLCLBackend.GetCanvas] BEGIN',
  472. ' Self: ', IntToHex(PtrUInt(Self), 8));
  473. {$ENDIF}
  474. if FCanvas = nil then
  475. begin
  476. FCanvas := TCanvas.Create;
  477. FCanvasHandle := TCarbonDeviceContext.Create;
  478. FCanvasHandle.CGContext := FContext;
  479. FCanvas.Handle := HDC(FCanvasHandle);
  480. FCanvas.OnChange := FOnCanvasChange;
  481. FCanvas.Font := FFont;
  482. end;
  483. Result := FCanvas;
  484. {$IFDEF VerboseGR32Carbon}
  485. WriteLn('[TLCLBackend.GetCanvas] END');
  486. {$ENDIF}
  487. end;
  488. procedure TLCLBackend.DeleteCanvas;
  489. begin
  490. {$IFDEF VerboseGR32Carbon}
  491. WriteLn('[TLCLBackend.DeleteCanvas]',
  492. ' Self: ', IntToHex(PtrUInt(Self), 8),
  493. ' FCanvas: ', PtrUInt(FCanvas));
  494. {$ENDIF}
  495. if Assigned(FCanvas) then
  496. begin
  497. FCanvas.Handle := 0;
  498. FCanvas.Free;
  499. FCanvas := nil;
  500. end;
  501. end;
  502. function TLCLBackend.CanvasAllocated: Boolean;
  503. begin
  504. Result := (FCanvas <> nil);
  505. {$IFDEF VerboseGR32Carbon}
  506. WriteLn('[TLCLBackend.CanvasAllocated]',
  507. ' Self: ', IntToHex(PtrUInt(Self), 8),
  508. ' FCanvas: ', PtrUInt(FCanvas));
  509. {$ENDIF}
  510. end;
  511. initialization
  512. StockFont := TFont.Create;
  513. finalization
  514. StockFont.Free;
  515. end.