ttfdump.lpr 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. program ttfdump;
  2. {$mode objfpc}{$H+}
  3. {$codepage utf8}
  4. uses
  5. {$ifdef unix}cwstring,{$endif} // required for UnicodeString handling.
  6. Classes,
  7. SysUtils,
  8. CustApp,
  9. fpparsettf,
  10. FPFontTextMapping,
  11. fpTTFSubsetter;
  12. type
  13. TMyApplication = class(TCustomApplication)
  14. private
  15. FFontFile: TTFFileInfo;
  16. procedure DumpGlyphIndex;
  17. function GetGlyphIndicesString(const AText: UnicodeString): AnsiString; overload;
  18. function GetGlyphIndices(const AText: UnicodeString): TTextMappingList; overload;
  19. procedure CreateSubsetFontFile(const AList: TTextMappingList);
  20. protected
  21. procedure DoRun; override;
  22. public
  23. constructor Create(TheOwner: TComponent); override;
  24. destructor Destroy; override;
  25. procedure WriteHelp; virtual;
  26. end;
  27. TFriendClass = class(TTFFileInfo)
  28. end;
  29. { TMyApplication }
  30. procedure TMyApplication.DumpGlyphIndex;
  31. begin
  32. Writeln('FHHead.numberOfHMetrics = ', FFontFile.HHead.numberOfHMetrics);
  33. Writeln('Length(Chars[]) = ', Length(FFontFile.Chars));
  34. writeln;
  35. writeln('Glyph Index values:');
  36. Writeln(' U+0020 (space) = ', Format('%d (%0:4.4x)', [FFontFile.Chars[$0020]]));
  37. Writeln(' U+0021 (!) = ', Format('%d (%0:4.4x)', [FFontFile.Chars[$0021]]));
  38. Writeln(' U+0048 (H) = ', Format('%d (%0:4.4x)', [FFontFile.Chars[$0048]]));
  39. writeln;
  40. Writeln('Glyph widths:');
  41. Writeln(' 3 = ', TFriendClass(FFontFile).ToNatural(FFontFile.Widths[FFontFile.Chars[$0020]].AdvanceWidth));
  42. Writeln(' 4 = ', TFriendClass(FFontFile).ToNatural(FFontFile.Widths[FFontFile.Chars[$0021]].AdvanceWidth));
  43. Writeln(' H = ', TFriendClass(FFontFile).ToNatural(FFontFile.Widths[FFontFile.Chars[$0048]].AdvanceWidth));
  44. end;
  45. function TMyApplication.GetGlyphIndices(const AText: UnicodeString): TTextMappingList;
  46. var
  47. i: integer;
  48. c: uint16;
  49. begin
  50. if AText = '' then
  51. Exit;
  52. Result := TTextMappingList.Create;
  53. for i := 1 to Length(AText) do
  54. begin
  55. c := uint16(AText[i]);
  56. Result.Add(c, FFontFile.Chars[c]);
  57. end;
  58. end;
  59. procedure TMyApplication.CreateSubsetFontFile(const AList: TTextMappingList);
  60. var
  61. lSubset: TFontSubsetter;
  62. begin
  63. writeln;
  64. writeln('called CreateSubsetFontFile...');
  65. lSubset := TFontSubsetter.Create(FFontFile, AList);
  66. try
  67. lSubSet.SaveToFile(ExtractFileName(GetOptionValue('f'))+'.subset.ttf');
  68. finally
  69. FreeAndNil(lSubSet);
  70. end;
  71. end;
  72. function TMyApplication.GetGlyphIndicesString(const AText: UnicodeString): AnsiString;
  73. var
  74. i: integer;
  75. c: word;
  76. begin
  77. Result := '';
  78. for i := 1 to Length(AText) do
  79. begin
  80. c := Word(AText[i]);
  81. if i > 1 then
  82. Result := Result + ',';
  83. Result := Result + IntToHex(FFontFile.Chars[c], 4);
  84. end;
  85. end;
  86. procedure TMyApplication.DoRun;
  87. var
  88. ErrorMsg: String;
  89. s: UnicodeString;
  90. lst: TTextMappingList;
  91. i: integer;
  92. begin
  93. // quick check parameters
  94. ErrorMsg := CheckOptions('hf:s', 'help');
  95. if ErrorMsg <> '' then
  96. begin
  97. ShowException(Exception.Create(ErrorMsg));
  98. Terminate;
  99. Exit;
  100. end;
  101. // parse parameters
  102. if (ParamCount = 0) or HasOption('h', 'help') then
  103. begin
  104. WriteHelp;
  105. Terminate;
  106. Exit;
  107. end;
  108. FFontFile.LoadFromFile(self.GetOptionValue('f'));
  109. DumpGlyphIndex;
  110. // test #1
  111. // s := 'Hello, World!';
  112. // test #2
  113. s := 'Typography: “What’s wrong?”';
  114. Writeln('');
  115. lst := GetGlyphIndices(s);
  116. Writeln(Format('%d Glyph indices for: "%s"', [lst.Count, s]));
  117. writeln(#9'GID'#9'CharID');
  118. writeln(#9'---'#9'------');
  119. for i := 0 to lst.Count-1 do
  120. Writeln(Format(#9'%s'#9'%s'#9'%s', [IntToHex(lst[i].GlyphID, 4), IntToHex(lst[i].CharID, 4), Char(lst[i].CharID)]));
  121. if HasOption('s','') then
  122. CreateSubsetFontFile(lst);
  123. lst.Free;
  124. writeln;
  125. writeln;
  126. // stop program loop
  127. Terminate;
  128. end;
  129. constructor TMyApplication.Create(TheOwner: TComponent);
  130. begin
  131. inherited Create(TheOwner);
  132. StopOnException := True;
  133. FFontFile := TTFFileInfo.Create;
  134. end;
  135. destructor TMyApplication.Destroy;
  136. begin
  137. FFontFile.Free;
  138. inherited Destroy;
  139. end;
  140. procedure TMyApplication.WriteHelp;
  141. begin
  142. writeln('Usage: ', ExeName, ' -h');
  143. writeln(' -h Show this help.');
  144. writeln(' -f <ttf> Load TTF font file.');
  145. writeln(' -s Generate a subset TTF file.');
  146. end;
  147. var
  148. Application: TMyApplication;
  149. begin
  150. Application := TMyApplication.Create(nil);
  151. Application.Title := 'TTF Font Dump';
  152. Application.Run;
  153. Application.Free;
  154. end.