GR32.Paint.Host.pas 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. unit GR32.Paint.Host;
  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 Paint tools for Graphics32
  23. *
  24. * The Initial Developer of the Original Code is
  25. * Anders Melander, [email protected]
  26. *
  27. * Portions created by the Initial Developer are Copyright (C) 2008-2025
  28. * the Initial Developer. All Rights Reserved.
  29. *
  30. * ***** END LICENSE BLOCK ***** *)
  31. interface
  32. {$INCLUDE GR32.inc}
  33. uses
  34. Classes,
  35. Controls,
  36. GR32,
  37. GR32_Image,
  38. GR32_Layers,
  39. GR32.Paint.Host.API,
  40. GR32.Paint.Tool.API;
  41. //------------------------------------------------------------------------------
  42. //
  43. // TBitmap32PaintHost
  44. //
  45. //------------------------------------------------------------------------------
  46. // An example implementation of IBitmap32PaintHost using TImage32 or TImgView32.
  47. //------------------------------------------------------------------------------
  48. type
  49. TBitmap32PaintHost = class(TInterfacedObject,
  50. IBitmap32PaintHost,
  51. IBitmap32PaintFeatureCursor,
  52. IBitmap32PaintFeatureVectorCursor)
  53. strict private
  54. FImage: TCustomImage32;
  55. strict private
  56. FPaintLayer: TBitmapLayer;
  57. strict private
  58. FColorPrimary: TColor32;
  59. FColorSecondary: TColor32;
  60. strict private
  61. // Cursor
  62. FCursorLayer: TCustomLayer;
  63. FToolCursorActive: boolean;
  64. FHasVectorCursor: boolean;
  65. FVectorCursorVisible: boolean;
  66. FDefaultCursor: TCursor;
  67. FCurrentCursor: TCursor;
  68. strict private
  69. // IBitmap32PaintHost
  70. function GetPaintLayer: TBitmapLayer;
  71. procedure SetPaintLayer(const Value: TBitmapLayer);
  72. function GetColorPrimary: TColor32;
  73. procedure SetColorPrimary(const Value: TColor32);
  74. function GetColorSecondary: TColor32;
  75. procedure SetColorSecondary(const Value: TColor32);
  76. function GetMagnification: Single;
  77. procedure SetMagnification(const Value: Single);
  78. function ViewPortToScreen(const APoint: TPoint): TPoint;
  79. function ScreenToViewPort(const APoint: TPoint): TPoint;
  80. function ViewPortToBitmap(const APoint: TPoint; SnapToNearest: boolean = True): TPoint; overload;
  81. function ViewPortToBitmap(const APoint: TFloatPoint): TFloatPoint; overload;
  82. function BitmapToViewPort(const APoint: TPoint): TPoint;
  83. function GetToolSettings(const AToolKey: string): ISettingValues;
  84. function CreateToolContext(const APaintTool: IBitmap32PaintTool): IBitmap32PaintToolContext; virtual;
  85. procedure Changed(const Action: string);
  86. private
  87. // IBitmap32PaintFeatureCursor
  88. procedure ShowToolCursor(AShow, ATransientChange: Boolean);
  89. procedure SetToolCursor(NewCursor: TCursor);
  90. private
  91. // IBitmap32PaintFeatureVectorCursor
  92. function SetToolVectorCursor(const Polygon: TArrayOfFixedPoint; const Hotspot: TPoint; Color: TColor32 = clTrBlack32; const StipplePattern: TArrayOfColor32 = []): boolean;
  93. procedure MoveToolVectorCursor(const APos: TPoint);
  94. public
  95. constructor Create(AImage: TCustomImage32);
  96. end;
  97. //------------------------------------------------------------------------------
  98. //------------------------------------------------------------------------------
  99. //------------------------------------------------------------------------------
  100. implementation
  101. uses
  102. {$if defined(MSWINDOWS)}
  103. Windows,
  104. {$ifend}
  105. {$if defined(UseInlining)}
  106. Types,
  107. {$ifend}
  108. GR32.Paint.ToolContext;
  109. //------------------------------------------------------------------------------
  110. //
  111. // TBitmap32PaintHost
  112. //
  113. //------------------------------------------------------------------------------
  114. constructor TBitmap32PaintHost.Create(AImage: TCustomImage32);
  115. begin
  116. inherited Create;
  117. FImage := AImage;
  118. end;
  119. //------------------------------------------------------------------------------
  120. function TBitmap32PaintHost.GetPaintLayer: TBitmapLayer;
  121. begin
  122. Result := FPaintLayer;
  123. end;
  124. procedure TBitmap32PaintHost.SetPaintLayer(const Value: TBitmapLayer);
  125. begin
  126. FPaintLayer := Value;
  127. end;
  128. //------------------------------------------------------------------------------
  129. function TBitmap32PaintHost.GetColorPrimary: TColor32;
  130. begin
  131. Result := FColorPrimary;
  132. end;
  133. function TBitmap32PaintHost.GetColorSecondary: TColor32;
  134. begin
  135. Result := FColorSecondary;
  136. end;
  137. procedure TBitmap32PaintHost.SetColorPrimary(const Value: TColor32);
  138. begin
  139. FColorPrimary := Value;
  140. end;
  141. procedure TBitmap32PaintHost.SetColorSecondary(const Value: TColor32);
  142. begin
  143. FColorSecondary := Value;
  144. end;
  145. //------------------------------------------------------------------------------
  146. function TBitmap32PaintHost.ViewPortToBitmap(const APoint: TPoint; SnapToNearest: boolean): TPoint;
  147. var
  148. SnapThreshold: integer;
  149. begin
  150. if (SnapToNearest) then
  151. begin
  152. SnapThreshold := Trunc((FImage.Scale-1) / 2);
  153. // Snap the coordinates to the nearest pixel
  154. Result := GR32.Point(APoint.X + SnapThreshold, APoint.Y + SnapThreshold);
  155. end else
  156. Result := APoint;
  157. if (FPaintLayer <> nil) then
  158. Result := FPaintLayer.ControlToLayer(Result)
  159. else
  160. Result := FImage.ControlToBitmap(Result);
  161. end;
  162. function TBitmap32PaintHost.ViewPortToBitmap(const APoint: TFloatPoint): TFloatPoint;
  163. begin
  164. if (FPaintLayer <> nil) then
  165. Result := FPaintLayer.ControlToLayer(APoint)
  166. else
  167. Result := FImage.ControlToBitmap(APoint);
  168. end;
  169. function TBitmap32PaintHost.BitmapToViewPort(const APoint: TPoint): TPoint;
  170. begin
  171. if (FPaintLayer <> nil) then
  172. Result := FPaintLayer.LayerToControl(APoint)
  173. else
  174. Result := FImage.BitmapToControl(APoint);
  175. end;
  176. function TBitmap32PaintHost.ViewPortToScreen(const APoint: TPoint): TPoint;
  177. begin
  178. Result := FImage.ClientToScreen(APoint);
  179. end;
  180. function TBitmap32PaintHost.ScreenToViewPort(const APoint: TPoint): TPoint;
  181. begin
  182. Result := FImage.ScreenToClient(APoint);
  183. end;
  184. //------------------------------------------------------------------------------
  185. function TBitmap32PaintHost.CreateToolContext(const APaintTool: IBitmap32PaintTool): IBitmap32PaintToolContext;
  186. begin
  187. if (FPaintLayer <> nil) then
  188. Result := TBitmap32PaintToolContext.Create(Self, APaintTool, FPaintLayer.Bitmap)
  189. else
  190. Result := TBitmap32PaintToolContext.Create(Self, APaintTool, FImage.Bitmap);
  191. end;
  192. //------------------------------------------------------------------------------
  193. function TBitmap32PaintHost.GetMagnification: Single;
  194. begin
  195. Result := FImage.Scale;
  196. end;
  197. procedure TBitmap32PaintHost.SetMagnification(const Value: Single);
  198. begin
  199. FImage.Scale := Value;
  200. end;
  201. //------------------------------------------------------------------------------
  202. procedure TBitmap32PaintHost.SetToolCursor(NewCursor: TCursor);
  203. procedure UpdateCursor;
  204. {$if defined(MSWINDOWS)}
  205. var
  206. p: TPoint;
  207. {$ifend}
  208. begin
  209. {$if defined(MSWINDOWS)}
  210. GetCursorPos(p);
  211. SetCursorPos(p.X, p.Y);
  212. {$ifend}
  213. end;
  214. begin
  215. if (FCurrentCursor <> FImage.Cursor) then
  216. // Something else changed the cursor. Use the current value as the default.
  217. FDefaultCursor := FImage.Cursor;
  218. if (NewCursor = crDefault) then
  219. NewCursor := FDefaultCursor;
  220. FCurrentCursor := NewCursor;
  221. if (FImage.Cursor <> NewCursor) then
  222. begin
  223. FImage.Cursor := NewCursor;
  224. // CM_CURSORCHANGED should force the cursor to update, but doesn't
  225. // ... so we have to resort to this ugly hack:
  226. UpdateCursor;
  227. end;
  228. end;
  229. procedure TBitmap32PaintHost.ShowToolCursor(AShow, ATransientChange: Boolean);
  230. begin
  231. if (not ATransientChange) then
  232. begin
  233. FToolCursorActive := AShow;
  234. if (not FToolCursorActive) then
  235. begin
  236. FHasVectorCursor := False;
  237. SetToolCursor(FDefaultCursor);
  238. end;
  239. end else
  240. FVectorCursorVisible := AShow;
  241. if (FCursorLayer <> nil) then
  242. FCursorLayer.Visible := FToolCursorActive and FVectorCursorVisible;
  243. end;
  244. //------------------------------------------------------------------------------
  245. function TBitmap32PaintHost.SetToolVectorCursor(const Polygon: TArrayOfFixedPoint; const Hotspot: TPoint; Color: TColor32; const StipplePattern: TArrayOfColor32): boolean;
  246. begin
  247. Result := True;
  248. if (FCursorLayer = nil) then
  249. begin
  250. // Not implemented in this example (yet)
  251. (*
  252. CursorLayer.Polygon := Polygon;
  253. CursorLayer.Hotspot := Hotspot;
  254. CursorLayer.Color := Color;
  255. CursorLayer.StipplePattern := StipplePattern;
  256. *)
  257. end;
  258. FHasVectorCursor := True;
  259. FVectorCursorVisible := True;
  260. end;
  261. procedure TBitmap32PaintHost.MoveToolVectorCursor(const APos: TPoint);
  262. begin
  263. // Not implemented in this example (yet)
  264. end;
  265. //------------------------------------------------------------------------------
  266. function TBitmap32PaintHost.GetToolSettings(const AToolKey: string): ISettingValues;
  267. begin
  268. // Not implemented in this example (yet)
  269. Result := nil;
  270. end;
  271. procedure TBitmap32PaintHost.Changed(const Action: string);
  272. begin
  273. end;
  274. //------------------------------------------------------------------------------
  275. end.