Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 

399 строки
15 KiB

  1. library libTextSuite;
  2. {$mode objfpc}{$H+}
  3. uses
  4. Classes, SysUtils,
  5. utsTextSuite, utsTypes, utsRendererOpenGL, utsRendererOpenGLES,
  6. uutlGenerics;
  7. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  8. //external types and contstants/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  9. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  10. type
  11. {$Z4}
  12. TltsErrorCode = (
  13. ltsErrUnknown = -1,
  14. ltsErrNone = 0,
  15. // misc
  16. ltsErrNotInitialized = 1,
  17. ltsErrInvalidEnum = 2,
  18. ltsErrInvalidValue = 3,
  19. ltsErrInvalidOperation = 4,
  20. // invalid handles
  21. ltsErrInvalidContextHandle = 100,
  22. ltsErrInvalidRendererHandle = 101
  23. );
  24. {$Z4}
  25. TltsRendererType = (
  26. ltsRendererOpenGL,
  27. ltsRendererOpenGLES,
  28. ltsRendererCustom
  29. );
  30. TltsContextHandle = Pointer;
  31. TltsRendererHandle = Pointer;
  32. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  33. //internal types and contstants/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  34. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  35. TltsContext = class(TtsContext)
  36. public
  37. destructor Destroy; override;
  38. end;
  39. TtsContextHashSet = specialize TutlHashSet<TtsContext>;
  40. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  41. TltsRendererOpenGL = class(TtsRendererOpenGL)
  42. public
  43. // TODO destructor Destroy; override;
  44. end;
  45. TltsRendererOpenGLES = class(TtsRendererOpenGLES)
  46. public
  47. // TODO destructor Destroy; override;
  48. end;
  49. { TODO
  50. TltsRendererCustom = class(TtsRenderer)
  51. protected
  52. function CreateRenderRef(const aChar: TtsChar; const aCharImage: TtsImage): TtsCharRenderRef; override;
  53. procedure FreeRenderRef(const aCharRef: TtsCharRenderRef); override;
  54. procedure BeginRender; override;
  55. procedure EndRender; override;
  56. procedure SetDrawPos(const X, Y: Integer); override;
  57. function GetDrawPos: TtsPosition; override;
  58. procedure MoveDrawPos(const X, Y: Integer); override;
  59. procedure SetColor(const aColor: TtsColor4f); override;
  60. procedure Render(const aCharRef: TtsCharRenderRef; const aForcedWidth: Integer = 0); override;
  61. public
  62. // TODO destructor Destroy; override;
  63. end;
  64. }
  65. TtsRendererHashSet = specialize TutlHashSet<TtsRenderer>;
  66. var
  67. IsInitilized: Boolean = false;
  68. Contexts: TtsContextHashSet = nil;
  69. Renderers: TtsRendererHashSet = nil;
  70. LastErrorCode: TltsErrorCode = ltsErrNone;
  71. LastErrorMsg: String;
  72. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  73. //helper methods////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  74. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  75. procedure SetLastError(const aEx: Exception);
  76. begin
  77. LastErrorCode := ltsErrUnknown;
  78. LastErrorMsg := aEx.Message;
  79. end;
  80. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  81. procedure SetLastError(const aErrorCode: TltsErrorCode; const aErrorMsg: String);
  82. begin
  83. LastErrorCode := aErrorCode;
  84. LastErrorMsg := aErrorMsg;
  85. end;
  86. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  87. function CheckIfInitialized: Boolean;
  88. begin
  89. result := IsInitilized;
  90. if not result then
  91. SetLastError(ltsErrNotInitialized, 'libTextSuite has not been initialized. call ltsInitialize before using any other methods.');
  92. end;
  93. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  94. function CheckContextHandle(const aHandle: TltsContextHandle; out aContext: TtsContext): Boolean;
  95. begin
  96. result := CheckIfInitialized;
  97. if result then begin
  98. aContext := TltsContext(aHandle);
  99. result := Contexts.Contains(aContext);
  100. if not result then
  101. SetLastError(ltsErrInvalidContextHandle, Format('0x%.16x is not a valid context handle', [{%H-}PtrUInt(aHandle)]));
  102. end;
  103. end;
  104. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  105. function CheckRendererHandle(const aHandle: TltsContextHandle; out aRenderer: TtsRenderer): Boolean;
  106. begin
  107. result := CheckIfInitialized;
  108. if result then begin
  109. aRenderer := TtsRenderer(aHandle);
  110. result := Renderers.Contains(aRenderer);
  111. if not result then
  112. SetLastError(ltsErrInvalidRendererHandle, Format('0x%.16x is not a valid renderer handle', [{%H-}PtrUInt(aHandle)]));
  113. end;
  114. end;
  115. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  116. function ValidateCodePage(const aValue: TtsCodePage): Boolean;
  117. begin
  118. result := (aValue >= Low(TtsCodePage)) and (aValue <= High(TtsCodePage));
  119. end;
  120. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  121. function ValidateFormat(const aValue: TtsFormat): Boolean;
  122. begin
  123. result := (aValue >= Low(TtsFormat)) and (aValue <= High(TtsFormat));
  124. end;
  125. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  126. //Context///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  127. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  128. function ltsContextCreate: TltsContextHandle; stdcall;
  129. var
  130. c: TltsContext;
  131. begin
  132. try
  133. result := nil;
  134. if not CheckIfInitialized then
  135. exit;
  136. c := TltsContext.Create;
  137. Contexts.Add(c);
  138. result := c;
  139. except
  140. on ex: Exception do begin
  141. SetLastError(ex);
  142. result := nil;
  143. end;
  144. end;
  145. end;
  146. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  147. function ltsContextGetCodePage(const aHandle: TltsContextHandle; var aCodePage: TtsCodePage): TltsErrorCode; stdcall;
  148. var
  149. c: TtsContext;
  150. begin
  151. try
  152. result := ltsErrNone;
  153. if CheckContextHandle(aHandle, c)
  154. then aCodePage := c.CodePage
  155. else result := LastErrorCode;
  156. except
  157. on ex: Exception do begin
  158. SetLastError(ex);
  159. result := LastErrorCode;
  160. end;
  161. end;
  162. end;
  163. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  164. function ltsContextGetDefaultChar(const aHandle: TltsContextHandle; var aValue: WideChar): TltsErrorCode; stdcall;
  165. var
  166. c: TtsContext;
  167. begin
  168. try
  169. result := ltsErrNone;
  170. if CheckContextHandle(aHandle, c)
  171. then aValue := c.CodePageDefault
  172. else result := LastErrorCode;
  173. except
  174. on ex: Exception do begin
  175. SetLastError(ex);
  176. result := LastErrorCode;
  177. end;
  178. end;
  179. end;
  180. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  181. function ltsContextSetCodePage(const aHandle: TltsContextHandle; const aCodePage: TtsCodePage): TltsErrorCode; stdcall;
  182. var
  183. c: TtsContext;
  184. begin
  185. try
  186. result := ltsErrNone;
  187. if CheckContextHandle(aHandle, c) then begin
  188. if not ValidateCodePage(aCodePage) then begin
  189. SetLastError(ltsErrInvalidEnum, Format('%d is not a valid enum value for CodePage', [aCodePage]));
  190. result := LastErrorCode;
  191. end else
  192. c.CodePage := aCodePage;
  193. end else
  194. result := LastErrorCode;
  195. except
  196. on ex: Exception do begin
  197. SetLastError(ex);
  198. result := LastErrorCode;
  199. end;
  200. end;
  201. end;
  202. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  203. function ltsContextSetDefaultChar(const aHandle: TltsContextHandle; const aValue: WideChar): TltsErrorCode; stdcall;
  204. var
  205. c: TtsContext;
  206. begin
  207. try
  208. result := ltsErrNone;
  209. if CheckContextHandle(aHandle, c)
  210. then c.CodePageDefault := aValue
  211. else result := LastErrorCode;
  212. except
  213. on ex: Exception do begin
  214. SetLastError(ex);
  215. result := LastErrorCode;
  216. end;
  217. end;
  218. end;
  219. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  220. function ltsContextDestroy(const aHandle: TltsContextHandle): TltsErrorCode; stdcall;
  221. var
  222. c: TtsContext;
  223. begin
  224. try
  225. result := ltsErrNone;
  226. if CheckContextHandle(aHandle, c)
  227. then Contexts.Remove(c)
  228. else result := LastErrorCode;
  229. except
  230. on ex: Exception do begin
  231. SetLastError(ex);
  232. result := LastErrorCode;
  233. end;
  234. end;
  235. end;
  236. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  237. //Renderer//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  238. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  239. function ltsRendererCreate(const aHandle: TltsContextHandle; const aType: TltsRendererType; const aFormat: TtsFormat): TltsRendererHandle; stdcall;
  240. var
  241. c: TtsContext;
  242. r: TtsRenderer;
  243. begin
  244. try
  245. result := nil;
  246. if not CheckContextHandle(aHandle, c) then
  247. exit;
  248. if not ValidateFormat(aFormat) then begin
  249. SetLastError(ltsErrInvalidEnum, Format('%d is not a valid format', [aFormat]));
  250. exit;
  251. end;
  252. case aType of
  253. ltsRendererOpenGL: r := TltsRendererOpenGL.Create(c, aFormat);
  254. ltsRendererOpenGLES: r := TltsRendererOpenGLES.Create(c, aFormat);
  255. // TODO ltsRendererCustom: r := TltsRendererCustom.Create(c, aFormat);
  256. else
  257. SetLastError(ltsErrInvalidEnum, Format('%d is not a valid renderer type', [aType]));
  258. exit;
  259. end;
  260. Renderers.Add(r);
  261. result := r;
  262. except
  263. on ex: Exception do begin
  264. SetLastError(ex);
  265. result := nil;
  266. end;
  267. end;
  268. end;
  269. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  270. function ltsRendererDestroy(const aHandle: TltsRendererHandle): TltsErrorCode; stdcall;
  271. var
  272. r: TtsRenderer;
  273. begin
  274. try
  275. result := ltsErrNone;
  276. if CheckRendererHandle(aHandle, r)
  277. then Renderers.Remove(r)
  278. else result := LastErrorCode;
  279. except
  280. on ex: Exception do begin
  281. SetLastError(ex);
  282. result := LastErrorCode;
  283. end;
  284. end;
  285. end;
  286. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  287. //Global////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  288. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  289. function ltsInitialize: TltsErrorCode; stdcall;
  290. begin
  291. try
  292. Contexts := TtsContextHashSet.Create(true);
  293. Renderers := TtsRendererHashSet.Create(true);
  294. IsInitilized := true;
  295. result := ltsErrNone;
  296. except
  297. on ex: Exception do begin
  298. SetLastError(ex);
  299. result := LastErrorCode;
  300. end;
  301. end;
  302. end;
  303. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  304. function ltsGetLastErrorCode: TltsErrorCode; stdcall;
  305. begin
  306. result := LastErrorCode;
  307. end;
  308. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  309. function ltsGetLastErrorMsg: PAnsiChar; stdcall;
  310. begin
  311. result := PAnsiChar(LastErrorMsg);
  312. end;
  313. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  314. function ltsFinalize: TltsErrorCode; stdcall;
  315. begin
  316. try
  317. IsInitilized := false;
  318. FreeAndNil(Renderers);
  319. FreeAndNil(Contexts);
  320. result := ltsErrNone;
  321. except
  322. on ex: Exception do begin
  323. SetLastError(ex);
  324. result := LastErrorCode;
  325. end;
  326. end;
  327. end;
  328. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  329. exports
  330. ltsContextCreate,
  331. ltsContextGetCodePage,
  332. ltsContextGetDefaultChar,
  333. ltsContextSetCodePage,
  334. ltsContextSetDefaultChar,
  335. ltsContextDestroy,
  336. ltsRendererCreate,
  337. ltsRendererDestroy,
  338. ltsInitialize,
  339. ltsGetLastErrorCode,
  340. ltsGetLastErrorMsg,
  341. ltsFinalize;
  342. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  343. //TltsContext///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  344. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  345. destructor TltsContext.Destroy;
  346. var
  347. i: Integer;
  348. begin
  349. if Assigned(Renderers) then begin
  350. for i := fRenderers.Count-1 downto 0 do
  351. Renderers.Remove(fRenderers[i] as TtsRenderer);
  352. end;
  353. // TODO cleanup generators
  354. inherited Destroy;
  355. end;
  356. end.