您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 

313 行
14 KiB

  1. unit ultsUtils;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils,
  6. uutlGenerics,
  7. ultsTypes,
  8. utsTextSuite;
  9. type
  10. TtsPostProcessorClass = class of TtsPostProcessor;
  11. procedure SetLastError(const aEx: Exception);
  12. procedure SetLastError(const aErrorCode: TltsErrorCode; const aErrorMsg: String);
  13. function CheckIfInitialized: Boolean;
  14. function CheckContextHandle(const aHandle: TltsContextHandle; out aContext: TtsContext): Boolean;
  15. function CheckRendererHandle(const aHandle: TltsContextHandle; out aRenderer: TtsRenderer): Boolean;
  16. function CheckTextBlockHandle(const aHandle: TltsTextBlockHandle; out aTextBlock: TtsTextBlock): Boolean;
  17. function CheckFontHandle(const aHandle: TltsFontHandle; out aFont: TtsFont): Boolean;
  18. function CheckFontCreatorHandle(const aHandle: TltsFontCreatorHandle; out aFontCreator: TtsFontCreator): Boolean;
  19. function CheckImageHandle(const aHandle: TltsImageHandle; out aImage: TtsImage): Boolean;
  20. function CheckPostProcessorHandle(const aHandle: TltsPostProcessorHandle; const aType: TtsPostProcessorClass; out aPostProcessor): Boolean;
  21. procedure AddReference(const aType: TltsObjectType; const aRef: TObject);
  22. procedure DelReference(const aType: TltsObjectType; const aRef: TObject);
  23. procedure DelReference(const aRef: TObject);
  24. function ValidateCodePage(const aValue: TtsCodePage): Boolean;
  25. function ValidateFormat(const aValue: TtsFormat): Boolean;
  26. function ValidateCharRangeUsage(const aValue: TtsCharRangeUsage): Boolean;
  27. procedure Initialize;
  28. procedure Finalize;
  29. type
  30. TltsStreamImpl = class(TStream)
  31. private
  32. fStream: PltsStream;
  33. public
  34. function Read(var Buffer; Count: Longint): Longint; override;
  35. function Seek(Offset: Longint; Origin: Word): Longint; override; overload;
  36. constructor Create(const aStream: PltsStream);
  37. end;
  38. var
  39. LastErrorCode: TltsErrorCode = ltsErrNone;
  40. LastErrorMsg: String;
  41. implementation
  42. type
  43. TtsContextHashSet = specialize TutlHashSet<TtsContext>;
  44. TtsRendererHashSet = specialize TutlHashSet<TtsRenderer>;
  45. TtsTextBlockHashSet = specialize TutlHashSet<TtsTextBlock>;
  46. TtsFontHashSet = specialize TutlHashSet<TtsFont>;
  47. TtsFontCreatorHashSet = specialize TutlHashSet<TtsFontCreator>;
  48. TtsImageHashSet = specialize TutlHashSet<TtsImage>;
  49. TtsPostProcessorHashSet = specialize TutlHashSet<TtsPostProcessor>;
  50. var
  51. IsInitilized: Boolean = false;
  52. Contexts: TtsContextHashSet = nil;
  53. Renderers: TtsRendererHashSet = nil;
  54. TextBlocks: TtsTextBlockHashSet = nil;
  55. Fonts: TtsFontHashSet = nil;
  56. FontCreators: TtsFontCreatorHashSet = nil;
  57. Images: TtsImageHashSet = nil;
  58. PostProcessors: TtsPostProcessorHashSet = nil;
  59. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  60. procedure SetLastError(const aEx: Exception);
  61. begin
  62. LastErrorCode := ltsErrUnknown;
  63. LastErrorMsg := aEx.Message;
  64. end;
  65. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  66. procedure SetLastError(const aErrorCode: TltsErrorCode; const aErrorMsg: String);
  67. begin
  68. LastErrorCode := aErrorCode;
  69. LastErrorMsg := aErrorMsg;
  70. end;
  71. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  72. function CheckIfInitialized: Boolean;
  73. begin
  74. result := IsInitilized;
  75. if not result then
  76. SetLastError(ltsErrNotInitialized, 'libTextSuite has not been initialized. call ltsInitialize before using any other methods.');
  77. end;
  78. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  79. function CheckContextHandle(const aHandle: TltsContextHandle; out aContext: TtsContext): Boolean;
  80. begin
  81. result := CheckIfInitialized;
  82. if result then begin
  83. aContext := TtsContext(aHandle);
  84. result := Contexts.Contains(aContext);
  85. if not result then
  86. SetLastError(ltsErrInvalidContextHandle, Format('0x%.16x is not a valid context handle', [{%H-}PtrUInt(aHandle)]));
  87. end;
  88. end;
  89. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  90. function CheckRendererHandle(const aHandle: TltsContextHandle; out aRenderer: TtsRenderer): Boolean;
  91. begin
  92. result := CheckIfInitialized;
  93. if result then begin
  94. aRenderer := TtsRenderer(aHandle);
  95. result := Renderers.Contains(aRenderer);
  96. if not result then
  97. SetLastError(ltsErrInvalidRendererHandle, Format('0x%.16x is not a valid renderer handle', [{%H-}PtrUInt(aHandle)]));
  98. end;
  99. end;
  100. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  101. function CheckTextBlockHandle(const aHandle: TltsTextBlockHandle; out aTextBlock: TtsTextBlock): Boolean;
  102. begin
  103. result := CheckIfInitialized;
  104. if result then begin
  105. aTextBlock := TtsTextBlock(aHandle);
  106. result := TextBlocks.Contains(aTextBlock);
  107. if not result then
  108. SetLastError(ltsErrInvalidTextBlockHandle, Format('0x%.16x is no a valid text block handle', [{%H-}PtrUInt(aHandle)]));
  109. end;
  110. end;
  111. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  112. function CheckFontHandle(const aHandle: TltsFontHandle; out aFont: TtsFont): Boolean;
  113. begin
  114. result := CheckIfInitialized;
  115. if result then begin
  116. aFont := TtsFont(aHandle);
  117. result := Fonts.Contains(aFont);
  118. if not result then
  119. SetLastError(ltsErrInvalidFontHandle, Format('0x%.16x is no a valid font handle', [{%H-}PtrUInt(aHandle)]));
  120. end;
  121. end;
  122. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  123. function CheckFontCreatorHandle(const aHandle: TltsFontCreatorHandle; out aFontCreator: TtsFontCreator): Boolean;
  124. begin
  125. result := CheckIfInitialized;
  126. if result then begin
  127. aFontCreator := TtsFontCreator(aHandle);
  128. result := FontCreators.Contains(aFontCreator);
  129. if not result then
  130. SetLastError(ltsErrInvalidFontCreatorHandle, Format('0x%.16x is no a valid font creator handle', [{%H-}PtrUInt(aHandle)]));
  131. end;
  132. end;
  133. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  134. function CheckImageHandle(const aHandle: TltsImageHandle; out aImage: TtsImage): Boolean;
  135. begin
  136. result := CheckIfInitialized;
  137. if result then begin
  138. aImage := TtsImage(aHandle);
  139. result := Images.Contains(aImage);
  140. if not result then
  141. SetLastError(ltsErrInvalidImageHandle, Format('0x%.16x is no a valid image handle', [{%H-}PtrUInt(aHandle)]));
  142. end;
  143. end;
  144. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  145. function CheckPostProcessorHandle(const aHandle: TltsPostProcessorHandle; const aType: TtsPostProcessorClass; out aPostProcessor): Boolean;
  146. begin
  147. result := CheckIfInitialized;
  148. if result then begin
  149. TtsPostProcessor(aPostProcessor) := TtsPostProcessor(aHandle);
  150. result := PostProcessors.Contains(TtsPostProcessor(aPostProcessor));
  151. if not result then begin
  152. SetLastError(ltsErrInvalidPostProcHandle, Format('0x%.16x is no a valid image handle', [{%H-}PtrUInt(aHandle)]));
  153. exit;
  154. end;
  155. result := (TtsPostProcessor(aPostProcessor) is aType);
  156. if not result then begin
  157. SetLastError(ltsErrInvalidType, Format('0x%.16x is no a %s post processor', [{%H-}PtrUInt(aHandle), aType.ClassName]));
  158. exit;
  159. end;
  160. end;
  161. end;
  162. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  163. procedure AddReference(const aType: TltsObjectType; const aRef: TObject);
  164. begin
  165. case aType of
  166. ltsObjTypeContext: Contexts.Add(aRef as TtsContext);
  167. ltsObjTypeRenderer: Renderers.Add(aRef as TtsRenderer);
  168. ltsObjTypeFont: Fonts.Add(aRef as TtsFont);
  169. ltsObjTypeTextBlock: TextBlocks.Add(aRef as TtsTextBlock);
  170. ltsObjTypeFontCreator: FontCreators.Add(aRef as TtsFontCreator);
  171. ltsObjTypeImage: Images.Add(aRef as TtsImage);
  172. ltsObjTypePostProcessor: PostProcessors.Add(aRef as TtsPostProcessor);
  173. end;
  174. end;
  175. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  176. procedure DelReference(const aType: TltsObjectType; const aRef: TObject);
  177. begin
  178. case aType of
  179. ltsObjTypeContext: Contexts.Remove(aRef as TtsContext);
  180. ltsObjTypeRenderer: Renderers.Remove(aRef as TtsRenderer);
  181. ltsObjTypeFont: Fonts.Remove(aRef as TtsFont);
  182. ltsObjTypeTextBlock: TextBlocks.Remove(aRef as TtsTextBlock);
  183. ltsObjTypeFontCreator: FontCreators.Remove(aRef as TtsFontCreator);
  184. ltsObjTypeImage: Images.Remove(aRef as TtsImage);
  185. ltsObjTypePostProcessor: PostProcessors.Remove(aRef as TtsPostProcessor);
  186. end;
  187. end;
  188. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  189. procedure DelReference(const aRef: TObject);
  190. begin
  191. if (aRef is TtsRenderer) then
  192. DelReference(ltsObjTypeRenderer, aRef)
  193. else if (aRef is TtsTextBlock) then
  194. DelReference(ltsObjTypeTextBlock, aRef)
  195. else if (aRef is TtsFont) then
  196. DelReference(ltsObjTypeFont, aRef)
  197. else if (aRef is TtsContext) then
  198. DelReference(ltsObjTypeContext, aRef)
  199. else if (aRef is TtsFontCreator) then
  200. DelReference(ltsObjTypeFontCreator, aRef)
  201. else if (aRef is TtsImage) then
  202. DelReference(ltsObjTypeImage, aRef)
  203. else if (aRef is TtsPostProcessor) then
  204. DelReference(ltsObjTypePostProcessor, aRef);
  205. end;
  206. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  207. function ValidateCodePage(const aValue: TtsCodePage): Boolean;
  208. begin
  209. result := (aValue >= Low(TtsCodePage)) and (aValue <= High(TtsCodePage));
  210. if not result then
  211. SetLastError(ltsErrInvalidEnum, Format('%d is not a valid code page value', [aValue]));
  212. end;
  213. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  214. function ValidateFormat(const aValue: TtsFormat): Boolean;
  215. begin
  216. result := (aValue >= Low(TtsFormat)) and (aValue <= High(TtsFormat));
  217. if not result then
  218. SetLastError(ltsErrInvalidEnum, Format('%d is not a valid format value', [aValue]));
  219. end;
  220. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  221. function ValidateCharRangeUsage(const aValue: TtsCharRangeUsage): Boolean;
  222. begin
  223. result := (aValue >= Low(TtsCharRangeUsage)) and (aValue <= High(TtsCharRangeUsage));
  224. if not result then
  225. SetLastError(ltsErrInvalidEnum, Format('%d is not a valid char range usage value', [aValue]));
  226. end;
  227. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  228. procedure Initialize;
  229. begin
  230. Contexts := TtsContextHashSet.Create(true);
  231. Renderers := TtsRendererHashSet.Create(false);
  232. TextBlocks := TtsTextBlockHashSet.Create(false);
  233. FontCreators := TtsFontCreatorHashSet.Create(false);
  234. Fonts := TtsFontHashSet.Create(false);
  235. Images := TtsImageHashSet.Create(false);
  236. PostProcessors := TtsPostProcessorHashSet.Create(false);
  237. IsInitilized := true;
  238. end;
  239. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  240. procedure Finalize;
  241. begin
  242. IsInitilized := false;
  243. FreeAndNil(PostProcessors);
  244. FreeAndNil(Images);
  245. FreeAndNil(TextBlocks);
  246. FreeAndNil(Fonts);
  247. FreeAndNil(FontCreators);
  248. FreeAndNil(Renderers);
  249. FreeAndNil(Contexts);
  250. end;
  251. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  252. //TltsStreamImpl////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  253. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  254. function TltsStreamImpl.Read(var Buffer; Count: Longint): Longint;
  255. begin
  256. if not Assigned(fStream) or not Assigned(fStream^.read)
  257. then result := inherited Read(Buffer, Count)
  258. else result := fStream^.read(fStream^.args, @buffer, Count);
  259. end;
  260. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  261. function TltsStreamImpl.Seek(Offset: Longint; Origin: Word): Longint;
  262. begin
  263. if not Assigned(fStream) or not Assigned(fStream^.seek)
  264. then result := inherited Seek(Offset, Origin)
  265. else result := fStream^.seek(fStream^.args, TltsStreamOrigin(Origin), Offset);
  266. end;
  267. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  268. constructor TltsStreamImpl.Create(const aStream: PltsStream);
  269. begin
  270. inherited Create;
  271. fStream := aStream;
  272. end;
  273. end.