gtext.inc 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854
  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:=byte((shortint(b1 and $80) shr 6)+(shortint(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. {$push}
  178. {$R-}
  179. b1:=b1 and $7f;
  180. b2:=b2 and $7f;
  181. { Now if the MSB of these values are set }
  182. { then the value is signed, therefore we }
  183. { sign extend it... }
  184. if (b1 and $40)<>0 then b1:=b1 or $80;
  185. if (b2 and $40)<>0 then b2:=b2 or $80;
  186. x:=smallint(b1);
  187. y:=smallint(b2);
  188. { restore previous range check mode }
  189. {$pop}
  190. end;
  191. function unpack(buf: pchar; index: smallint; var Stroke: TStrokes): smallint;
  192. var
  193. po: TStrokes;
  194. num_ops: smallint;
  195. opcode, i, opc: word;
  196. counter: smallint;
  197. lindex: smallint;
  198. jx, jy: smallint;
  199. begin
  200. num_ops := 0;
  201. counter := index;
  202. lindex :=0;
  203. while TRUE do {* For each byte in buffer *}
  204. Begin
  205. Inc(num_ops); {* Count the operation *}
  206. opcode := decode( buf[counter], buf[counter+1] ,jx, jy );
  207. Inc(counter,2);
  208. if( opcode = ord(_END_OF_CHAR) ) then break; {* Exit loop at end of char *}
  209. end;
  210. counter:=index;
  211. for i:=0 to num_ops-1 do { /* For each opcode in buffer */ }
  212. Begin
  213. opc := decode(buf[counter], buf[counter+1], po[lindex].x, po[lindex].y); {* Decode the data field *}
  214. inc(counter,2);
  215. po[lindex].opcode := opc; {* Save the opcode *}
  216. Inc(lindex);
  217. end;
  218. Stroke:=po;
  219. unpack := num_ops; {* return OPS count *}
  220. end;
  221. procedure GetTextPosition(var xpos,ypos: longint; const TextString: string);
  222. begin
  223. if CurrentTextInfo.Font = DefaultFont then
  224. begin
  225. if Currenttextinfo.direction=horizdir then
  226. begin
  227. case Currenttextinfo.horiz of
  228. centertext : XPos:=(textwidth(textstring) shr 1);
  229. lefttext : XPos:=0;
  230. righttext : XPos:=textwidth(textstring);
  231. end;
  232. case Currenttextinfo.vert of
  233. centertext : YPos:=-(textheight(textstring) shr 1);
  234. bottomtext : YPos:=-textheight(textstring);
  235. toptext : YPos:=0;
  236. end;
  237. end else
  238. begin
  239. case Currenttextinfo.horiz of
  240. centertext : XPos:=(textheight(textstring) shr 1);
  241. lefttext : XPos:=textheight(textstring);
  242. righttext : XPos:=textheight(textstring);
  243. end;
  244. case Currenttextinfo.vert of
  245. centertext : YPos:=(textwidth(textstring) shr 1);
  246. bottomtext : YPos:=0;
  247. toptext : YPos:=textwidth(textstring);
  248. end;
  249. end;
  250. end
  251. else
  252. begin
  253. if Currenttextinfo.direction=horizdir then
  254. begin
  255. case CurrentTextInfo.horiz of
  256. centertext : XPos:=(textwidth(textstring) shr 1);
  257. lefttext : XPos:=0;
  258. righttext : XPos:=textwidth(textstring);
  259. end;
  260. case CurrentTextInfo.vert of
  261. centertext : YPos:=(textheight(textstring) shr 1);
  262. bottomtext : YPos:=0;
  263. toptext : YPos:=textheight(textstring);
  264. end;
  265. end else
  266. begin
  267. case CurrentTextInfo.horiz of
  268. centertext : XPos:=(textheight(textstring) shr 1);
  269. lefttext : XPos:=0;
  270. righttext : XPos:=textheight(textstring);
  271. end;
  272. case CurrentTextInfo.vert of
  273. centertext : YPos:=(textwidth(textstring) shr 1);
  274. bottomtext : YPos:=0;
  275. toptext : YPos:=textwidth(textstring);
  276. end;
  277. end;
  278. end;
  279. end;
  280. {***************************************************************************}
  281. { Exported routines }
  282. {***************************************************************************}
  283. function RegisterBGIfont(font : pointer) : smallint;
  284. var
  285. hp : pchar;
  286. b : word;
  287. i: longint;
  288. Header: THeader;
  289. counter: longint;
  290. FontData: pchar;
  291. FHeader: TFHeader;
  292. begin
  293. RegisterBGIfont:=grInvalidFontNum;
  294. i:=0;
  295. { Check if the font header is valid first of all }
  296. if testfont(font) then
  297. begin
  298. hp:=pchar(font);
  299. { Move to EOF in prefix header }
  300. while (hp[i] <> chr($1a)) do Inc(i);
  301. System.move(hp[i+1],FHeader,sizeof(FHeader));
  302. System.move(hp[Prefix_Size],header,sizeof(Header));
  303. {$ifdef FPC_BIG_ENDIAN}
  304. swap_fheader(fheader);
  305. swap_header(header);
  306. {$endif FPC_BIG_ENDIAN}
  307. { check if the font name is already allocated? }
  308. i:=Prefix_Size+sizeof(Header);
  309. for b:=1 to installedfonts do
  310. begin
  311. if fonts[b].name=FHeader.Font_name then
  312. begin
  313. System.move(FHeader,fonts[b].PHeader,sizeof(FHeader));
  314. System.move(Header,fonts[b].Header,sizeof(Header));
  315. System.move(hp[i],Fonts[b].Offsets[Fonts[b].Header.First_Char],Fonts[b].Header.Nr_chars*sizeof(smallint));
  316. {$ifdef FPC_BIG_ENDIAN}
  317. swap_offsets(Fonts[b].Offsets,Fonts[b].Header.First_Char,Fonts[b].Header.Nr_chars);
  318. {$endif FPC_BIG_ENDIAN}
  319. Inc(i,Fonts[b].Header.Nr_chars*sizeof(smallint));
  320. System.move(hp[i],Fonts[b].Widths[Fonts[b].Header.First_Char],Fonts[b].Header.Nr_chars*sizeof(byte));
  321. Inc(i,Fonts[b].Header.Nr_chars*sizeof(byte));
  322. counter:=Fonts[b].PHeader.font_size+PREFIX_SIZE-i;
  323. { allocate also space for null }
  324. GetMem(FontData,Counter+1);
  325. System.move(hp[i],FontData^,Counter);
  326. { Null terminate the string }
  327. FontData[counter+1] := #0;
  328. if fonts[b].header.Signature<> SIGNATURE then
  329. begin
  330. _graphResult:=grInvalidFont;
  331. System.Freemem(FontData, Counter+1);
  332. exit;
  333. end;
  334. fonts[b].instr:=FontData;
  335. fonts[b].instrlength:=Counter+1;
  336. RegisterBGIfont:=b;
  337. end;
  338. end;
  339. end
  340. else
  341. RegisterBGIFont:=grInvalidFont;
  342. end;
  343. procedure GetTextSettings(var TextInfo : TextSettingsType);
  344. begin
  345. textinfo:=currenttextinfo;
  346. end;
  347. function TextHeight(const TextString : string) : word;
  348. begin
  349. if Currenttextinfo.font=DefaultFont
  350. then TextHeight:=8*CurrentTextInfo.CharSize
  351. else
  352. TextHeight:=Trunc((fonts[Currenttextinfo.font].header.org_to_cap-
  353. fonts[Currenttextinfo.font].header.org_to_dec) * CurrentYRatio);
  354. end;
  355. function TextWidth(const TextString : string) : word;
  356. var i,x : smallint;
  357. c : byte;
  358. s : String;
  359. begin
  360. x := 0;
  361. { if this is the default font ... }
  362. if Currenttextinfo.font = Defaultfont then
  363. TextWidth:=length(TextString)*8*CurrentTextInfo.CharSize
  364. { This is a stroked font ... }
  365. else begin
  366. s := ConvertString(TextString);
  367. for i:=1 to length(s) do
  368. begin
  369. c:=byte(s[i]);
  370. { dec(c,fonts[Currenttextinfo.font].header.first_char);}
  371. if (c-fonts[Currenttextinfo.font].header.first_char>=
  372. fonts[Currenttextinfo.font].header.nr_chars) then
  373. continue;
  374. x:=x+byte(fonts[Currenttextinfo.font].widths[c]);
  375. end;
  376. TextWidth:=round(x * CurrentXRatio) ;
  377. end;
  378. end;
  379. procedure OutTextXYDefault(x,y : smallint;const TextString : string);
  380. type
  381. Tpoint = record
  382. X,Y: smallint;
  383. end;
  384. var
  385. ConvString : String;
  386. i,j,k,c : longint;
  387. xpos,ypos : longint;
  388. counter : longint;
  389. cnt1,cnt2 : smallint;
  390. cnt3,cnt4 : smallint;
  391. charsize : word;
  392. WriteMode : word;
  393. curX2, curY2, xpos2, ypos2, x2, y2: graph_float;
  394. oldvalues : linesettingstype;
  395. fontbitmap : TBitmapChar;
  396. chr : char;
  397. curx2i,cury2i,
  398. xpos2i,ypos2i : longint;
  399. begin
  400. { save current write mode }
  401. WriteMode := CurrentWriteMode;
  402. CurrentWriteMode := NormalPut;
  403. GetTextPosition(xpos,ypos,textstring);
  404. X:=X-XPos; Y:=Y+YPos;
  405. XPos:=X; YPos:=Y;
  406. ConvString := ConvertString(TextString);
  407. CharSize := CurrentTextInfo.Charsize;
  408. if Currenttextinfo.font=DefaultFont then
  409. begin
  410. c:=length(ConvString);
  411. if CurrentTextInfo.direction=HorizDir then
  412. { Horizontal direction }
  413. begin
  414. for i:=0 to c-1 do
  415. begin
  416. xpos:=x+(i*8)*Charsize;
  417. { we copy the character bitmap before accessing it }
  418. { this improves speed on non optimizing compilers }
  419. { since it is one less address calculation. }
  420. Fontbitmap:=TBitmapChar(DefaultFontData[ConvString[i+1]]);
  421. { no scaling }
  422. if CharSize = 1 then
  423. Begin
  424. for j:=0 to 7 do
  425. for k:=0 to 7 do
  426. if Fontbitmap[j,k]<>0 then
  427. PutPixel(xpos+k,j+y,CurrentColor)
  428. else if DrawTextBackground then
  429. PutPixel(xpos+k,j+y,CurrentBkColor);
  430. end
  431. else
  432. { perform scaling of bitmap font }
  433. Begin
  434. j:=0;
  435. cnt3:=0;
  436. while j <= 7 do
  437. begin
  438. { X-axis scaling }
  439. for cnt4 := 0 to charsize-1 do
  440. begin
  441. k:=0;
  442. cnt2 := 0;
  443. while k <= 7 do
  444. begin
  445. for cnt1 := 0 to charsize-1 do
  446. begin
  447. If FontBitmap[j,k] <> 0 then
  448. PutPixel(xpos+cnt1+cnt2,y+cnt3+cnt4,CurrentColor)
  449. else if DrawTextBackground then
  450. PutPixel(xpos+cnt1+cnt2,y+cnt3+cnt4,CurrentBkColor);
  451. end;
  452. Inc(k);
  453. Inc(cnt2,charsize);
  454. end;
  455. end;
  456. Inc(j);
  457. Inc(cnt3,charsize);
  458. end;
  459. end;
  460. end;
  461. end
  462. else
  463. { Vertical direction }
  464. begin
  465. for i:=0 to c-1 do
  466. begin
  467. chr := ConvString[i+1];
  468. Fontbitmap:=TBitmapChar(DefaultFontData[chr]);
  469. ypos := y-(i shl 3)*CharSize;
  470. { no scaling }
  471. if CharSize = 1 then
  472. Begin
  473. for j:=0 to 7 do
  474. for k:=0 to 7 do
  475. if Fontbitmap[j,k] <> 0 then
  476. PutPixel(xpos+j,ypos-k,CurrentColor)
  477. else if DrawTextBackground then
  478. PutPixel(xpos+j,ypos-k,CurrentBkColor);
  479. end
  480. else
  481. { perform scaling of bitmap font }
  482. Begin
  483. j:=0;
  484. cnt3:=0;
  485. while j<=7 do
  486. begin
  487. { X-axis scaling }
  488. for cnt4 := 0 to charsize-1 do
  489. begin
  490. k:=0;
  491. cnt2 := 0;
  492. while k<=7 do
  493. begin
  494. for cnt1 := 0 to charsize-1 do
  495. begin
  496. If FontBitmap[j,k] <> 0 then
  497. PutPixel(xpos+cnt3-cnt4,ypos+cnt1-cnt2,CurrentColor)
  498. else if DrawTextBackground then
  499. PutPixel(xpos+cnt3-cnt4,ypos+cnt1-cnt2,CurrentBkColor);
  500. end;
  501. Inc(k);
  502. Inc(cnt2,charsize);
  503. end;
  504. end;
  505. Inc(j);
  506. Inc(cnt3,charsize);
  507. end;
  508. end;
  509. end;
  510. end;
  511. end else
  512. { This is a stroked font which is already loaded into memory }
  513. begin
  514. getlinesettings(oldvalues);
  515. { reset line style to defaults }
  516. setlinestyle(solidln,oldvalues.pattern,normwidth);
  517. if Currenttextinfo.direction=vertdir then
  518. xpos:=xpos + Textheight(ConvString);
  519. CurX2:=xpos; xpos2 := curX2; x2 := xpos2;
  520. CurY2:=ypos; ypos2 := curY2; y2 := ypos2;
  521. { x:=xpos; y:=ypos;}
  522. for i:=1 to length(ConvString) do
  523. begin
  524. c:=byte(ConvString[i]);
  525. { Stroke_Count[c] := }
  526. unpack( fonts[CurrentTextInfo.font].instr,
  527. fonts[CurrentTextInfo.font].Offsets[c], Strokes );
  528. counter:=0;
  529. while true do
  530. begin
  531. if CurrentTextInfo.direction=VertDir then
  532. begin
  533. xpos2:=x2-(Strokes[counter].Y*CurrentYRatio);
  534. ypos2:=y2-(Strokes[counter].X*CurrentXRatio);
  535. end
  536. else
  537. begin
  538. xpos2:=x2+(Strokes[counter].X*CurrentXRatio) ;
  539. ypos2:=y2-(Strokes[counter].Y*CurrentYRatio) ;
  540. end;
  541. case opcodes(Strokes[counter].opcode) of
  542. _END_OF_CHAR: break;
  543. _DO_SCAN: begin
  544. { Currently unsupported };
  545. end;
  546. _MOVE : Begin
  547. CurX2 := XPos2;
  548. CurY2 := YPos2;
  549. end;
  550. _DRAW: Begin
  551. curx2i:=trunc(CurX2);
  552. cury2i:=trunc(CurY2);
  553. xpos2i:=trunc(xpos2);
  554. ypos2i:=trunc(ypos2);
  555. { this optimization doesn't matter that much
  556. if (curx2i=xpos2i) then
  557. begin
  558. if (cury2i=ypos2i) then
  559. putpixel(curx2i,cury2i,currentcolor)
  560. else if (cury2i+1=ypos2i) or
  561. (cury2i=ypos2i+1) then
  562. begin
  563. putpixel(curx2i,cury2i,currentcolor);
  564. putpixel(curx2i,ypos2i,currentcolor);
  565. end
  566. else
  567. Line(curx2i,cury2i,xpos2i,ypos2i);
  568. end
  569. else if (cury2i=ypos2i) then
  570. begin
  571. if (curx2i+1=xpos2i) or
  572. (curx2i=xpos2i+1) then
  573. begin
  574. putpixel(curx2i,cury2i,currentcolor);
  575. putpixel(xpos2i,cury2i,currentcolor);
  576. end
  577. else
  578. Line(curx2i,cury2i,xpos2i,ypos2i);
  579. end
  580. else
  581. }
  582. Line(curx2i,cury2i,xpos2i,ypos2i);
  583. CurX2:=xpos2;
  584. CurY2:=ypos2;
  585. end;
  586. else
  587. Begin
  588. end;
  589. end;
  590. Inc(counter);
  591. end; { end while }
  592. if Currenttextinfo.direction=VertDir then
  593. y2:=y2-(byte(fonts[CurrenttextInfo.font].widths[c])*CurrentXRatio)
  594. else
  595. x2:=x2+(byte(fonts[Currenttextinfo.font].widths[c])*CurrentXRatio);
  596. end;
  597. setlinestyle( oldvalues.linestyle, oldvalues.pattern, oldvalues.thickness);
  598. end;
  599. { restore write mode }
  600. CurrentWriteMode := WriteMode;
  601. end;
  602. procedure OutText(const TextString : string);
  603. var x,y:smallint;
  604. begin
  605. { Save CP }
  606. x:=CurrentX;
  607. y:=CurrentY;
  608. OutTextXY(CurrentX,CurrentY,TextString);
  609. { If the direction is Horizontal and the justification left }
  610. { then and only then do we update the CP }
  611. if (Currenttextinfo.direction=HorizDir) and
  612. (Currenttextinfo.horiz=LeftText) then
  613. inc(x,textwidth(TextString));
  614. { Update the CP }
  615. CurrentX := X;
  616. CurrentY := Y;
  617. end;
  618. procedure SetTextJustify(horiz,vert : word);
  619. begin
  620. if (horiz<0) or (horiz>2) or
  621. (vert<0) or (vert>2) then
  622. begin
  623. _graphresult:=grError;
  624. exit;
  625. end;
  626. Currenttextinfo.horiz:=horiz;
  627. Currenttextinfo.vert:=vert;
  628. end;
  629. procedure SetTextStyle(font,direction : word;charsize : word);
  630. var
  631. f : file;
  632. Prefix: array[0..Prefix_Size-1] of char; {* File Prefix Holder *}
  633. Length, Current: longint;
  634. FontData: Pchar;
  635. hp : pchar;
  636. i : longint;
  637. begin
  638. if font>installedfonts then
  639. begin
  640. _graphresult:=grInvalidFontNum;
  641. exit;
  642. end;
  643. Currenttextinfo.font:=font;
  644. if (direction<>HorizDir) and (direction<>VertDir) then
  645. direction:=HorizDir;
  646. Currenttextinfo.direction:=direction;
  647. { According to the Turbo Pascal programmer's reference }
  648. { maximum charsize for bitmapped font is 10 }
  649. if (CurrentTextInfo.Font = DefaultFont) and (Charsize > 10) then
  650. Currenttextinfo.charsize:=10
  651. else if charsize<1 then
  652. Currenttextinfo.charsize:=1
  653. else
  654. Currenttextinfo.charsize:=charsize;
  655. { This is only valid for stroked fonts }
  656. {$ifdef logging}
  657. LogLn('(org_to_cap - org_to_dec): ' + strf(
  658. fonts[Currenttextinfo.font].header.org_to_cap-
  659. fonts[Currenttextinfo.font].header.org_to_dec));
  660. {$endif logging}
  661. if (charsize <> usercharsize) then
  662. Case CharSize of
  663. 1: Begin
  664. CurrentXRatio := 0.55;
  665. CurrentYRatio := 0.55;
  666. End;
  667. 2: Begin
  668. CurrentXRatio := 0.65;
  669. CurrentYRatio := 0.65;
  670. End;
  671. 3: Begin
  672. CurrentXRatio := 0.75;
  673. CurrentYRatio := 0.75;
  674. End;
  675. 4: Begin
  676. CurrentXRatio := 1.0;
  677. CurrentYRatio := 1.0;
  678. End;
  679. 5: Begin
  680. CurrentXRatio := 1.3;
  681. CurrentYRatio := 1.3;
  682. End;
  683. 6: Begin
  684. CurrentXRatio := 1.65;
  685. CurrentYRatio := 1.65
  686. End;
  687. 7: Begin
  688. CurrentXRatio := 2.0;
  689. CurrentYRatio := 2.0;
  690. End;
  691. 8: Begin
  692. CurrentXRatio := 2.5;
  693. CurrentYRatio := 2.5;
  694. End;
  695. 9: Begin
  696. CurrentXRatio := 3.0;
  697. CurrentYRatio := 3.0;
  698. End;
  699. 10: Begin
  700. CurrentXRatio := 4.0;
  701. CurrentYRatio := 4.0;
  702. End
  703. End;
  704. { if this is a stroked font then load it if not already loaded }
  705. { into memory... }
  706. if (font>DefaultFont) and not assigned(fonts[font].instr) then
  707. begin
  708. assign(f,bgipath+fonts[font].name+'.CHR');
  709. {$push}
  710. {$i-}
  711. reset(f,1);
  712. {$pop}
  713. if ioresult<>0 then
  714. begin
  715. _graphresult:=grFontNotFound;
  716. Currenttextinfo.font:=DefaultFont;
  717. exit;
  718. end;
  719. {* Read in the file prefix *}
  720. BlockRead(F, Prefix, Prefix_Size);
  721. hp:=Prefix;
  722. i:=0;
  723. while (hp[i] <> chr($1a)) do Inc(i);
  724. System.move(hp[i+1],fonts[font].PHeader,sizeof(TFHeader));
  725. (* Read in the Header file *)
  726. BlockRead(F,fonts[font].Header,Sizeof(THeader));
  727. {$ifdef FPC_BIG_ENDIAN}
  728. swap_fheader(fonts[font].PHeader);
  729. swap_header(fonts[font].Header);
  730. {$endif FPC_BIG_ENDIAN}
  731. BlockRead(F,Fonts[font].Offsets[Fonts[font].Header.First_Char],Fonts[font].Header.Nr_chars*sizeof(smallint));
  732. {$ifdef FPC_BIG_ENDIAN}
  733. swap_offsets(Fonts[font].Offsets,Fonts[font].Header.First_Char,Fonts[font].Header.Nr_chars);
  734. {$endif FPC_BIG_ENDIAN}
  735. {* Load the character width table into memory. *}
  736. BlockRead(F,Fonts[font].Widths[Fonts[font].Header.First_Char],Fonts[font].Header.Nr_chars*sizeof(byte));
  737. {* Determine the length of the stroke database. *}
  738. current := FilePos( f ); {* Current file location *}
  739. Seek( f, FileSize(F)); {* Go to the end of the file *}
  740. length := FilePos( f ); {* Get the file length *}
  741. Seek( f, current); {* Restore old file location *}
  742. {* Load the stroke database. *}
  743. { also allocate space for Null character }
  744. Getmem(FontData, Length+1); {* Create space for font data *}
  745. BlockRead(F, FontData^, length-current); {* Load the stroke data *}
  746. FontData[length-current+1] := #0;
  747. if fonts[font].header.Signature<> SIGNATURE then
  748. begin
  749. _graphResult:=grInvalidFont;
  750. Currenttextinfo.font:=DefaultFont;
  751. System.Freemem(FontData, Length+1);
  752. exit;
  753. end;
  754. fonts[font].instr:=FontData;
  755. fonts[font].instrLength:=Length+1;
  756. if not testfont(Prefix) then
  757. begin
  758. _graphresult:=grInvalidFont;
  759. Currenttextinfo.font:=DefaultFont;
  760. System.Freemem(FontData, Length+1);
  761. end;
  762. close(f);
  763. end;
  764. end;
  765. procedure SetUserCharSize(Multx,Divx,Multy,Divy : word);
  766. begin
  767. CurrentXRatio := MultX / DivX;
  768. CurrentYRatio := MultY / DivY;
  769. end;