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

2D图形编程

开发平台:

Delphi

  1. unit MediaUtils;
  2. //---------------------------------------------------------------------------
  3. // MediaUtils.pas                                       Modified: 22-Jan-2007
  4. // Utility routines for handling media files                      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 MediaUtils.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, Classes, SysUtils, AsphyreDb, AsphyreXML, AsphyreTypes;
  41. //---------------------------------------------------------------------------
  42. {$WARN SYMBOL_PLATFORM OFF}
  43. //---------------------------------------------------------------------------
  44. type
  45.  TImageDescType = (idtImage, idtSurface, idtDraft);
  46. //---------------------------------------------------------------------------
  47.  TFontDescType = (fdtSystem, fdtBitmap);
  48. //---------------------------------------------------------------------------
  49. // IsArchiveLink()
  50. //
  51. // Validates if the specified link points to Archive.
  52. // Example:
  53. //   /data/media/map.zip | test.image
  54. //---------------------------------------------------------------------------
  55. function IsArchiveLink(const Text: string): Boolean;
  56. //---------------------------------------------------------------------------
  57. // ExtractArchiveName()
  58. //
  59. // Generates a valid archive file name with full path from the archive link.
  60. //---------------------------------------------------------------------------
  61. function ExtractArchiveName(const Text: string): string;
  62. //---------------------------------------------------------------------------
  63. // ExtractArchiveKey()
  64. //
  65. // Generates a valid key from the archive link.
  66. //---------------------------------------------------------------------------
  67. function ExtractArchiveKey(const Text: string): string;
  68. //---------------------------------------------------------------------------
  69. // LoadLinkXML()
  70. //
  71. // Attempts to load a link pointing to XML file
  72. //---------------------------------------------------------------------------
  73. function LoadLinkXML(const Link: string): TXMLNode;
  74. //---------------------------------------------------------------------------
  75. // GetWindowsDir()
  76. //
  77. // Retreives Windows System path.
  78. //---------------------------------------------------------------------------
  79. function GetWindowsPath(): TFileName;
  80. //---------------------------------------------------------------------------
  81. // GetTempDir()
  82. //
  83. // Retreives Temporary path.
  84. //---------------------------------------------------------------------------
  85. function GetTempPath(): TFileName;
  86. //---------------------------------------------------------------------------
  87. // MakeValidPath()
  88. //
  89. // Assures that the specified path ends with "", so a file name can be
  90. // added to it.
  91. //---------------------------------------------------------------------------
  92. function MakeValidPath(const Path: string): string;
  93. //---------------------------------------------------------------------------
  94. // MakeValidFileName()
  95. //
  96. // Assures that the specified file name does not begin with "", so a path
  97. // can be added to it.
  98. //---------------------------------------------------------------------------
  99. function MakeValidFileName(const FileName: string): string;
  100. //---------------------------------------------------------------------------
  101. // ParseInt()
  102. //
  103. // Parses a signed integer value read from XML. If no AutoValue is provided,
  104. // in case of empty or non-parseable text, -1 will be returned.
  105. //---------------------------------------------------------------------------
  106. function ParseInt(const Text: string): Integer; overload;
  107. function ParseInt(const Text: string; AutoValue: Integer): Integer; overload;
  108. //---------------------------------------------------------------------------
  109. // ParseCardinal()
  110. //
  111. // Parses an unsigned integer value read from XML. If no AutoValue is provided,
  112. // in case of empty or non-parseable text, High(Cardinal) will be returned.
  113. //---------------------------------------------------------------------------
  114. function ParseCardinal(const Text: string): Cardinal; overload;
  115. function ParseCardinal(const Text: string;
  116.  AutoValue: Cardinal): Cardinal; overload;
  117. //---------------------------------------------------------------------------
  118. // ParseFloat()
  119. //
  120. // Parses a floating-point  unsigned integer value read from XML. If no
  121. // AutoValue is provided, in case of empty or non-parseable text,
  122. // High(Cardinal) will be returned.
  123. //---------------------------------------------------------------------------
  124. function ParseFloat(const Text: string): Real; overload;
  125. function ParseFloat(const Text: string; AutoValue: Real): Real; overload;
  126. //---------------------------------------------------------------------------
  127. // ParseBoolean()
  128. //
  129. // Parses Boolean text representation (true, false, yes, no).
  130. //---------------------------------------------------------------------------
  131. function ParseBoolean(const Text: string;
  132.  AutoValue: Boolean): Boolean; overload;
  133. function ParseBoolean(const Text: string): Boolean; overload;
  134. //---------------------------------------------------------------------------
  135. // ParseColor()
  136. //
  137. // Parses an HTML or hexadecimal color.
  138. //  -> For HTML colors (#RRGGBB), alpha is always 255.
  139. //  -> If no AutoValue is specified, unparseable text gives opaque white.
  140. //---------------------------------------------------------------------------
  141. function ParseColor(const Text: string): Cardinal; overload;
  142. function ParseColor(const Text: string;
  143.  AutoColor: Cardinal): Cardinal; overload;
  144. //---------------------------------------------------------------------------
  145. // ParseFormat()
  146. //
  147. // Parses a text representation of TD3DFormat without "D3DFMT_" prefix.
  148. //  Example: "a8r8g8b8" will return D3DFMT_A8R8G8B8 value.
  149. //    -> The string must be in low case!
  150. //---------------------------------------------------------------------------
  151. function ParseFormat(const Text: string): TD3DFormat;
  152. //---------------------------------------------------------------------------
  153. // ParseImageType()
  154. //
  155. // Parses a text representation of TImageDescType.
  156. //---------------------------------------------------------------------------
  157. function ParseImageType(const Text: string): TImageDescType;
  158. //---------------------------------------------------------------------------
  159. // ParseFontType()
  160. //
  161. // Parses a text representation of TFontDescType.
  162. //---------------------------------------------------------------------------
  163. function ParseFontType(const Text: string): TFontDescType;
  164. //---------------------------------------------------------------------------
  165. // BooleanToString()
  166. //
  167. // Returns string representation of boolean.
  168. //---------------------------------------------------------------------------
  169. function BooleanToString(Value: Boolean): string;
  170. //---------------------------------------------------------------------------
  171. // ParseColorField()
  172. //
  173. // Parses XML color fields e.g.: <tag color="#00FF00" alpha="128" />
  174. //---------------------------------------------------------------------------
  175. function ParseColorField(Node: TXMLNode;
  176.  AutoColor: Cardinal = $FFFFFFFF): Cardinal;
  177. //---------------------------------------------------------------------------
  178. // ParseColor2Field()
  179. //
  180. // Parses XML color field representing TColor2. It accepts single color
  181. // and multicolor entries.
  182. //  Single color entry: <tag color="#00FF00" alpha="128" />
  183. //  Multi-color entry: <tag c1="#00FF00" a1="128" c2="#FFFFFF" a2="255" />
  184. //---------------------------------------------------------------------------
  185. function ParseColor2Field(Node: TXMLNode): TColor2; overload;
  186. //---------------------------------------------------------------------------
  187. // ParseHAlign()
  188. //
  189. // Parses text horizontal alignment attribute.
  190. //---------------------------------------------------------------------------
  191. function ParseHAlign(const Text: string;
  192.  AutoAlign: THorizontalAlign = haLeft): THorizontalAlign;
  193. //---------------------------------------------------------------------------
  194. // ParseVAlign()
  195. //
  196. // Parses text vertical alignment attribute.
  197. //---------------------------------------------------------------------------
  198. function ParseVAlign(const Text: string;
  199.  AutoAlign: TVerticalAlign = vaCenter): TVerticalAlign;
  200. //---------------------------------------------------------------------------
  201. implementation
  202. //---------------------------------------------------------------------------
  203. uses
  204.  AsphyreArchives, AsphyreEffects;
  205. //---------------------------------------------------------------------------
  206. function IsArchiveLink(const Text: string): Boolean;
  207. var
  208.  xPos: Integer;
  209. begin
  210.  xPos:= Pos('|', Text);
  211.  Result:= (Length(Text) >= 3)and(xPos > 1)and(xPos < Length(Text));
  212. end;
  213. //---------------------------------------------------------------------------
  214. function ExtractArchiveName(const Text: string): string;
  215. var
  216.  xPos, i: Integer;
  217. begin
  218.  Result:= Text;
  219.  // Step 1. Remove "key" part from the link.
  220.  xPos:= Pos('|', Text);
  221.  if (xPos <> 0) then
  222.   Delete(Result, xPos, Length(Result) + 1 - xPos);
  223.  // Step 2. Replace "/" with "".
  224.  for i:= 1 to Length(Result) do
  225.   if (Result[i] = '/') then Result[i]:= '';
  226.  // Step 3. Trim all leading and trailing spaces.
  227.  Result:= Trim(Result);
  228.  // Step 4. Remove leading "", if such exists.
  229.  if (Length(Result) > 0)and(Result[1] = '') then Delete(Result, 1, 1);
  230.  // Step 5. Include program path
  231.  Result:= ExtractFilePath(ParamStr(0)) + Result;
  232. end;
  233. //---------------------------------------------------------------------------
  234. function ExtractArchiveKey(const Text: string): string;
  235. var
  236.  xPos: Integer;
  237. begin
  238.  Result:= Text;
  239.  // Step 1. Remove "archive" part from the link.
  240.  xPos:= Pos('|', Text);
  241.  if (xPos <> 0) then
  242.   Delete(Result, 1, xPos);
  243.  // Step 2. Trim all leading and trailing spaces.
  244.  Result:= Trim(Result);
  245. end;
  246. //---------------------------------------------------------------------------
  247. function LoadLinkXML(const Link: string): TXMLNode;
  248. var
  249.  Stream: TMemoryStream;
  250. begin
  251.  if (IsArchiveLink(Link)) then
  252.   begin
  253.    Stream:= TMemoryStream.Create();
  254.    if (not ArchiveManager.ExtractToStream(Link, Stream)) then
  255.     begin
  256.      Result:= nil;
  257.      Stream.Free();
  258.      Exit;
  259.     end;
  260.    Stream.Seek(0, soFromBeginning);
  261.    try
  262.     Result:= LoadXMLFromStream(Stream);
  263.    finally
  264.     Stream.Free();
  265.    end;
  266.   end else Result:= LoadXMLFromFile(ExtractArchiveName(Link));
  267. end;
  268. //---------------------------------------------------------------------------
  269. function GetWindowsPath(): TFileName;
  270. var
  271.  WinDir: array [0..MAX_PATH - 1] of Char;
  272. begin
  273.  SetString(Result, WinDir, GetWindowsDirectory(WinDir, MAX_PATH));
  274.  if (Result = '') then Result:= ExtractFilePath(ParamStr(0));
  275. end;
  276. //---------------------------------------------------------------------------
  277. function GetTempPath(): TFileName;
  278. var
  279.  TempDir: array[0..MAX_PATH - 1] of Char;
  280. begin
  281.  try
  282.   SetString(Result, TempDir, Windows.GetTempPath(MAX_PATH, TempDir));
  283.   if (not DirectoryExists(Result)) then
  284.    if (not CreateDirectory(PChar(Result), nil)) then
  285.     begin
  286.      Result:= IncludeTrailingBackslash(GetWindowsPath()) + 'TEMP';
  287.      if (not DirectoryExists(Result)) then
  288.       if (not CreateDirectory(Pointer(Result), nil)) then
  289.        begin
  290.         Result:= ExtractFileDrive(Result) + 'TEMP';
  291.         if (not DirectoryExists(Result)) then
  292.          if (not CreateDirectory(Pointer(Result), nil)) then
  293.           begin
  294.            Result:= ExtractFileDrive(Result) + 'TMP';
  295.            if (not DirectoryExists(Result)) then
  296.             if (not CreateDirectory(Pointer(Result), nil)) then
  297.              Result:= ExtractFilePath(ParamStr(0));
  298.           end;
  299.        end;
  300.     end;
  301.   except
  302.    Result:= ExtractFilePath(ParamStr(0));
  303.  end;
  304. end;
  305. //---------------------------------------------------------------------------
  306. function MakeValidPath(const Path: string): string;
  307. begin
  308.  Result:= Trim(Path);
  309.  if (Length(Result) > 0)and(Result[Length(Result)] <> '') then
  310.   Result:= Result + '';
  311. end;
  312. //---------------------------------------------------------------------------
  313. function MakeValidFileName(const FileName: string): string;
  314. begin
  315.  Result:= Trim(FileName);
  316.  while (Length(Result) > 0)and(Result[1] = '') do Delete(Result, 1, 1);
  317. end;
  318. //---------------------------------------------------------------------------
  319. function ParseInt(const Text: string): Integer;
  320. begin
  321.  Result:= StrToIntDef(Text, -1);
  322. end;
  323. //---------------------------------------------------------------------------
  324. function ParseInt(const Text: string; AutoValue: Integer): Integer;
  325. begin
  326.  Result:= StrToIntDef(Text, AutoValue);
  327. end;
  328. //---------------------------------------------------------------------------
  329. function ParseCardinal(const Text: string): Cardinal;
  330. begin
  331.  Result:= Cardinal(StrToIntDef(Text, Integer(High(Cardinal))));
  332. end;
  333. //---------------------------------------------------------------------------
  334. function ParseCardinal(const Text: string; AutoValue: Cardinal): Cardinal;
  335. begin
  336.  Result:= Cardinal(StrToIntDef(Text, Integer(AutoValue)));
  337. end;
  338. //---------------------------------------------------------------------------
  339. function ParseBoolean(const Text: string; AutoValue: Boolean): Boolean;
  340. begin
  341.  Result:= AutoValue;
  342.  if (Text = 'no')or(Text = 'false') then Result:= False;
  343.  if (Text = 'yes')or(Text = 'true') then Result:= True;
  344. end;
  345. //---------------------------------------------------------------------------
  346. function ParseBoolean(const Text: string): Boolean;
  347. begin
  348.  Result:= ParseBoolean(Text, False);
  349. end;
  350. //---------------------------------------------------------------------------
  351. function ParseFloat(const Text: string): Real;
  352. begin
  353.  Result:= ParseFloat(Text, 0.0);
  354. end;
  355. //---------------------------------------------------------------------------
  356. function ParseFloat(const Text: string; AutoValue: Real): Real;
  357. var
  358.  PrevDecimalSpeparator: Char;
  359. begin
  360.  PrevDecimalSpeparator:= DecimalSeparator;
  361.  DecimalSeparator     := '.';
  362.  Result:= StrToFloatDef(Text, AutoValue);
  363.  DecimalSeparator     := PrevDecimalSpeparator;
  364. end;
  365. //---------------------------------------------------------------------------
  366. function ParseColor(const Text: string; AutoColor: Cardinal): Cardinal;
  367. begin
  368.  if (Text = 'source')or(Text = 'auto')or(Text = 'none') then
  369.   begin
  370.    Result:= AutoColor;
  371.    Exit;
  372.   end;
  373.  Result:= $FFFFFFFF;
  374.  if (Length(Text) < 2)or((Text[1] <> '#')and(Text[1] <> '$')) then Exit;
  375.  if (Text[1] = '#') then
  376.   begin
  377.    Result:= Cardinal(StrToIntDef('$' + Copy(Text, 2, Length(Text) - 1),
  378.     Integer(AutoColor))) or $FF000000;
  379.   end else Result:= Cardinal(StrToIntDef(Text, Integer(AutoColor)));
  380. end;
  381. //---------------------------------------------------------------------------
  382. function ParseColor(const Text: string): Cardinal;
  383. begin
  384.  Result:= ParseColor(Text, $FFFFFFFF);
  385. end;
  386. //---------------------------------------------------------------------------
  387. function ParseFormat(const Text: string): TD3DFormat;
  388. begin
  389.  Result:= D3DFMT_UNKNOWN;
  390.  if (Text = 'a2r10g10b10') then Result:= D3DFMT_A2R10G10B10;
  391.  if (Text = 'r8g8b8') then Result:= D3DFMT_R8G8B8;
  392.  if (Text = 'a8r8g8b8') then Result:= D3DFMT_A8R8G8B8;
  393.  if (Text = 'x8r8g8b8') then Result:= D3DFMT_X8R8G8B8;
  394.  if (Text = 'r5g6b5') then Result:= D3DFMT_R5G6B5;
  395.  if (Text = 'x1r5g5b5') then Result:= D3DFMT_X1R5G5B5;
  396.  if (Text = 'a1r5g5b5') then Result:= D3DFMT_A1R5G5B5;
  397.  if (Text = 'a4r4g4b4') then Result:= D3DFMT_A4R4G4B4;
  398.  if (Text = 'a4r4g4b4') then Result:= D3DFMT_A4R4G4B4;
  399.  if (Text = 'r3g3b2') then Result:= D3DFMT_R3G3B2;
  400.  if (Text = 'a8') then Result:= D3DFMT_A8;
  401.  if (Text = 'a8r3g3b2') then Result:= D3DFMT_A8R3G3B2;
  402.  if (Text = 'x4r4g4b4') then Result:= D3DFMT_X4R4G4B4;
  403.  if (Text = 'a2b10g10r10') then Result:= D3DFMT_A2B10G10R10;
  404.  if (Text = 'a8b8g8r8') then Result:= D3DFMT_A8B8G8R8;
  405.  if (Text = 'x8b8g8r8') then Result:= D3DFMT_X8B8G8R8;
  406.  if (Text = 'g16r16') then Result:= D3DFMT_G16R16;
  407.  if (Text = 'a4r4g4b4') then Result:= D3DFMT_A4R4G4B4;
  408.  if (Text = 'a2r10g10b10') then Result:= D3DFMT_A2R10G10B10;
  409.  if (Text = 'a16b16g16r16') then Result:= D3DFMT_A16B16G16R16;
  410.  if (Text = 'a8p8') then Result:= D3DFMT_A8P8;
  411.  if (Text = 'p8') then Result:= D3DFMT_P8;
  412.  if (Text = 'l8') then Result:= D3DFMT_L8;
  413.  if (Text = 'a8l8') then Result:= D3DFMT_A8L8;
  414.  if (Text = 'a4l4') then Result:= D3DFMT_A4L4;
  415.  if (Text = 'v8u8') then Result:= D3DFMT_V8U8;
  416.  if (Text = 'l6v5u5') then Result:= D3DFMT_L6V5U5;
  417.  if (Text = 'x8l8v8u8') then Result:= D3DFMT_X8L8V8U8;
  418.  if (Text = 'q8w8v8u8') then Result:= D3DFMT_Q8W8V8U8;
  419.  if (Text = 'v16u16') then Result:= D3DFMT_V16U16;
  420.  if (Text = 'a2w10v10u10') then Result:= D3DFMT_A2W10V10U10;
  421.  if (Text = 'a8x8v8u8') then Result:= D3DFMT_A8X8V8U8;
  422.  if (Text = 'l8x8v8u8') then Result:= D3DFMT_L8X8V8U8;
  423.  if (Text = 'uyvy') then Result:= D3DFMT_UYVY;
  424.  if (Text = 'rgbg') then Result:= D3DFMT_RGBG;
  425.  if (Text = 'yuy2') then Result:= D3DFMT_YUY2;
  426.  if (Text = 'grgb') then Result:= D3DFMT_GRGB;
  427.  if (Text = 'dxt1') then Result:= D3DFMT_DXT1;
  428.  if (Text = 'dxt2') then Result:= D3DFMT_DXT2;
  429.  if (Text = 'dxt3') then Result:= D3DFMT_DXT3;
  430.  if (Text = 'dxt4') then Result:= D3DFMT_DXT4;
  431.  if (Text = 'dxt5') then Result:= D3DFMT_DXT5;
  432.  if (Text = 'q16w16v16u16') then Result:= D3DFMT_Q16W16V16U16;
  433.  if (Text = 'multi2_argb8') then Result:= D3DFMT_MULTI2_ARGB8;
  434.  if (Text = 'r16f') then Result:= D3DFMT_R16F;
  435.  if (Text = 'g16r16f') then Result:= D3DFMT_G16R16F;
  436.  if (Text = 'a16b16g16r16f') then Result:= D3DFMT_A16B16G16R16F;
  437.  if (Text = 'r32f') then Result:= D3DFMT_R32F;
  438.  if (Text = 'g32r32f') then Result:= D3DFMT_G32R32F;
  439.  if (Text = 'a32b32g32r32f') then Result:= D3DFMT_A32B32G32R32F;
  440.  if (Text = 'cxv8u8') then Result:= D3DFMT_CxV8U8;
  441. end;
  442. //---------------------------------------------------------------------------
  443. function ParseImageType(const Text: string): TImageDescType;
  444. begin
  445.  Result:= idtImage;
  446.  if (Text = 'surface') then Result:= idtSurface;
  447.  if (Text = 'draft') then Result:= idtDraft;
  448. end;
  449. //---------------------------------------------------------------------------
  450. function ParseFontType(const Text: string): TFontDescType;
  451. begin
  452.  Result:= fdtSystem;
  453.  if (Text = 'bitmap') then Result:= fdtBitmap;
  454. end;
  455. //---------------------------------------------------------------------------
  456. function BooleanToString(Value: Boolean): string;
  457. begin
  458.  if (Value) then Result:= 'yes' else Result:= 'no';
  459. end;
  460. //---------------------------------------------------------------------------
  461. function ParseColorField(Node: TXMLNode;
  462.  AutoColor: Cardinal = $FFFFFFFF): Cardinal;
  463. begin
  464.  Result:= ParseColor(Node.FieldValue['color'], AutoColor);
  465.  Result:= (Result and $FFFFFF) or (ParseCardinal(Node.FieldValue['alpha'],
  466.   AutoColor shr 24) shl 24);
  467. end;
  468. //---------------------------------------------------------------------------
  469. function ParseColor2Field(Node: TXMLNode): TColor2; overload;
  470. begin
  471.  if (Node.FindFieldByName('color') <> -1) then
  472.   begin
  473.    Result:= cColor2(ParseColorField(Node, $FFFFFFFF));
  474.    Exit;
  475.   end;
  476.  Result[0]:= ParseColor(Node.FieldValue['c1']);
  477.  Result[0]:= (Result[0] and $FFFFFF) or
  478.   (ParseCardinal(Node.FieldValue['a1']) shl 24);
  479.  Result[1]:= ParseColor(Node.FieldValue['c2']);
  480.  Result[1]:= (Result[1] and $FFFFFF) or
  481.   (ParseCardinal(Node.FieldValue['a2']) shl 24);
  482. end;
  483. //---------------------------------------------------------------------------
  484. function ParseHAlign(const Text: string;
  485.  AutoAlign: THorizontalAlign = haLeft): THorizontalAlign;
  486. begin
  487.  Result:= AutoAlign;
  488.  if (Text = 'left') then Result:= haLeft;
  489.  if (Text = 'right') then Result:= haRight;
  490.  if (Text = 'center') then Result:= haCenter;
  491.  if (Text = 'justified') then Result:= haJustified;
  492. end;
  493. //---------------------------------------------------------------------------
  494. function ParseVAlign(const Text: string;
  495.  AutoAlign: TVerticalAlign = vaCenter): TVerticalAlign;
  496. begin
  497.  Result:= AutoAlign;
  498.  if (Text = 'top') then Result:= vaTop;
  499.  if (Text = 'bottom') then Result:= vaBottom;
  500.  if (Text = 'center') then Result:= vaCenter;
  501. end;
  502. //---------------------------------------------------------------------------
  503. end.