MediaFonts.pas
上传用户:ctlcnc
上传日期:2021-12-10
资源大小:4933k
文件大小:13k
源码类别:

2D图形编程

开发平台:

Delphi

  1. unit MediaFonts;
  2. //---------------------------------------------------------------------------
  3. // MediaFonts.pas                                       Modified: 20-Feb-2007
  4. // Resource management system for Asphyre fonts                   Version 1.0
  5. //---------------------------------------------------------------------------
  6. // Important Notice:
  7. //
  8. // If you modify/use this code or one of its parts either in original or
  9. // modified form, you must comply with Mozilla Public License v1.1,
  10. // specifically section 3, "Distribution Obligations". Failure to do so will
  11. // result in the license breach, which will be resolved in the court.
  12. // Remember that violating author's rights is considered a serious crime in
  13. // many countries. Thank you!
  14. //
  15. // !! Please *read* Mozilla Public License 1.1 document located at:
  16. //  http://www.mozilla.org/MPL/
  17. //
  18. // If you require any clarifications about the license, feel free to contact
  19. // us or post your question on our forums at: http://www.afterwarp.net
  20. //---------------------------------------------------------------------------
  21. // The contents of this file are subject to the Mozilla Public License
  22. // Version 1.1 (the "License"); you may not use this file except in
  23. // compliance with the License. You may obtain a copy of the License at
  24. // http://www.mozilla.org/MPL/
  25. //
  26. // Software distributed under the License is distributed on an "AS IS"
  27. // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
  28. // License for the specific language governing rights and limitations
  29. // under the License.
  30. //
  31. // The Original Code is MediaFonts.pas.
  32. //
  33. // The Initial Developer of the Original Code is M. Sc. Yuriy Kotsarenko.
  34. // Portions created by M. Sc. Yuriy Kotsarenko are Copyright (C) 2007,
  35. // Afterwarp Interactive. All Rights Reserved.
  36. //---------------------------------------------------------------------------
  37. interface
  38. //---------------------------------------------------------------------------
  39. uses
  40.  Windows, Direct3D9, D3DX9, Types, SysUtils, AsphyreXML, Vectors2px,
  41.  MediaUtils
  42.  {$IFDEF DebugMode}, AsphyreDebug{$ENDIF};
  43. //---------------------------------------------------------------------------
  44. type
  45.  TFontCharInfo = record
  46.   AsciiCode: Integer;
  47.   Width    : Integer;
  48.  end;
  49. //---------------------------------------------------------------------------
  50.  PFontDesc = ^TFontDesc;
  51.  TFontDesc = record
  52.   // valuse common to all fonts
  53.   Identifier : string;
  54.   DescType   : TFontDescType;
  55.   // values specific to bitmap fonts
  56.   Image      : string;
  57.   PatSize    : TPoint2px;
  58.   PatCount   : Integer;
  59.   FirstLetter: Integer;
  60.   Interleave : Integer;
  61.   BlankSpace : Single;
  62.   CharInfo   : array of TFontCharInfo;
  63.   procedure ResetCharInfo();
  64.   function InsertCharInfo(AsciiCode, Width: Integer): Integer;
  65.  end;
  66. //---------------------------------------------------------------------------
  67.  TFontGroup = class
  68.  private
  69.   Data: array of TFontDesc;
  70.   FName  : string;
  71.   FOption: string;
  72.   function GetCount(): Integer;
  73.   function GetItem(Num: Integer): PFontDesc;
  74.   function NewItem(): PFontDesc;
  75.   procedure ParseItem(Node: TXMLNode);
  76.   procedure ParseFulldesc(Desc: PFontDesc; Node: TXMLNode);
  77.  public
  78.   property Name: string read FName;
  79.   property Option: string read FOption;
  80.   property Count: Integer read GetCount;
  81.   property Item[Num: Integer]: PFontDesc read GetItem; default;
  82.   function Find(const Text: string): PFontDesc;
  83.   procedure ParseXML(Node: TXMLNode);
  84.   constructor Create(const AName: string);
  85.  end;
  86. //---------------------------------------------------------------------------
  87.  TFontGroups = class
  88.  private
  89.   Data: array of TFontGroup;
  90.   function GetCount(): Integer;
  91.   function GetItem(Num: Integer): TFontGroup;
  92.   function GetGroup(const Name: string): TFontGroup;
  93.   function NewGroup(const Name: string): TFontGroup;
  94.   function GetTotal(): Integer;
  95.  public
  96.   property Count: Integer read GetCount;
  97.   property Item[Num: Integer]: TFontGroup read GetItem;
  98.   property Group[const Name: string]: TFontGroup read GetGroup;
  99.   property Total: Integer read GetTotal;
  100.   function IndexOf(Name: string): Integer;
  101.   procedure Clear();
  102.   function Find(const uid: string; Option: string): PFontDesc;
  103.   procedure ParseLink(const Link: string);
  104.   destructor Destroy(); override;
  105.  end;
  106. //---------------------------------------------------------------------------
  107. var
  108.  FontGroups: TFontGroups = nil;
  109. //---------------------------------------------------------------------------
  110. implementation
  111. //---------------------------------------------------------------------------
  112. procedure TFontDesc.ResetCharInfo();
  113. begin
  114.  SetLength(CharInfo, 0);
  115. end;
  116. //---------------------------------------------------------------------------
  117. function TFontDesc.InsertCharInfo(AsciiCode, Width: Integer): Integer;
  118. var
  119.  Index: Integer;
  120. begin
  121.  Index:= Length(CharInfo);
  122.  SetLength(CharInfo, Index + 1);
  123.  CharInfo[Index].AsciiCode:= AsciiCode;
  124.  CharInfo[Index].Width    := Width;
  125.  Result:= Index;
  126. end;
  127. //---------------------------------------------------------------------------
  128. constructor TFontGroup.Create(const AName: string);
  129. begin
  130.  inherited Create();
  131.  FName:= LowerCase(AName);
  132. end;
  133. //---------------------------------------------------------------------------
  134. function TFontGroup.GetCount(): Integer;
  135. begin
  136.  Result:= Length(Data);
  137. end;
  138. //---------------------------------------------------------------------------
  139. function TFontGroup.GetItem(Num: Integer): PFontDesc;
  140. begin
  141.  if (Num >= 0)and(Num < Length(Data)) then
  142.   Result:= @Data[Num] else Result:= nil;
  143. end;
  144. //---------------------------------------------------------------------------
  145. function TFontGroup.Find(const Text: string): PFontDesc;
  146. var
  147.  LoText: ShortString;
  148.  i: Integer;
  149. begin
  150.  LoText:= LowerCase(Text);
  151.  Result:= nil;
  152.  for i:= 0 to Length(Data) - 1 do
  153.   if (Data[i].Identifier = LoText) then
  154.    begin
  155.     Result:= @Data[i];
  156.     Break;
  157.    end;
  158. end;
  159. //---------------------------------------------------------------------------
  160. function TFontGroup.NewItem(): PFontDesc;
  161. var
  162.  Index: Integer;
  163. begin
  164.  Index:= Length(Data);
  165.  SetLength(Data, Index + 1);
  166.  FillChar(Data[Index], SizeOf(TFontDesc), 0);
  167.  Data[Index].ResetCharInfo();
  168.  Result:= @Data[Index];
  169. end;
  170. //---------------------------------------------------------------------------
  171. procedure TFontGroup.ParseFulldesc(Desc: PFontDesc; Node: TXMLNode);
  172. var
  173.  Aux, Child: TXMLNode;
  174.  i: Integer;
  175. begin
  176.  if (LowerCase(Node.Name) <> 'fontdesc') then Exit;
  177.  // (1) Parse "pattern" node
  178.  Aux:= Node.ChildNode['pattern'];
  179.  if (Aux <> nil) then
  180.   begin
  181.    Desc.PatSize.X:= ParseInt(Aux.FieldValue['width'], 0);
  182.    Desc.PatSize.Y:= ParseInt(Aux.FieldValue['height'], 0);
  183.    Desc.PatCount := ParseInt(Aux.FieldValue['count'], 0);
  184.   end;
  185.  {$IFDEF DebugMode}
  186.  DebugLog('   --> with ' + IntToStr(Desc.PatCount) + ' of ' +
  187.   IntToStr(Desc.PatSize.X) + 'x' + IntToStr(Desc.PatSize.Y));
  188.  {$ENDIF}
  189.  // (2) Parse "text" node
  190.  Aux:= Node.ChildNode['text'];
  191.  if (Aux <> nil) then
  192.   begin
  193.    Desc.FirstLetter:= ParseInt(Aux.FieldValue['first_letter'], 0);
  194.    Desc.Interleave := ParseInt(Aux.FieldValue['interleave'], 0);
  195.   end;
  196.  {$IFDEF DebugMode}
  197.  DebugLog('   --> first letter ' + IntToStr(Desc.FirstLetter) +
  198.   ' and interleave of ' + IntToStr(Desc.Interleave));
  199.  {$ENDIF}
  200.  // (3) Parse "charinfo" node
  201.  Aux:= Node.ChildNode['charinfo'];
  202.  if (Aux <> nil) then
  203.   for i:= 0 to Aux.ChildCount - 1 do
  204.    if (LowerCase(Aux.Child[i].Name) = 'item') then
  205.     begin
  206.      Child:= Aux.Child[i];
  207.      Desc.InsertCharInfo(ParseInt(Child.FieldValue['ascii_code'], 0),
  208.       ParseInt(Child.FieldValue['width'], 0));
  209.     end;
  210. end;
  211. //---------------------------------------------------------------------------
  212. procedure TFontGroup.ParseItem(Node: TXMLNode);
  213. var
  214.  Desc: PFontDesc;
  215.  Name: string;
  216.  Root: TXMLNode;
  217. begin
  218.  // (1) Determine resource type.
  219.  Name:= LowerCase(Node.Name);
  220.  if (Name <> 'font') then Exit;
  221.  // (2) Create image description.
  222.  Desc:= NewItem();
  223.  
  224.  Desc.Identifier:= LowerCase(Node.FieldValue['uid']);
  225.  Desc.DescType  := ParseFontType(LowerCase(Node.FieldValue['type']));
  226.  Desc.Image     := LowerCase(Node.FieldValue['image']);
  227.  Desc.BlankSpace:= ParseFloat(LowerCase(Node.FieldValue['space']));
  228.  {$IFDEF DebugMode}
  229.  DebugLog('  ++ Font described as "' + Desc.Identifier + '".');
  230.  {$ENDIF}
  231.  // (3) Parse full bitmap font description.
  232.  if (Node.FieldValue['desc'] <> '') then
  233.   begin
  234.    Root:= LoadLinkXML(Node.FieldValue['desc']);
  235.    if (Root <> nil) then
  236.     begin
  237.      ParseFulldesc(Desc, Root);
  238.      Root.Free();
  239.     end else
  240.     begin
  241.      {$IFDEF DebugMode}
  242.      DebugLog('Failed loading font desc link: ' + Node.FieldValue['fulldesc']);
  243.      {$ENDIF}
  244.     end;
  245.   end;
  246. end;
  247. //---------------------------------------------------------------------------
  248. procedure TFontGroup.ParseXML(Node: TXMLNode);
  249. var
  250.  i: Integer;
  251. begin
  252.  if (LowerCase(Node.Name) <> 'font-group') then Exit;
  253.  FName  := LowerCase(Node.FieldValue['name']);
  254.  FOption:= LowerCase(Node.FieldValue['option']);
  255.  {$IFDEF DebugMode}
  256.  DebugLog(' + New font group "' + FName + '", option "' + FOption + '".');
  257.  {$ENDIF}
  258.  for i:= 0 to Node.ChildCount - 1 do
  259.   ParseItem(Node.Child[i]);
  260. end;
  261. //---------------------------------------------------------------------------
  262. destructor TFontGroups.Destroy();
  263. begin
  264.  Clear();
  265.  inherited;
  266. end;
  267. //---------------------------------------------------------------------------
  268. function TFontGroups.GetCount: Integer;
  269. begin
  270.  Result:= Length(Data);
  271. end;
  272. //---------------------------------------------------------------------------
  273. function TFontGroups.GetItem(Num: Integer): TFontGroup;
  274. begin
  275.  if (Num >= 0)and(Num < Length(Data)) then
  276.   Result:= Data[Num] else Result:= nil;
  277. end;
  278. //---------------------------------------------------------------------------
  279. function TFontGroups.IndexOf(Name: string): Integer;
  280. var
  281.  i: Integer;
  282. begin
  283.  Name:= LowerCase(Name);
  284.  Result:= -1;
  285.  for i:= 0 to Length(Data) - 1 do
  286.   if (Data[i].Name = Name) then
  287.    begin
  288.     Result:= i;
  289.     Break;
  290.    end;
  291. end;
  292. //---------------------------------------------------------------------------
  293. function TFontGroups.GetGroup(const Name: string): TFontGroup;
  294. var
  295.  Index: Integer;
  296. begin
  297.  Result:= nil;
  298.  Index := IndexOf(Name);
  299.  if (Index <> -1) then Result:= Data[Index];
  300. end;
  301. //---------------------------------------------------------------------------
  302. procedure TFontGroups.Clear();
  303. var
  304.  i: Integer;
  305. begin
  306.  for i:= 0 to Length(Data) - 1 do
  307.   if (Data[i] <> nil) then
  308.    begin
  309.     Data[i].Free();
  310.     Data[i]:= nil;
  311.    end;
  312.  SetLength(Data, 0);
  313. end;
  314. //---------------------------------------------------------------------------
  315. function TFontGroups.GetTotal(): Integer;
  316. var
  317.  i: Integer;
  318. begin
  319.  Result:= 0;
  320.  for i:= 0 to Length(Data) - 1 do
  321.   Inc(Result, Data[i].Count);
  322. end;
  323. //---------------------------------------------------------------------------
  324. function TFontGroups.Find(const uid: string; Option: string): PFontDesc;
  325. var
  326.  i: Integer;
  327. begin
  328.  Result:= nil;
  329.  Option:= LowerCase(Option);
  330.  for i:= 0 to Length(Data) - 1 do
  331.   if (Option = '')or(Data[i].Option = '')or(LowerCase(Data[i].Option) = Option) then
  332.    begin
  333.     Result:= Data[i].Find(uid);
  334.     if (Result <> nil) then Break;
  335.    end;
  336. end;
  337. //---------------------------------------------------------------------------
  338. function TFontGroups.NewGroup(const Name: string): TFontGroup;
  339. var
  340.  Index: Integer;
  341. begin
  342.  Index:= Length(Data);
  343.  SetLength(Data, Index + 1);
  344.  Data[Index]:= TFontGroup.Create(Name);
  345.  Result:= Data[Index];
  346. end;
  347. //---------------------------------------------------------------------------
  348. procedure TFontGroups.ParseLink(const Link: string);
  349. var
  350.  nName: string;
  351.  Root : TXMLNode;
  352.  gName: string;
  353.  Group: TFontGroup;
  354.  Text : string;
  355.  i: Integer;
  356. begin
  357.  {$IFDEF DebugMode}
  358.  DebugLog('Begin entry [font groups]: ' + Link);
  359.  {$ENDIF}
  360.  Root:= LoadLinkXML(Link);
  361.  if (Root = nil) then Exit;
  362.  if (LowerCase(Root.Name) <> 'unires')  then
  363.   begin
  364.    {$IFDEF DebugMode}
  365.    DebugLog('Root node is not UNIRES, exiting.');
  366.    {$ENDIF}
  367.    Root.Free();
  368.    Exit;
  369.   end;
  370.  for i:= 0 to Root.ChildCount - 1 do
  371.   begin
  372.    nName:= LowerCase(Root.Child[i].Name);
  373.    if (nName = 'font-group') then
  374.     begin
  375.      gName:= LowerCase(Root.Child[i].FieldValue['name']);
  376.      if (Length(gName) > 0) then
  377.       begin
  378.        Group:= GetGroup(gName);
  379.        if (Group = nil) then Group:= NewGroup(gName);
  380.        Group.ParseXML(Root.Child[i]);
  381.       end;
  382.     end;
  383.    if (nName = 'resource') then
  384.     begin
  385.      Text:= Root.Child[i].FieldValue['source'];
  386.      if (Length(Text) > 0) then ParseLink(Text);
  387.     end;
  388.   end;
  389.  Root.Free();
  390.  {$IFDEF DebugMode}
  391.  DebugLog('End entry [font groups]: ' + Link);
  392.  {$ENDIF}
  393. end;
  394. //---------------------------------------------------------------------------
  395. initialization
  396.  FontGroups:= TFontGroups.Create();
  397. //---------------------------------------------------------------------------
  398. finalization
  399.  FontGroups.Free();
  400.  FontGroups:= nil;
  401. //---------------------------------------------------------------------------
  402. end.