gtext.inc 32 KB

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