gtext.inc 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by the Free Pascal development team
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************}
  10. {***************************************************************************}
  11. { Text output routines }
  12. {***************************************************************************}
  13. const
  14. maxfonts = 16; { maximum possible fonts }
  15. MaxChars = 255; { Maximum nr. of characters in a file }
  16. Prefix_Size = $80; { prefix size to skip }
  17. SIGNATURE = '+'; { Signature of CHR file }
  18. type
  19. { Prefix header of Font file }
  20. { PFHeader = ^TFHeader;}
  21. TFHeader = packed record
  22. header_size: word; {* Version 2.0 Header Format *}
  23. font_name: array[1..4] of char;
  24. font_size: word; {* Size in byte of file *}
  25. font_major: byte; {* Driver Version Information *}
  26. font_minor: byte;
  27. min_major: byte; {* BGI Revision Information *}
  28. min_minor: byte;
  29. end;
  30. { Font record information }
  31. { PHeader = ^THeader;}
  32. THeader = packed record
  33. Signature: char; { signature byte }
  34. Nr_chars: smallint; { number of characters in file }
  35. Reserved: byte;
  36. First_char: byte; { first character in file }
  37. cdefs : smallint; { offset to character definitions }
  38. scan_flag: byte; { TRUE if char is scanable }
  39. org_to_cap: shortint; { Height from origin to top of capitol }
  40. org_to_base:shortint; { Height from origin to baseline }
  41. org_to_dec: shortint; { Height from origin to bot of decender }
  42. _reserved: array[1..4] of char;
  43. Unused: byte;
  44. end;
  45. TOffsetTable =array[0..MaxChars] of smallint;
  46. TWidthTable =array[0..MaxChars] of byte;
  47. tfontrec = packed record
  48. name : string[8];
  49. header : THeader; { font header }
  50. pheader : TFHeader; { prefix header }
  51. offsets : TOffsetTable;
  52. widths : TWidthTable;
  53. instrlength: longint; { length of instr, because instr can }
  54. instr : pchar; { contain null characters }
  55. end;
  56. { pStroke = ^TStroke;}
  57. TStroke = packed record
  58. opcode: byte;
  59. x: smallint; { relative x offset character }
  60. y: smallint; { relative y offset character }
  61. end;
  62. TStrokes = Array[0..1000] of TStroke;
  63. opcodes = (_END_OF_CHAR, _DO_SCAN, _DRAW := 253, _MOVE := 254 );
  64. var
  65. fonts : array[1..maxfonts] of tfontrec;
  66. Strokes: TStrokes; {* Stroke Data Base *}
  67. { Stroke_count: Array[0..MaxChars] of smallint;} {* Stroke Count Table *}
  68. {***************************************************************************}
  69. { Internal support routines }
  70. {***************************************************************************}
  71. {$ifdef FPC_BIG_ENDIAN}
  72. procedure swap_fheader(var h: tfheader);
  73. (*
  74. TFHeader = packed record
  75. header_size: word; {* Version 2.0 Header Format *}
  76. font_name: array[1..4] of char;
  77. font_size: word; {* Size in byte of file *}
  78. font_major: byte; {* Driver Version Information *}
  79. font_minor: byte;
  80. min_major: byte; {* BGI Revision Information *}
  81. min_minor: byte;
  82. end;
  83. *)
  84. begin
  85. with h do
  86. begin
  87. header_size := swap(header_size);
  88. font_size := swap(font_size);
  89. end;
  90. end;
  91. procedure swap_header(var h: theader);
  92. (*
  93. THeader = packed record
  94. Signature: char; { signature byte }
  95. Nr_chars: smallint; { number of characters in file }
  96. Reserved: byte;
  97. First_char: byte; { first character in file }
  98. cdefs : smallint; { offset to character definitions }
  99. scan_flag: byte; { TRUE if char is scanable }
  100. org_to_cap: shortint; { Height from origin to top of capitol }
  101. org_to_base:shortint; { Height from origin to baseline }
  102. org_to_dec: shortint; { Height from origin to bot of decender }
  103. _reserved: array[1..4] of char;
  104. Unused: byte;
  105. end;
  106. *)
  107. begin
  108. with h do
  109. begin
  110. nr_chars := swap(nr_chars);
  111. cdefs := swap(cdefs);
  112. end;
  113. end;
  114. procedure swap_offsets(var t: toffsettable; start, len: longint);
  115. (*
  116. TOffsetTable =array[0..MaxChars] of smallint;
  117. *)
  118. var
  119. i: longint;
  120. begin
  121. for i := start to start+len-1 do
  122. t[i]:=Swap(t[i]);
  123. end;
  124. {$endif FPC_BIG_ENDIAN}
  125. function ConvertString(const OrigString: String): String;
  126. var
  127. i: Integer;
  128. ConvResult: String;
  129. begin
  130. if GraphStringTransTable = nil then
  131. ConvertString := OrigString
  132. else
  133. begin
  134. SetLength(ConvResult, Length(OrigString));
  135. for i := 1 to Length(OrigString) do
  136. ConvResult[i] := GraphStringTransTable^[OrigString[i]];
  137. ConvertString := ConvResult;
  138. end;
  139. end;
  140. function testfont(p : pchar) : boolean;
  141. begin
  142. testfont:=(p[0]='P') and
  143. (p[1]='K') and
  144. (p[2]=#8) and
  145. (p[3]=#8);
  146. end;
  147. function InstallUserFont(const FontFileName : string) : smallint;
  148. begin
  149. _graphresult:=grOk;
  150. { first check if we do not allocate too many fonts! }
  151. if installedfonts=maxfonts then
  152. begin
  153. _graphresult:=grError;
  154. InstallUserFont := DefaultFont;
  155. exit;
  156. end;
  157. inc(installedfonts);
  158. fonts[installedfonts].name:=FontFileName;
  159. fonts[installedfonts].instr := nil;
  160. fonts[installedfonts].instrlength := 0;
  161. InstallUserFont:=installedfonts;
  162. end;
  163. function Decode(byte1,byte2: char; var x,y: smallint): smallint;
  164. { This routines decoes a signle word in a font opcode section }
  165. { to a stroke record. }
  166. var
  167. b1,b2: shortint;
  168. Begin
  169. b1:=shortint(byte1);
  170. b2:=shortint(byte2);
  171. { Decode the CHR OPCODE }
  172. Decode:=smallint(((b1 and $80) shr 6)+((b2 and $80) shr 7));
  173. { Now get the X,Y coordinates }
  174. { bit 0..7 only which are considered }
  175. { signed values. }
  176. { disable range check mode }
  177. {$ifopt R+}
  178. {$define OPT_R_WAS_ON}
  179. {$R-}
  180. {$endif}
  181. b1:=b1 and $7f;
  182. b2:=b2 and $7f;
  183. { Now if the MSB of these values are set }
  184. { then the value is signed, therefore we }
  185. { sign extend it... }
  186. if (b1 and $40)<>0 then b1:=b1 or $80;
  187. if (b2 and $40)<>0 then b2:=b2 or $80;
  188. x:=smallint(b1);
  189. y:=smallint(b2);
  190. { restore previous range check mode }
  191. {$ifdef OPT_R_WAS_ON}
  192. {$R+}
  193. {$endif}
  194. end;
  195. function unpack(buf: pchar; index: smallint; var Stroke: TStrokes): smallint;
  196. var
  197. po: TStrokes;
  198. num_ops: smallint;
  199. opcode, i, opc: word;
  200. counter: smallint;
  201. lindex: smallint;
  202. jx, jy: smallint;
  203. begin
  204. num_ops := 0;
  205. counter := index;
  206. lindex :=0;
  207. while TRUE do {* For each byte in buffer *}
  208. Begin
  209. Inc(num_ops); {* Count the operation *}
  210. opcode := decode( buf[counter], buf[counter+1] ,jx, jy );
  211. Inc(counter,2);
  212. if( opcode = ord(_END_OF_CHAR) ) then break; {* Exit loop at end of char *}
  213. end;
  214. counter:=index;
  215. for i:=0 to num_ops-1 do { /* For each opcode in buffer */ }
  216. Begin
  217. opc := decode(buf[counter], buf[counter+1], po[lindex].x, po[lindex].y); {* Decode the data field *}
  218. inc(counter,2);
  219. po[lindex].opcode := opc; {* Save the opcode *}
  220. Inc(lindex);
  221. end;
  222. Stroke:=po;
  223. unpack := num_ops; {* return OPS count *}
  224. end;
  225. procedure GetTextPosition(var xpos,ypos: longint; const TextString: string);
  226. begin
  227. if CurrentTextInfo.Font = DefaultFont then
  228. begin
  229. if Currenttextinfo.direction=horizdir then
  230. begin
  231. case Currenttextinfo.horiz of
  232. centertext : XPos:=(textwidth(textstring) shr 1);
  233. lefttext : XPos:=0;
  234. righttext : XPos:=textwidth(textstring);
  235. end;
  236. case Currenttextinfo.vert of
  237. centertext : YPos:=-(textheight(textstring) shr 1);
  238. bottomtext : YPos:=-textheight(textstring);
  239. toptext : YPos:=0;
  240. end;
  241. end else
  242. begin
  243. case Currenttextinfo.horiz of
  244. centertext : XPos:=(textheight(textstring) shr 1);
  245. lefttext : XPos:=textheight(textstring);
  246. righttext : XPos:=textheight(textstring);
  247. end;
  248. case Currenttextinfo.vert of
  249. centertext : YPos:=(textwidth(textstring) shr 1);
  250. bottomtext : YPos:=0;
  251. toptext : YPos:=textwidth(textstring);
  252. end;
  253. end;
  254. end
  255. else
  256. begin
  257. if Currenttextinfo.direction=horizdir then
  258. begin
  259. case CurrentTextInfo.horiz of
  260. centertext : XPos:=(textwidth(textstring) shr 1);
  261. lefttext : XPos:=0;
  262. righttext : XPos:=textwidth(textstring);
  263. end;
  264. case CurrentTextInfo.vert of
  265. centertext : YPos:=(textheight(textstring) shr 1);
  266. bottomtext : YPos:=0;
  267. toptext : YPos:=textheight(textstring);
  268. end;
  269. end else
  270. begin
  271. case CurrentTextInfo.horiz of
  272. centertext : XPos:=(textheight(textstring) shr 1);
  273. lefttext : XPos:=0;
  274. righttext : XPos:=textheight(textstring);
  275. end;
  276. case CurrentTextInfo.vert of
  277. centertext : YPos:=(textwidth(textstring) shr 1);
  278. bottomtext : YPos:=0;
  279. toptext : YPos:=textwidth(textstring);
  280. end;
  281. end;
  282. end;
  283. end;
  284. {***************************************************************************}
  285. { Exported routines }
  286. {***************************************************************************}
  287. function RegisterBGIfont(font : pointer) : smallint;
  288. var
  289. hp : pchar;
  290. b : word;
  291. i: longint;
  292. Header: THeader;
  293. counter: longint;
  294. FontData: pchar;
  295. FHeader: TFHeader;
  296. begin
  297. RegisterBGIfont:=grInvalidFontNum;
  298. i:=0;
  299. { Check if the font header is valid first of all }
  300. if testfont(font) then
  301. begin
  302. hp:=pchar(font);
  303. { Move to EOF in prefix header }
  304. while (hp[i] <> chr($1a)) do Inc(i);
  305. System.move(hp[i+1],FHeader,sizeof(FHeader));
  306. System.move(hp[Prefix_Size],header,sizeof(Header));
  307. {$ifdef FPC_BIG_ENDIAN}
  308. swap_fheader(fheader);
  309. swap_header(header);
  310. {$endif FPC_BIG_ENDIAN}
  311. { check if the font name is already allocated? }
  312. i:=Prefix_Size+sizeof(Header);
  313. for b:=1 to installedfonts do
  314. begin
  315. if fonts[b].name=FHeader.Font_name then
  316. begin
  317. System.move(FHeader,fonts[b].PHeader,sizeof(FHeader));
  318. System.move(Header,fonts[b].Header,sizeof(Header));
  319. System.move(hp[i],Fonts[b].Offsets[Fonts[b].Header.First_Char],Fonts[b].Header.Nr_chars*sizeof(smallint));
  320. {$ifdef FPC_BIG_ENDIAN}
  321. swap_offsets(Fonts[b].Offsets,Fonts[b].Header.First_Char,Fonts[b].Header.Nr_chars);
  322. {$endif FPC_BIG_ENDIAN}
  323. Inc(i,Fonts[b].Header.Nr_chars*sizeof(smallint));
  324. System.move(hp[i],Fonts[b].Widths[Fonts[b].Header.First_Char],Fonts[b].Header.Nr_chars*sizeof(byte));
  325. Inc(i,Fonts[b].Header.Nr_chars*sizeof(byte));
  326. counter:=Fonts[b].PHeader.font_size+PREFIX_SIZE-i;
  327. { allocate also space for null }
  328. GetMem(FontData,Counter+1);
  329. System.move(hp[i],FontData^,Counter);
  330. { Null terminate the string }
  331. FontData[counter+1] := #0;
  332. if fonts[b].header.Signature<> SIGNATURE then
  333. begin
  334. _graphResult:=grInvalidFont;
  335. System.Freemem(FontData, Counter+1);
  336. exit;
  337. end;
  338. fonts[b].instr:=FontData;
  339. fonts[b].instrlength:=Counter+1;
  340. RegisterBGIfont:=b;
  341. end;
  342. end;
  343. end
  344. else
  345. RegisterBGIFont:=grInvalidFont;
  346. end;
  347. procedure GetTextSettings(var TextInfo : TextSettingsType);
  348. begin
  349. textinfo:=currenttextinfo;
  350. end;
  351. function TextHeight(const TextString : string) : word;
  352. begin
  353. if Currenttextinfo.font=DefaultFont
  354. then TextHeight:=8*CurrentTextInfo.CharSize
  355. else
  356. TextHeight:=Trunc((fonts[Currenttextinfo.font].header.org_to_cap-
  357. fonts[Currenttextinfo.font].header.org_to_dec) * CurrentYRatio);
  358. end;
  359. function TextWidth(const TextString : string) : word;
  360. var i,x : smallint;
  361. c : byte;
  362. s : String;
  363. begin
  364. x := 0;
  365. { if this is the default font ... }
  366. if Currenttextinfo.font = Defaultfont then
  367. TextWidth:=length(TextString)*8*CurrentTextInfo.CharSize
  368. { This is a stroked font ... }
  369. else begin
  370. s := ConvertString(TextString);
  371. for i:=1 to length(s) do
  372. begin
  373. c:=byte(s[i]);
  374. { dec(c,fonts[Currenttextinfo.font].header.first_char);}
  375. if (c-fonts[Currenttextinfo.font].header.first_char>=
  376. fonts[Currenttextinfo.font].header.nr_chars) then
  377. continue;
  378. x:=x+byte(fonts[Currenttextinfo.font].widths[c]);
  379. end;
  380. TextWidth:=round(x * CurrentXRatio) ;
  381. end;
  382. end;
  383. procedure OutTextXYDefault(x,y : smallint;const TextString : string);
  384. type
  385. Tpoint = record
  386. X,Y: smallint;
  387. end;
  388. var
  389. ConvString : String;
  390. i,j,k,c : longint;
  391. xpos,ypos : longint;
  392. counter : longint;
  393. cnt1,cnt2 : smallint;
  394. cnt3,cnt4 : smallint;
  395. charsize : word;
  396. WriteMode : word;
  397. curX2, curY2, xpos2, ypos2, x2, y2: graph_float;
  398. oldvalues : linesettingstype;
  399. fontbitmap : TBitmapChar;
  400. chr : char;
  401. curx2i,cury2i,
  402. xpos2i,ypos2i : longint;
  403. begin
  404. { save current write mode }
  405. WriteMode := CurrentWriteMode;
  406. CurrentWriteMode := NormalPut;
  407. GetTextPosition(xpos,ypos,textstring);
  408. X:=X-XPos; Y:=Y+YPos;
  409. XPos:=X; YPos:=Y;
  410. ConvString := ConvertString(TextString);
  411. CharSize := CurrentTextInfo.Charsize;
  412. if Currenttextinfo.font=DefaultFont then
  413. begin
  414. c:=length(ConvString);
  415. if CurrentTextInfo.direction=HorizDir then
  416. { Horizontal direction }
  417. begin
  418. for i:=0 to c-1 do
  419. begin
  420. xpos:=x+(i*8)*Charsize;
  421. { we copy the character bitmap before accessing it }
  422. { this improves speed on non optimizing compilers }
  423. { since it is one less address calculation. }
  424. Fontbitmap:=TBitmapChar(DefaultFontData[ConvString[i+1]]);
  425. { no scaling }
  426. if CharSize = 1 then
  427. Begin
  428. for j:=0 to 7 do
  429. for k:=0 to 7 do
  430. if Fontbitmap[j,k]<>0 then
  431. PutPixel(xpos+k,j+y,CurrentColor)
  432. else if DrawTextBackground then
  433. PutPixel(xpos+k,j+y,CurrentBkColor);
  434. end
  435. else
  436. { perform scaling of bitmap font }
  437. Begin
  438. j:=0;
  439. cnt3:=0;
  440. while j <= 7 do
  441. begin
  442. { X-axis scaling }
  443. for cnt4 := 0 to charsize-1 do
  444. begin
  445. k:=0;
  446. cnt2 := 0;
  447. while k <= 7 do
  448. begin
  449. for cnt1 := 0 to charsize-1 do
  450. begin
  451. If FontBitmap[j,k] <> 0 then
  452. PutPixel(xpos+cnt1+cnt2,y+cnt3+cnt4,CurrentColor)
  453. else if DrawTextBackground then
  454. PutPixel(xpos+cnt1+cnt2,y+cnt3+cnt4,CurrentBkColor);
  455. end;
  456. Inc(k);
  457. Inc(cnt2,charsize);
  458. end;
  459. end;
  460. Inc(j);
  461. Inc(cnt3,charsize);
  462. end;
  463. end;
  464. end;
  465. end
  466. else
  467. { Vertical direction }
  468. begin
  469. for i:=0 to c-1 do
  470. begin
  471. chr := ConvString[i+1];
  472. Fontbitmap:=TBitmapChar(DefaultFontData[chr]);
  473. ypos := y-(i shl 3)*CharSize;
  474. { no scaling }
  475. if CharSize = 1 then
  476. Begin
  477. for j:=0 to 7 do
  478. for k:=0 to 7 do
  479. if Fontbitmap[j,k] <> 0 then
  480. PutPixel(xpos+j,ypos-k,CurrentColor)
  481. else if DrawTextBackground then
  482. PutPixel(xpos+j,ypos-k,CurrentBkColor);
  483. end
  484. else
  485. { perform scaling of bitmap font }
  486. Begin
  487. j:=0;
  488. cnt3:=0;
  489. while j<=7 do
  490. begin
  491. { X-axis scaling }
  492. for cnt4 := 0 to charsize-1 do
  493. begin
  494. k:=0;
  495. cnt2 := 0;
  496. while k<=7 do
  497. begin
  498. for cnt1 := 0 to charsize-1 do
  499. begin
  500. If FontBitmap[j,k] <> 0 then
  501. PutPixel(xpos+cnt3-cnt4,ypos+cnt1-cnt2,CurrentColor)
  502. else if DrawTextBackground then
  503. PutPixel(xpos+cnt3-cnt4,ypos+cnt1-cnt2,CurrentBkColor);
  504. end;
  505. Inc(k);
  506. Inc(cnt2,charsize);
  507. end;
  508. end;
  509. Inc(j);
  510. Inc(cnt3,charsize);
  511. end;
  512. end;
  513. end;
  514. end;
  515. end else
  516. { This is a stroked font which is already loaded into memory }
  517. begin
  518. getlinesettings(oldvalues);
  519. { reset line style to defaults }
  520. setlinestyle(solidln,oldvalues.pattern,normwidth);
  521. if Currenttextinfo.direction=vertdir then
  522. xpos:=xpos + Textheight(ConvString);
  523. CurX2:=xpos; xpos2 := curX2; x2 := xpos2;
  524. CurY2:=ypos; ypos2 := curY2; y2 := ypos2;
  525. { x:=xpos; y:=ypos;}
  526. for i:=1 to length(ConvString) do
  527. begin
  528. c:=byte(ConvString[i]);
  529. { Stroke_Count[c] := }
  530. unpack( fonts[CurrentTextInfo.font].instr,
  531. fonts[CurrentTextInfo.font].Offsets[c], Strokes );
  532. counter:=0;
  533. while true do
  534. begin
  535. if CurrentTextInfo.direction=VertDir then
  536. begin
  537. xpos2:=x2-(Strokes[counter].Y*CurrentYRatio);
  538. ypos2:=y2-(Strokes[counter].X*CurrentXRatio);
  539. end
  540. else
  541. begin
  542. xpos2:=x2+(Strokes[counter].X*CurrentXRatio) ;
  543. ypos2:=y2-(Strokes[counter].Y*CurrentYRatio) ;
  544. end;
  545. case opcodes(Strokes[counter].opcode) of
  546. _END_OF_CHAR: break;
  547. _DO_SCAN: begin
  548. { Currently unsupported };
  549. end;
  550. _MOVE : Begin
  551. CurX2 := XPos2;
  552. CurY2 := YPos2;
  553. end;
  554. _DRAW: Begin
  555. curx2i:=trunc(CurX2);
  556. cury2i:=trunc(CurY2);
  557. xpos2i:=trunc(xpos2);
  558. ypos2i:=trunc(ypos2);
  559. { this optimization doesn't matter that much
  560. if (curx2i=xpos2i) then
  561. begin
  562. if (cury2i=ypos2i) then
  563. putpixel(curx2i,cury2i,currentcolor)
  564. else if (cury2i+1=ypos2i) or
  565. (cury2i=ypos2i+1) then
  566. begin
  567. putpixel(curx2i,cury2i,currentcolor);
  568. putpixel(curx2i,ypos2i,currentcolor);
  569. end
  570. else
  571. Line(curx2i,cury2i,xpos2i,ypos2i);
  572. end
  573. else if (cury2i=ypos2i) then
  574. begin
  575. if (curx2i+1=xpos2i) or
  576. (curx2i=xpos2i+1) then
  577. begin
  578. putpixel(curx2i,cury2i,currentcolor);
  579. putpixel(xpos2i,cury2i,currentcolor);
  580. end
  581. else
  582. Line(curx2i,cury2i,xpos2i,ypos2i);
  583. end
  584. else
  585. }
  586. Line(curx2i,cury2i,xpos2i,ypos2i);
  587. CurX2:=xpos2;
  588. CurY2:=ypos2;
  589. end;
  590. else
  591. Begin
  592. end;
  593. end;
  594. Inc(counter);
  595. end; { end while }
  596. if Currenttextinfo.direction=VertDir then
  597. y2:=y2-(byte(fonts[CurrenttextInfo.font].widths[c])*CurrentXRatio)
  598. else
  599. x2:=x2+(byte(fonts[Currenttextinfo.font].widths[c])*CurrentXRatio);
  600. end;
  601. setlinestyle( oldvalues.linestyle, oldvalues.pattern, oldvalues.thickness);
  602. end;
  603. { restore write mode }
  604. CurrentWriteMode := WriteMode;
  605. end;
  606. procedure OutText(const TextString : string);
  607. var x,y:smallint;
  608. begin
  609. { Save CP }
  610. x:=CurrentX;
  611. y:=CurrentY;
  612. OutTextXY(CurrentX,CurrentY,TextString);
  613. { If the direction is Horizontal and the justification left }
  614. { then and only then do we update the CP }
  615. if (Currenttextinfo.direction=HorizDir) and
  616. (Currenttextinfo.horiz=LeftText) then
  617. inc(x,textwidth(TextString));
  618. { Update the CP }
  619. CurrentX := X;
  620. CurrentY := Y;
  621. end;
  622. procedure SetTextJustify(horiz,vert : word);
  623. begin
  624. if (horiz<0) or (horiz>2) or
  625. (vert<0) or (vert>2) then
  626. begin
  627. _graphresult:=grError;
  628. exit;
  629. end;
  630. Currenttextinfo.horiz:=horiz;
  631. Currenttextinfo.vert:=vert;
  632. end;
  633. procedure SetTextStyle(font,direction : word;charsize : word);
  634. var
  635. f : file;
  636. Prefix: array[0..Prefix_Size-1] of char; {* File Prefix Holder *}
  637. Length, Current: longint;
  638. FontData: Pchar;
  639. hp : pchar;
  640. i : longint;
  641. begin
  642. if font>installedfonts then
  643. begin
  644. _graphresult:=grInvalidFontNum;
  645. exit;
  646. end;
  647. Currenttextinfo.font:=font;
  648. if (direction<>HorizDir) and (direction<>VertDir) then
  649. direction:=HorizDir;
  650. Currenttextinfo.direction:=direction;
  651. { According to the Turbo Pascal programmer's reference }
  652. { maximum charsize for bitmapped font is 10 }
  653. if (CurrentTextInfo.Font = DefaultFont) and (Charsize > 10) then
  654. Currenttextinfo.charsize:=10
  655. else if charsize<1 then
  656. Currenttextinfo.charsize:=1
  657. else
  658. Currenttextinfo.charsize:=charsize;
  659. { This is only valid for stroked fonts }
  660. {$ifdef logging}
  661. LogLn('(org_to_cap - org_to_dec): ' + strf(
  662. fonts[Currenttextinfo.font].header.org_to_cap-
  663. fonts[Currenttextinfo.font].header.org_to_dec));
  664. {$endif logging}
  665. if (charsize <> usercharsize) then
  666. Case CharSize of
  667. 1: Begin
  668. CurrentXRatio := 0.55;
  669. CurrentYRatio := 0.55;
  670. End;
  671. 2: Begin
  672. CurrentXRatio := 0.65;
  673. CurrentYRatio := 0.65;
  674. End;
  675. 3: Begin
  676. CurrentXRatio := 0.75;
  677. CurrentYRatio := 0.75;
  678. End;
  679. 4: Begin
  680. CurrentXRatio := 1.0;
  681. CurrentYRatio := 1.0;
  682. End;
  683. 5: Begin
  684. CurrentXRatio := 1.3;
  685. CurrentYRatio := 1.3;
  686. End;
  687. 6: Begin
  688. CurrentXRatio := 1.65;
  689. CurrentYRatio := 1.65
  690. End;
  691. 7: Begin
  692. CurrentXRatio := 2.0;
  693. CurrentYRatio := 2.0;
  694. End;
  695. 8: Begin
  696. CurrentXRatio := 2.5;
  697. CurrentYRatio := 2.5;
  698. End;
  699. 9: Begin
  700. CurrentXRatio := 3.0;
  701. CurrentYRatio := 3.0;
  702. End;
  703. 10: Begin
  704. CurrentXRatio := 4.0;
  705. CurrentYRatio := 4.0;
  706. End
  707. End;
  708. { if this is a stroked font then load it if not already loaded }
  709. { into memory... }
  710. if (font>DefaultFont) and not assigned(fonts[font].instr) then
  711. begin
  712. assign(f,bgipath+fonts[font].name+'.CHR');
  713. {$ifopt I+}
  714. {$define IOCHECK_WAS_ON}
  715. {$i-}
  716. {$endif}
  717. reset(f,1);
  718. {$ifdef IOCHECK_WAS_ON}
  719. {$i+}
  720. {$endif}
  721. if ioresult<>0 then
  722. begin
  723. _graphresult:=grFontNotFound;
  724. Currenttextinfo.font:=DefaultFont;
  725. exit;
  726. end;
  727. {* Read in the file prefix *}
  728. BlockRead(F, Prefix, Prefix_Size);
  729. hp:=Prefix;
  730. i:=0;
  731. while (hp[i] <> chr($1a)) do Inc(i);
  732. System.move(hp[i+1],fonts[font].PHeader,sizeof(TFHeader));
  733. (* Read in the Header file *)
  734. BlockRead(F,fonts[font].Header,Sizeof(THeader));
  735. {$ifdef FPC_BIG_ENDIAN}
  736. swap_fheader(fonts[font].PHeader);
  737. swap_header(fonts[font].Header);
  738. {$endif FPC_BIG_ENDIAN}
  739. BlockRead(F,Fonts[font].Offsets[Fonts[font].Header.First_Char],Fonts[font].Header.Nr_chars*sizeof(smallint));
  740. {$ifdef FPC_BIG_ENDIAN}
  741. swap_offsets(Fonts[font].Offsets,Fonts[font].Header.First_Char,Fonts[font].Header.Nr_chars);
  742. {$endif FPC_BIG_ENDIAN}
  743. {* Load the character width table into memory. *}
  744. BlockRead(F,Fonts[font].Widths[Fonts[font].Header.First_Char],Fonts[font].Header.Nr_chars*sizeof(byte));
  745. {* Determine the length of the stroke database. *}
  746. current := FilePos( f ); {* Current file location *}
  747. Seek( f, FileSize(F)); {* Go to the end of the file *}
  748. length := FilePos( f ); {* Get the file length *}
  749. Seek( f, current); {* Restore old file location *}
  750. {* Load the stroke database. *}
  751. { also allocate space for Null character }
  752. Getmem(FontData, Length+1); {* Create space for font data *}
  753. BlockRead(F, FontData^, length-current); {* Load the stroke data *}
  754. FontData[length-current+1] := #0;
  755. if fonts[font].header.Signature<> SIGNATURE then
  756. begin
  757. _graphResult:=grInvalidFont;
  758. Currenttextinfo.font:=DefaultFont;
  759. System.Freemem(FontData, Length+1);
  760. exit;
  761. end;
  762. fonts[font].instr:=FontData;
  763. fonts[font].instrLength:=Length+1;
  764. if not testfont(Prefix) then
  765. begin
  766. _graphresult:=grInvalidFont;
  767. Currenttextinfo.font:=DefaultFont;
  768. System.Freemem(FontData, Length+1);
  769. end;
  770. close(f);
  771. end;
  772. end;
  773. procedure SetUserCharSize(Multx,Divx,Multy,Divy : word);
  774. begin
  775. CurrentXRatio := MultX / DivX;
  776. CurrentYRatio := MultY / DivY;
  777. end;