fpfonttextmapping.pp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. {
  2. This file is part of the Free Component Library (FCL)
  3. Copyright (c) 2016 by Graeme Geldenhuys
  4. This unit defines classes that manage font glyph IDs and unicode
  5. character codes.
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {$IFNDEF FPC_DOTTEDUNITS}
  13. unit FPFontTextMapping;
  14. {$ENDIF FPC_DOTTEDUNITS}
  15. {$mode objfpc}{$H+}
  16. interface
  17. {$IFDEF FPC_DOTTEDUNITS}
  18. uses
  19. System.Classes,
  20. System.SysUtils,
  21. System.Contnrs;
  22. {$ELSE FPC_DOTTEDUNITS}
  23. uses
  24. Classes,
  25. SysUtils,
  26. contnrs;
  27. {$ENDIF FPC_DOTTEDUNITS}
  28. type
  29. TTextMapping = class(TObject)
  30. private
  31. FCharID: uint32;
  32. FGlyphID: uint32;
  33. FNewGlyphID: uint32;
  34. FGlyphData: TStream;
  35. FIsCompoundGlyph: boolean;
  36. public
  37. constructor Create;
  38. class function NewTextMap(const ACharID, AGlyphID: uint32): TTextMapping;
  39. property CharID: uint32 read FCharID write FCharID;
  40. property GlyphID: uint32 read FGlyphID write FGlyphID;
  41. property NewGlyphID: uint32 read FNewGlyphID write FNewGlyphID;
  42. property GlyphData: TStream read FGlyphData write FGlyphData;
  43. property IsCompoundGlyph: boolean read FIsCompoundGlyph write FIsCompoundGlyph;
  44. end;
  45. TTextMappingList = class(TObject)
  46. private
  47. FList: TFPObjectList;
  48. function GetCount: Integer;
  49. protected
  50. function GetItem(AIndex: Integer): TTextMapping; virtual;
  51. procedure SetItem(AIndex: Integer; AValue: TTextMapping); virtual;
  52. public
  53. constructor Create;
  54. destructor Destroy; override;
  55. function Add(AObject: TTextMapping): Integer; overload;
  56. function Add(const ACharID, AGlyphID: uint32): Integer; overload;
  57. function Contains(const AGlyphID: uint32): boolean;
  58. function ContainsCharID(const AID: uint32): boolean;
  59. function GetNewGlyphID(const ACharID: uint32): uint32;
  60. function GetMaxCharID: uint32;
  61. function GetMaxGlyphID: uint32;
  62. procedure Insert(const AIndex: integer; const ACharID, AGlyphID: uint32);
  63. procedure Sort;
  64. property Count: Integer read GetCount;
  65. property Items[AIndex: Integer]: TTextMapping read GetItem write SetItem; default;
  66. end;
  67. implementation
  68. { TTextMapping }
  69. constructor TTextMapping.Create;
  70. begin
  71. FGlyphData := nil;
  72. FCharID := 0;
  73. FGlyphID := 0;
  74. FNewGlyphID := 0;
  75. FIsCompoundGlyph := False;
  76. end;
  77. class function TTextMapping.NewTextMap(const ACharID, AGlyphID: uint32): TTextMapping;
  78. begin
  79. Result := TTextMapping.Create;
  80. Result.CharID := ACharID;
  81. Result.GlyphID := AGlyphID;
  82. end;
  83. { TTextMappingList }
  84. function TTextMappingList.GetCount: Integer;
  85. begin
  86. Result := FList.Count;
  87. end;
  88. function TTextMappingList.GetItem(AIndex: Integer): TTextMapping;
  89. begin
  90. Result := TTextMapping(FList.Items[AIndex]);
  91. end;
  92. procedure TTextMappingList.SetItem(AIndex: Integer; AValue: TTextMapping);
  93. begin
  94. FList.Items[AIndex] := AValue;
  95. end;
  96. constructor TTextMappingList.Create;
  97. begin
  98. FList := TFPObjectList.Create(True);
  99. end;
  100. destructor TTextMappingList.Destroy;
  101. begin
  102. FList.Free;
  103. inherited Destroy;
  104. end;
  105. function TTextMappingList.Add(AObject: TTextMapping): Integer;
  106. var
  107. i: integer;
  108. begin
  109. Result := -1;
  110. for i := 0 to FList.Count-1 do
  111. begin
  112. if TTextMapping(FList.Items[i]).CharID = AObject.CharID then
  113. Exit; // mapping already exists
  114. end;
  115. Result := FList.Add(AObject);
  116. end;
  117. function TTextMappingList.Add(const ACharID, AGlyphID: uint32): Integer;
  118. var
  119. o: TTextMapping;
  120. begin
  121. o := TTextMapping.Create;
  122. o.CharID := ACharID;
  123. o.GlyphID := AGlyphID;
  124. Result := Add(o);
  125. if Result = -1 then
  126. o.Free;
  127. end;
  128. function TTextMappingList.Contains(const AGlyphID: uint32): boolean;
  129. var
  130. i: integer;
  131. begin
  132. Result := False;
  133. for i := 0 to Count-1 do
  134. begin
  135. if Items[i].GlyphID = AGlyphID then
  136. begin
  137. Result := True;
  138. Exit;
  139. end;
  140. end;
  141. end;
  142. function TTextMappingList.ContainsCharID(const AID: uint32): boolean;
  143. var
  144. i: integer;
  145. begin
  146. Result := False;
  147. for i := 0 to Count-1 do
  148. begin
  149. if Items[i].CharID = AID then
  150. begin
  151. Result := True;
  152. Exit;
  153. end;
  154. end;
  155. end;
  156. function TTextMappingList.GetNewGlyphID(const ACharID: uint32): uint32;
  157. var
  158. i: integer;
  159. begin
  160. for i := 0 to Count-1 do
  161. begin
  162. if Items[i].CharID = ACharID then
  163. begin
  164. Result := Items[i].NewGlyphID;
  165. Exit;
  166. end;
  167. end;
  168. end;
  169. function TTextMappingList.GetMaxCharID: uint32;
  170. begin
  171. Sort;
  172. Result := Items[Count-1].CharID;
  173. end;
  174. function TTextMappingList.GetMaxGlyphID: uint32;
  175. var
  176. gid: uint32;
  177. i: integer;
  178. begin
  179. gid := 0;
  180. for i := 0 to Count-1 do
  181. begin
  182. if Items[i].GlyphID > gid then
  183. gid := Items[i].GlyphID;
  184. end;
  185. result := gid;
  186. end;
  187. procedure TTextMappingList.Insert(const AIndex: integer; const ACharID, AGlyphID: uint32);
  188. var
  189. o: TTextMapping;
  190. begin
  191. o := TTextMapping.Create;
  192. o.CharID := ACharID;
  193. o.GlyphID := AGlyphID;
  194. FList.Insert(AIndex, o);
  195. end;
  196. function CompareByCharID(A, B: TTextMapping): Integer; inline;
  197. begin
  198. if A.CharID < B.CharID then
  199. Result := -1
  200. else if A.CharID > B.CharID then
  201. Result := 1
  202. else
  203. Result := 0;
  204. end;
  205. function CompareByCharIDPtr(A, B: Pointer): Integer;
  206. begin
  207. Result := CompareByCharID(TTextMapping(A), TTextMapping(B));
  208. end;
  209. procedure TTextMappingList.Sort;
  210. begin
  211. FList.Sort(@CompareByCharIDPtr);
  212. end;
  213. end.