GR32_Backends_LCL_Carbon.pas 16 KB

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