build fix: no comphelper/profilezone.hxx in this branch
[LibreOffice.git] / vcl / source / filter / sgvtext.cxx
blob9fcf62dba545c553ce609fb9c2265758a73b44b5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "sal/config.h"
22 #include <osl/thread.h>
23 #include <rtl/math.h>
24 #include <comphelper/string.hxx>
25 #include <tools/config.hxx>
26 #include <tools/fract.hxx>
27 #include <vcl/graphicfilter.hxx>
28 #include "sgffilt.hxx"
29 #include "sgfbram.hxx"
30 #include "sgvmain.hxx"
31 #include <memory>
32 #include <cstdlib>
34 extern SgfFontLst* pSgfFonts;
36 // Limitations: only grey shadows, 2D and with fixed distance.
37 // Start of AbsBase.Pas
39 // vvv special characters in text buffer vvv
40 #define TextEnd 0 /* ^@ end of character sequence */
41 #define HardSpace 6 /* ^F non-breaking space,' ' */
42 #define SoftTrennK 11 /* ^K character for k-c-switch for separation, 'k' */
43 #define AbsatzEnd 13 /* ^M new paragraph=CR */
44 #define HardTrenn 16 /* ^P hard separator (not wrapped), '-' */
45 #define SoftTrennAdd 19 /* ^S extra-character, separates e.g. "schiff-fahrt" */
46 #define Escape 27 /* ^[ start of escape sequence */
47 #define SoftTrenn 31 /* ^_ soft separator, '-' only end of line */
48 #define MaxEscValLen 8
49 #define MaxEscLen (MaxEscValLen+3)
51 // Escape sequences: [Esc]<Ident><Value>[Esc] at least 4 characters
52 // Max length of value should be: 8 chars (7+sign). Therefore max. length
53 // of a escape sequence: 11 chars.
54 // Identifer:
56 #define EscFont 'F' /* fontID, e.g. 92500 for CG Times */
57 #define EscGrad 'G' /* font angle 1..255 for <<Pt-127<<Pt */
58 #define EscBreit 'B' /* width 1..255% of the font angle */
59 #define EscKaptS 'K' /* uppercase size 1..255% of the text angle */
60 #define EscLFeed 'L' /* character spacing 1..32767% of max. text angle of the line*/
61 // or 1..32767 for 1..16383<<Pt absolute (if bit 15=1)
62 #define EscSlant 'S' /* italic (angle) 1..8999 for 0.01deg..89.99deg */
63 #define EscVPos 'V' /* character vertical position 1..255 for <<Pt..127<<Pt */
64 #define EscZAbst 'Z' /* character spacing -128..127% */
65 #define EscHJust 'A' /* H-justify paragraph: left, cent, right, block, aligned, fixed (0..5)*/
67 #define EscFarbe 'C' /* colour 0..7 */
68 #define EscBFarb 'U' /* background colour 0..7 */
69 #define EscInts 'I' /* colour intensity 0..100% */
70 #define EscMustr 'M' /* pattern 0..? incl. transp... */
71 #define EscMFarb 'O' /* pattern colour 0..7 */
72 #define EscMBFrb 'P' /* 2nd pattern colour 0..7 */
73 #define EscMInts 'W' /* pattern intensity 0..7 */
75 #define EscSMstr 'E' /* shadow pattern 0..? inkl. Transp... */
76 #define EscSFarb 'R' /* shadow colour 0..7 */
77 #define EscSBFrb 'T' /* 2nd shadow colour 0..7 */
78 #define EscSInts 'Q' /* shadow intensity 0..7 */
80 #define EscSXDst 'X' /* shadow offset X 0..100% */
81 #define EscSYDst 'Y' /* shadow offset Y 0..100% */
82 #define EscSDist 'D' /* shadow offset X-Y 0..100% */
84 #define EscBold 'f' /* bold */
85 #define EscLSlnt 'l' /* L italic */
86 #define EscRSlnt 'r' /* R italic */
87 #define EscUndln 'u' /* underlined */
88 #define EscDbUnd 'p' /* double underlined */
89 #define EscKaptF 'k' /* uppercase flag */
90 #define EscStrik 'd' /* strikethrough */
91 #define EscDbStk 'e' /* double strikethrough */
92 #define EscSupSc 'h' /* superscript */
93 #define EscSubSc 't' /* subscript */
94 #define Esc2DShd 's' /* 2D-shadow */
95 #define Esc3DShd 'j' /* 3D-shadow */
96 #define Esc4DShd 'i' /* 4D-shadow */
97 #define EscEbShd 'b' /* embossed */
99 // AllEscIdent =[EscFont, EscGrad, EscBreit,EscKaptS,EscLFeed,EscSlant,EscVPos, EscZAbst,EscHJust,
100 // EscFarbe,EscBFarb,EscInts, EscMustr,EscMFarb,EscMBFrb,EscMInts,
101 // EscSMstr,EscSFarb,EscSBFrb,EscSInts,EscSXDst,EscSYDst,EscSDist,
102 // EscBold, EscLSlnt,EscRSlnt,EscUndln,EscDbUnd,EscKaptF,EscStrik,EscDbStk,
103 // EscSupSc,EscSubSc,Esc2DShd,Esc3DShd,Esc4DShd];
104 // Justify muss spaetestens am Anfang des Absatzes stehen
105 #define EscSet '\x1e' /* set flag */
106 #define EscReset '\x1f' /* reset flag */
107 #define EscDeflt '\x11' /* set flag to default */
108 #define EscToggl '\x1d' /* toggle flag */
109 #define EscNoFlg 0
110 #define EscNoVal -2147483647 /* -MaxLongInt */
112 #define NoTrenn 0xFFFF /* parameter value for 'Rest' of GetTextChar(), if separation should not occur */
113 #define DoTrenn 0xFFFE /* parameter value for 'Rest' of GetTextChar(), if separtion should occur */
115 #define MaxLineChars 1024
117 #define ChrXPosArrSize (MaxLineChars+1+1) /* 2k - start with 0 opposite to StarDraw */
118 #define CharLineSize (MaxLineChars+1+1)
120 #define MinChar 32
121 #define MaxChar 255
123 #define CharTopToBase 100 /* due to quotes more as 75% */
124 #define CharTopToBtm 120 /* line height larger as text angle */
125 // for Avanti-Bold 'ue' actually even 130%
127 // end of AbsBase.Pas
129 // Start of DefBase.Pas
131 #define TextBoldBit 0x0001 /* bold */
132 #define TextRSlnBit 0x0002 /* italic */
133 #define TextUndlBit 0x0004 /* underline */
134 #define TextStrkBit 0x0008 /* strikethrough */
135 #define TextSupSBit 0x0010 /* superscript */
136 #define TextSubSBit 0x0020 /* subscript */
137 #define TextKaptBit 0x0040 /* capital */
138 #define TextLSlnBit 0x0080 /* left italic */
139 #define TextDbUnBit 0x0100 /* double underline */
140 #define TextDbStBit 0x0200 /* double strikethrough */
141 #define TextSh2DBit 0x0400 /* 2D-shadow 2.0 */
142 #define TextSh3DBit 0x0800 /* 3D-shadow 2.0 */
143 #define TextSh4DBit 0x1000 /* 4D-shadow 2.0 */
144 #define TextShEbBit 0x2000 /* embossed-shadow 2.0 */
146 #define THJustLeft 0x00
147 #define THJustCenter 0x01
148 #define THJustRight 0x02
149 #define THJustBlock 0x03
150 #define THJustDrvOut 0x04 /* Justified formatted */
151 #define THJustLocked 0x05 /* J u s t l o c k e d */
153 #define MaxCharSlant 4200 /* maximum 42deg italic ! */
155 // end of DefBase.Pas
157 bool CheckTextOutl(ObjAreaType& F, ObjLineType& L)
159 return (F.FIntens!=L.LIntens) ||
160 ((F.FFarbe!=L.LFarbe) && (F.FIntens>0)) ||
161 ((F.FBFarbe!=L.LBFarbe) && (F.FIntens<100));
164 // Start of Misc.Pas
166 short hPoint2Sgf(short a)
168 long b;
169 b=long(a)*127*SgfDpmm/(144*5);
170 return short(b);
173 // End of Misc.Pas
175 // Start of AbsRead.Pas
177 // Function GetTopToBaseLine() Function GetBaseLineToBtm()
179 // Calculate distance from ascender of line to baseline or from baseline to
180 // descender. All in SGF-units.
182 sal_uInt16 GetTopToBaseLine(sal_uInt16 MaxGrad)
184 long ret;
185 ret=long(MaxGrad)*long(CharTopToBase) /long(100);
186 return sal_uInt16(ret);
189 // Function GetTextChar() Function GetTextCharConv()
191 // Reads a character from textbuffer, in doing so escape sequences
192 // are evaluated and accordingly the input/output parameter AktAtr is set.
193 // Index is incremented accordingly.
194 // Parameter Rest should always contain the number of characters,
195 // the number of remaining characters in that line.
196 // Otherwise the hyphenation does not work. If the constant NoTrenn
197 // is used instead, no hyphenation is done. To the contrary then
198 // constant DoTrenn triggers hyphenation where a soft-break is present.
200 // Soft separators are converted to a minus sign.
201 // On top GetTextCharConv() converts HardSpace and AbsatzEnde
202 // in spaces, including HardTrenner in minus signs. TextEnde is
203 // always returned as Char(0).
205 UCHAR ConvertTextChar(UCHAR c)
207 if (c<32) {
208 switch (c) {
209 case HardSpace : c=' '; break;
210 case AbsatzEnd : c=' '; break;
211 case SoftTrenn : c='-'; break;
212 case HardTrenn : c='-'; break;
213 case SoftTrennK : c='-'; break;
214 case SoftTrennAdd: c='-';
217 return c;
220 long ChgValue(long Def, long Min, long Max, UCHAR FlgVal, long NumVal)
222 long r=0;
224 if (FlgVal==EscDeflt) {
225 r=Def; // return to default
226 } else {
227 if (NumVal!=EscNoVal) r=NumVal; // set non-breaking
230 if (Min!=0 || Max!=0) {
231 if (r>Max) r=Max;
232 if (r<Min) r=Min;
234 return r;
237 void ChgSchnittBit(sal_uInt16 Bit, sal_uInt16 Radio1, sal_uInt16 Radio2, sal_uInt16 Radio3,
238 UCHAR FlgVal, sal_uInt16 Schnitt0, sal_uInt16& Schnitt)
240 sal_uInt16 All,Rad;
242 Rad=Radio1 | Radio2 | Radio3;
243 All=Bit | Rad;
245 switch (FlgVal) {
246 case EscSet : Schnitt=(Schnitt & ~All) | Bit; break;
247 case EscReset: Schnitt=(Schnitt & ~All); break;
248 case EscDeflt: Schnitt=(Schnitt & ~All) | (Schnitt0 & All); break;
249 case EscToggl: Schnitt=(Schnitt & ~Rad) ^ Bit;
253 UCHAR GetNextChar(UCHAR* TBuf, sal_uInt16 Index)
255 sal_uInt16 Cnt;
256 while (TBuf[Index]==Escape) {
257 Index++;
258 Cnt=0;
259 while (TBuf[Index]!=Escape && Cnt<=MaxEscLen) {
260 Index++; Cnt++; }
261 Index++;
263 return TBuf[Index];
266 UCHAR ProcessOne(UCHAR* TBuf, sal_uInt16& Index,
267 ObjTextType& Atr0, ObjTextType& AktAtr,
268 bool ScanEsc)
270 UCHAR c;
271 UCHAR Ident;
272 bool Ende;
273 bool q;
274 UCHAR FlgVal;
275 long NumVal;
276 long Sgn;
277 short i;
278 bool EoVal;
280 do {
281 c=TBuf[Index]; Index++;
282 Ende=(c!=Escape);
283 if (!Ende) {
284 c=TBuf[Index]; Index++;
285 Ident=c; // remember identifier
286 FlgVal=EscNoFlg;
287 NumVal=EscNoVal;
288 c=TBuf[Index]; Index++; // value starts here
289 if (c==EscSet || c==EscReset || c==EscDeflt || c==EscToggl) FlgVal=c; else {
290 if (c=='-') Sgn=-1; else Sgn=1;
291 if (c=='+' || c=='-') { c=TBuf[Index]; Index++; }
292 i=MaxEscValLen;
293 NumVal=0;
294 do {
295 NumVal=10*NumVal+c-'0';
296 EoVal=(TBuf[Index]<'0' || TBuf[Index]>'9');
297 if (!EoVal) { c=TBuf[Index]; Index++; }
298 i--;
299 } while (i>0 && !EoVal);
300 NumVal=Sgn*NumVal;
302 q=!CheckTextOutl(AktAtr.F,AktAtr.L);
304 switch (Ident) {
305 case EscFont : AktAtr.SetFont(sal_uLong (ChgValue(Atr0.GetFont(),0,0 ,FlgVal,NumVal)));break;
306 case EscGrad : AktAtr.Grad =sal_uInt16(ChgValue(Atr0.Grad, 2,2000 ,FlgVal,NumVal)); break;
307 case EscBreit: AktAtr.Breite =sal_uInt16(ChgValue(Atr0.Breite, 1,1000 ,FlgVal,NumVal)); break;
308 case EscKaptS: AktAtr.Kapit =(sal_uInt8)(ChgValue(Atr0.Kapit, 1,255 ,FlgVal,NumVal)); break;
309 case EscLFeed: AktAtr.LnFeed =sal_uInt16(ChgValue(Atr0.LnFeed, 1,65535 ,FlgVal,NumVal)); break;
310 case EscSlant: AktAtr.Slant =sal_uInt16(ChgValue(Atr0.Slant, 1,MaxCharSlant ,FlgVal,NumVal)); break;
311 case EscVPos : AktAtr.ChrVPos=char (ChgValue(Atr0.ChrVPos,-128,127 ,FlgVal,NumVal)); break;
312 case EscZAbst: AktAtr.ZAbst =(sal_uInt8)(ChgValue(Atr0.ZAbst, 1,255 ,FlgVal,NumVal)); break;
313 case EscHJust: AktAtr.Justify=(sal_uInt8)(ChgValue(Atr0.Justify & 0x0F,0,5 ,FlgVal,NumVal)); break;
314 case EscFarbe: { AktAtr.L.LFarbe =(sal_uInt8)(ChgValue(Atr0.L.LFarbe,0,7 ,FlgVal,NumVal)); if (q) AktAtr.F.FFarbe =AktAtr.L.LFarbe; } break;
315 case EscBFarb: { AktAtr.L.LBFarbe=(sal_uInt8)(ChgValue(Atr0.L.LBFarbe,0,255,FlgVal,NumVal)); if (q) AktAtr.F.FBFarbe=AktAtr.L.LBFarbe; } break;
316 case EscInts : { AktAtr.L.LIntens=(sal_uInt8)(ChgValue(Atr0.L.LIntens,0,100,FlgVal,NumVal)); if (q) AktAtr.F.FIntens=AktAtr.L.LIntens; } break;
318 case EscMustr: { AktAtr.F.FMuster=sal_uInt16(ChgValue(Atr0.F.FMuster,0,65535,FlgVal,NumVal)); } break;
319 case EscMFarb: { AktAtr.F.FFarbe =(sal_uInt8)(ChgValue(Atr0.F.FFarbe,0,7 ,FlgVal,NumVal)); } break;
320 case EscMBFrb: { AktAtr.F.FBFarbe=(sal_uInt8)(ChgValue(Atr0.F.FBFarbe,0,255,FlgVal,NumVal)); } break;
321 case EscMInts: { AktAtr.F.FIntens=(sal_uInt8)(ChgValue(Atr0.F.FIntens,0,100,FlgVal,NumVal)); } break;
323 case EscSMstr: { AktAtr.ShdF.FMuster=sal_uInt16(ChgValue(Atr0.ShdF.FMuster,0,65535,FlgVal,NumVal)); } break;
324 case EscSFarb: { AktAtr.ShdL.LFarbe =(sal_uInt8)(ChgValue(Atr0.ShdL.LFarbe,0,7 ,FlgVal,NumVal)); AktAtr.ShdF.FFarbe =AktAtr.ShdL.LFarbe; } break;
325 case EscSBFrb: { AktAtr.ShdL.LBFarbe=(sal_uInt8)(ChgValue(Atr0.ShdL.LBFarbe,0,255,FlgVal,NumVal)); AktAtr.ShdF.FBFarbe=AktAtr.ShdL.LBFarbe; } break;
326 case EscSInts: { AktAtr.ShdL.LIntens=(sal_uInt8)(ChgValue(Atr0.ShdL.LIntens,0,100,FlgVal,NumVal)); AktAtr.ShdF.FIntens=AktAtr.ShdL.LIntens; } break;
327 case EscSDist: { AktAtr.ShdVers.x=(short)ChgValue(Atr0.ShdVers.x,0,30000,FlgVal,NumVal); AktAtr.ShdVers.y=AktAtr.ShdVers.x; } break;
328 case EscSXDst: { AktAtr.ShdVers.x=(short)ChgValue(Atr0.ShdVers.x,0,30000,FlgVal,NumVal); } break;
329 case EscSYDst: { AktAtr.ShdVers.y=(short)ChgValue(Atr0.ShdVers.y,0,30000,FlgVal,NumVal); } break;
331 case EscBold : ChgSchnittBit(TextBoldBit,0,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
332 case EscRSlnt: ChgSchnittBit(TextRSlnBit,TextLSlnBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
333 case EscUndln: ChgSchnittBit(TextUndlBit,TextDbUnBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
334 case EscStrik: ChgSchnittBit(TextStrkBit,TextDbStBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
335 case EscDbUnd: ChgSchnittBit(TextDbUnBit,TextUndlBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
336 case EscDbStk: ChgSchnittBit(TextDbStBit,TextStrkBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
337 case EscSupSc: ChgSchnittBit(TextSupSBit,TextSubSBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
338 case EscSubSc: ChgSchnittBit(TextSubSBit,TextSupSBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
339 case EscKaptF: ChgSchnittBit(TextKaptBit,0,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
340 case EscLSlnt: ChgSchnittBit(TextLSlnBit,TextRSlnBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
341 case Esc2DShd: ChgSchnittBit(TextSh2DBit,TextSh3DBit,TextSh4DBit,TextShEbBit,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
342 case Esc3DShd: ChgSchnittBit(TextSh3DBit,TextSh2DBit,TextSh4DBit,TextShEbBit,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
343 case Esc4DShd: ChgSchnittBit(TextSh4DBit,TextSh2DBit,TextSh3DBit,TextShEbBit,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
344 case EscEbShd: ChgSchnittBit(TextShEbBit,TextSh2DBit,TextSh3DBit,TextSh4DBit,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
345 } //endcase
346 if (TBuf[Index]==Escape) Index++; // read 2nd escape }
348 } while (!Ende && !ScanEsc);
349 if (!Ende) c=Escape;
350 return c;
351 } // end of ProcessOne
353 UCHAR GetTextChar(UCHAR* TBuf, sal_uInt16& Index,
354 ObjTextType& Atr0, ObjTextType& AktAtr,
355 sal_uInt16 Rest, bool ScanEsc)
357 UCHAR c=ProcessOne(TBuf,Index,Atr0,AktAtr,ScanEsc);
358 if (!ScanEsc) {
359 if (c==SoftTrennAdd || c==SoftTrennK || c==SoftTrenn) {
360 UCHAR nc=GetNextChar(TBuf,Index);
361 UCHAR c0=c;
362 if (Rest==0 || Rest==DoTrenn ||
363 nc==' ' || nc==AbsatzEnd || nc==TextEnd) c='-';
364 else {
365 c=ProcessOne(TBuf,Index,Atr0,AktAtr,ScanEsc); // skip separator
366 if (c0==SoftTrennAdd) {
367 if (c>=32) c=ProcessOne(TBuf,Index,Atr0,AktAtr,ScanEsc); // skip another letter
371 if ((Rest==1 || Rest==DoTrenn) && GetNextChar(TBuf,Index)==SoftTrennK) {
372 if (c=='c') c='k';
373 else if (c=='C') c='K';
376 return c;
379 // HardSpace and HardTrenn should be converted explicitely ! }
380 // if AktAtr.Schnitt and TextKaptBit =TextKaptBit then c:=UpCase(c);(explizit) }
382 // The separationmethod SoftTrennAdd assumes, the separating consonant }
383 // is 3x present in TextBuf, e.g.: "schiff-fahrt". }
384 // If not separated then, "-f" is removed. }
386 UCHAR GetTextCharConv(UCHAR* TBuf, sal_uInt16& Index,
387 ObjTextType& Atr0, ObjTextType& AktAtr,
388 sal_uInt16 Rest, bool ScanEsc)
390 UCHAR c;
392 c=GetTextChar(TBuf,Index,Atr0,AktAtr,Rest,ScanEsc);
393 if (c<32) {
394 switch (c) {
395 case HardSpace : c=' '; break;
396 case AbsatzEnd : c=' '; break;
397 case HardTrenn : c='-';
400 return c;
403 // Function GetLineFeed()
405 // Required line spacing in SGF-Units. ChrVPos is taken into account.
406 // ======================================================================
407 sal_uInt16 GetLineFeed(UCHAR* TBuf, sal_uInt16 Index, ObjTextType Atr0, ObjTextType AktAtr,
408 sal_uInt16 nChar, sal_uInt16& LF, sal_uInt16& MaxGrad)
410 bool AbsEnd=false;
411 sal_uLong LF100=0;
412 sal_uLong MaxLF100=0;
413 bool LFauto=false;
414 bool First=true;
415 sal_uInt16 Grad;
416 sal_uInt16 i=0;
417 sal_uInt16 r=1;
419 MaxGrad=0;
420 while (!AbsEnd && nChar>0) {
421 nChar--;
422 UCHAR c=GetTextChar(TBuf,Index,Atr0,AktAtr,nChar,false);
423 i++;
424 AbsEnd=(c==TextEnd || c==AbsatzEnd);
425 if (First || (!AbsEnd && c!=' ' && c!=HardTrenn)) {
426 LFauto=(AktAtr.LnFeed & 0x8000)==0;
427 LF100=AktAtr.LnFeed & 0x7FFF;
428 if (LFauto) LF100=LF100*AktAtr.Grad; else LF100*=LF100;
429 if (AktAtr.ChrVPos>0) LF100-=AktAtr.ChrVPos*100;
430 if (LF100>MaxLF100) MaxLF100=LF100;
431 Grad=AktAtr.Grad;
432 if (AktAtr.ChrVPos>0) Grad=Grad-AktAtr.ChrVPos;
433 if (Grad>MaxGrad) MaxGrad=Grad;
434 First=false;
436 if (!AbsEnd && c!=' ') r=i;
438 MaxGrad=hPoint2Sgf(MaxGrad);
439 if (MaxLF100<=4000) { // otherwise overflow could occur
440 LF=sal_uInt16(hPoint2Sgf(short(MaxLF100)) /100);
441 } else {
442 LF=sal_uInt16(hPoint2Sgf(short(MaxLF100) /100));
445 return r;
448 // End of AbsRead.Pas
450 // Start of iFont.Pas
452 #define SuperSubFact 60 /* superscript/subscript: 60% of text angle */
453 #define DefaultSpace 40 /* Default: space is 40% of text angle */
455 sal_uInt16 SetTextContext(OutputDevice& rOut, ObjTextType& Atr, bool Kapt, sal_uInt16 nRotation,
456 sal_uInt16 FitXMul, sal_uInt16 FitXDiv, sal_uInt16 FitYMul, sal_uInt16 FitYDiv)
458 SgfFontOne* pSgfFont; // Font from the IniFile
459 vcl::Font aFont;
460 Color aColor;
461 sal_uLong Grad;
462 sal_uLong Brei;
463 OUString FNam;
464 sal_uInt16 StdBrei=50; // average line width in % of text angle
465 bool bFit=(FitXMul!=1 || FitXDiv!=1 || FitYMul!=1 || FitYDiv!=1);
467 pSgfFont = pSgfFonts->GetFontDesc(Atr.GetFont());
469 if ( pSgfFont!=nullptr )
471 FNam =pSgfFont->SVFName;
472 StdBrei=pSgfFont->SVWidth;
473 if (pSgfFont->Fixd) aFont.SetPitch(PITCH_FIXED); else aFont.SetPitch(PITCH_VARIABLE);
474 aFont.SetFamily(pSgfFont->SVFamil);
475 aFont.SetCharSet(pSgfFont->SVChSet);
476 aFont.SetFamilyName(FNam);
478 else
479 { // if not in Inifile, some fonts are hard coded here
480 aFont.SetPitch(PITCH_VARIABLE);
481 switch (Atr.GetFont()) {
482 case 92500: case 92501: case 92504: case 92505:
484 #if defined(_WIN32)
485 FNam = "Times New Roman"; // CG Times is Times New Roman in Windows
486 #else
487 FNam = "Times"; // otherwise just Times
488 #endif
489 StdBrei=40;
490 aFont.SetFamily(FAMILY_ROMAN);
491 } break;
492 case 94021: case 94022: case 94023: case 94024: {
493 #if defined(_WIN32)
494 FNam = "Arial"; // Univers is Arial in Windows
495 #else
496 FNam = "Helvetica"; // otherwise Helvetica
497 #endif
498 aFont.SetFamily(FAMILY_SWISS);
499 StdBrei=47;
500 } break;
501 case 93950: case 93951: case 93952: case 93953: {
502 #if defined(_WIN32)
503 FNam = "Courier New"; // The vector-Courierfont is called Courier New in Windows
504 #else
505 FNam = "Courier"; // otherwise Courier remains Courier
506 #endif
507 aFont.SetFamily(FAMILY_ROMAN);
508 aFont.SetPitch(PITCH_FIXED);
509 } break;
510 default: FNam = "Helvetica";
512 aFont.SetFamilyName(FNam);
513 //aFont.SetCharSet(CHARSET_SYSTEM);
516 Grad=sal_uLong(Atr.Grad);
517 if ((Atr.Schnitt & TextKaptBit) !=0 && Kapt) Grad=Grad*sal_uLong(Atr.Kapit)/100;
518 if ((Atr.Schnitt & TextSupSBit) !=0 || (Atr.Schnitt & TextSubSBit) !=0) Grad=Grad*SuperSubFact/100;
519 Brei=Grad;
520 if (Atr.Breite!=100 || bFit) {
521 if (bFit) {
522 Grad=Grad*sal_uLong(FitYMul)/sal_uLong(FitYDiv);
523 Brei=Brei*sal_uLong(FitXMul)/sal_uLong(FitXDiv);
525 Brei=Brei*sal_uLong(Atr.Breite)/100;
526 Brei=Brei*sal_uLong(StdBrei)/100;
527 aFont.SetFontSize(Size(hPoint2Sgf(sal_uInt16(Brei)),hPoint2Sgf(sal_uInt16(Grad))));
528 } else {
529 aFont.SetFontSize(Size(0,hPoint2Sgf(sal_uInt16(Grad))));
532 aColor=Sgv2SvFarbe(Atr.L.LFarbe,Atr.L.LBFarbe,Atr.L.LIntens); aFont.SetColor(aColor);
533 aColor=Sgv2SvFarbe(Atr.F.FFarbe,Atr.F.FBFarbe,Atr.F.FIntens); aFont.SetFillColor(aColor);
534 aFont.SetTransparent(true);
535 aFont.SetAlignment(ALIGN_BASELINE);
537 nRotation/=10; nRotation=3600-nRotation; if (nRotation==3600) nRotation=0;
538 aFont.SetOrientation(nRotation);
540 if ((Atr.Schnitt & TextBoldBit) !=0) aFont.SetWeight(WEIGHT_BOLD);
541 if ((Atr.Schnitt & TextRSlnBit) !=0) aFont.SetItalic(ITALIC_NORMAL);
542 if ((Atr.Schnitt & TextUndlBit) !=0) aFont.SetUnderline(LINESTYLE_SINGLE);
543 if ((Atr.Schnitt & TextDbUnBit) !=0) aFont.SetUnderline(LINESTYLE_DOUBLE);
544 if ((Atr.Schnitt & TextStrkBit) !=0) aFont.SetStrikeout(STRIKEOUT_SINGLE);
545 if ((Atr.Schnitt & TextDbStBit) !=0) aFont.SetStrikeout(STRIKEOUT_DOUBLE);
546 if ((Atr.Schnitt & TextSh2DBit) !=0) aFont.SetShadow(true);
547 if ((Atr.Schnitt & TextSh3DBit) !=0) aFont.SetShadow(true);
548 if ((Atr.Schnitt & TextSh4DBit) !=0) aFont.SetShadow(true);
549 if ((Atr.Schnitt & TextShEbBit) !=0) aFont.SetShadow(true);
550 if (CheckTextOutl(Atr.F,Atr.L)) aFont.SetOutline(true);
552 if (aFont!=rOut.GetFont()) rOut.SetFont(aFont);
554 return 0;
557 // iFont.Pas
559 // Start of Absatz.Pas
561 struct ProcChrSta {
562 sal_uInt16 Index;
563 sal_uInt16 ChrXP;
564 UCHAR OutCh;
565 bool Kapt;
566 ObjTextType Attrib;
569 void InitProcessCharState(ProcChrSta& State, ObjTextType& AktAtr, sal_uInt16 IndexA)
571 State.Attrib=AktAtr;
572 State.OutCh=0;
573 State.Index=IndexA;
574 State.ChrXP=0;
575 State.Kapt=false;
578 bool UpcasePossible(UCHAR c)
580 return ((c>='a' && c<='z') || c == 0xe4 || c == 0xf6 || c == 0xfc );
583 UCHAR Upcase(UCHAR c)
585 if ((c>=(UCHAR)'a' && c<=(UCHAR)'z')) c=(c-(UCHAR)'a')+(UCHAR)'A';
586 else if ( c == 0xe4 ) c = 0xc4;
587 else if ( c == 0xf6 ) c = 0xd6;
588 else if ( c == 0xfc ) c = 0xdc;
589 return c;
592 sal_uInt16 GetCharWidth(OutputDevice& rOut, UCHAR c)
594 sal_uInt16 ChrWidth;
596 if (c==' ')
598 ChrWidth=(sal_uInt16)rOut.GetTextWidth( OUString('A') );
599 if (rOut.GetFont().GetPitch()!=PITCH_FIXED) {
600 ChrWidth=MulDiv(ChrWidth,DefaultSpace,100);
603 else
605 static_assert(MaxChar == 255, "with MaxChar == 255 c cannot be greater than MaxChar");
606 static_assert(sizeof(UCHAR) == 1, "assert if MaxChar type is ever changed");
607 if (c>=MinChar /*&& c<=MaxChar*/)
609 ChrWidth=(sal_uInt16)rOut.GetTextWidth(OUString(reinterpret_cast<sal_Char*>(&c), 1, RTL_TEXTENCODING_IBM_437));
611 else
613 ChrWidth=(sal_uInt16)rOut.GetTextWidth(OUString(static_cast<sal_Unicode>('A')));
616 return ChrWidth;
619 UCHAR ProcessChar(OutputDevice& rOut, UCHAR* TBuf, ProcChrSta& R, ObjTextType& Atr0,
620 sal_uInt16& nChars, sal_uInt16 Rest,
621 short* Line, UCHAR* cLine)
623 sal_uInt16 KernDist=0; // value for kerning
624 sal_uInt16 ChrWidth;
625 UCHAR c;
626 bool AbsEnd;
628 c=GetTextChar(TBuf,R.Index,Atr0,R.Attrib,Rest,false); // tries to separate, if Rest contains appropriate value
630 AbsEnd=(c==AbsatzEnd || c==TextEnd);
631 if (!AbsEnd) {
632 R.OutCh=ConvertTextChar(c); // from HardTrenn to '-', ...
633 R.Kapt=(R.Attrib.Schnitt & TextKaptBit) !=0 && UpcasePossible(R.OutCh);
634 if (R.Kapt) R.OutCh=Upcase(R.OutCh);
635 SetTextContext(rOut,R.Attrib,R.Kapt,0,1,1,1,1);
637 UCHAR c1 = (R.Kapt)?Upcase(c):c;
638 ChrWidth=GetCharWidth(rOut,c1);
640 if (R.Attrib.ZAbst!=100) { // special line distance ?
641 sal_uLong Temp;
642 Temp=sal_uLong(ChrWidth)*sal_uLong(R.Attrib.ZAbst)/100;
643 ChrWidth=sal_uInt16(Temp);
645 nChars++;
646 if (R.ChrXP>32000) R.ChrXP=32000;
647 Line[nChars]=R.ChrXP-KernDist;
648 cLine[nChars]=c;
649 R.ChrXP+=ChrWidth-KernDist; // position of next character
651 return c;
654 void FormatLine(UCHAR* TBuf, sal_uInt16& Index, ObjTextType& Atr0, ObjTextType& AktAtr,
655 sal_uInt16 UmbWdt, sal_uInt16 AdjWdt,
656 short* Line, sal_uInt16& nChars,
657 double, double,
658 UCHAR* cLine, bool TextFit)
660 ScopedVclPtrInstance< VirtualDevice > vOut;
661 UCHAR c,c0;
662 bool First; // first char ?
663 sal_uInt8 Just = 0; // paragraph format
664 bool Border; // border of box reached ?
665 bool Border0;
666 bool AbsEnd; // end of paragraph reached ?
667 std::unique_ptr<ProcChrSta> R(new ProcChrSta);
668 std::unique_ptr<ProcChrSta> R0(new ProcChrSta);
669 std::unique_ptr<ProcChrSta> WErec(new ProcChrSta);
670 sal_uInt16 WEnChar;
671 std::unique_ptr<ProcChrSta> WErec0(new ProcChrSta);
672 sal_uInt16 WEnChar0;
673 std::unique_ptr<ProcChrSta> TRrec(new ProcChrSta);
674 sal_uInt16 TRnChar;
676 sal_uInt16 WordEndCnt; // justify and separate
677 bool WordEnd;
678 bool Trenn;
680 short BoxRest; // to crush and format
681 sal_uInt16 i,j,k,h;
682 sal_uInt16 re,li;
684 vOut->SetMapMode(MapMode(MapUnit::Map10thMM,Point(),Fraction(1,4),Fraction(1,4)));
686 nChars=0;
687 SetTextContext(*vOut.get(),AktAtr,false,0,1,1,1,1);
688 InitProcessCharState(*R,AktAtr,Index);
689 (*R0)=(*R); (*WErec)=(*R); WEnChar=0; c0=0; Border0=false;
690 Border=false; First=true;
691 WordEndCnt=0;
693 do { // check how many words to on that line
694 if (Border) c=ProcessChar(*vOut.get(),TBuf,*R,Atr0,nChars,DoTrenn,Line,cLine);
695 else c=ProcessChar(*vOut.get(),TBuf,*R,Atr0,nChars,NoTrenn,Line,cLine);
696 AbsEnd=(c==AbsatzEnd || c==TextEnd);
697 //if not AbsEnd then
699 if (First) {
700 Just=R->Attrib.Justify & 0x0F; // paragraph format remains, then at start
702 Border=R->ChrXP>UmbWdt;
703 WordEnd=(AbsEnd || (c==' ')) && (c0!=' ') && (c0!=0);
704 Trenn=c=='-';
705 if (WordEnd && !Border0) {
706 WordEndCnt++;
707 (*WErec)=(*R0);
708 WEnChar=nChars-1;
710 if (Trenn && !Border) {
711 WordEndCnt++;
712 (*WErec)=(*R);
713 WEnChar=nChars;
716 (*R0)=(*R); c0=c;
717 Border0=Border;
718 First=false;
719 AbsEnd=AbsEnd || (nChars>=MaxLineChars);
720 } while (!(AbsEnd || (Border && ((WordEndCnt>0) || WordEnd || Trenn))));
722 if (Border) { // separate and crush
723 (*WErec0)=(*WErec); WEnChar0=WEnChar;
724 c0=0;
725 (*R)=(*WErec); nChars=WEnChar;
726 (*TRrec)=(*R); TRnChar=nChars;
727 Border0=false;
728 do { // first check how many syllables fit
729 UCHAR ct=ProcessChar(*vOut.get(),TBuf,*TRrec,Atr0,TRnChar,DoTrenn,Line,cLine);
730 c=ProcessChar(*vOut.get(),TBuf,*R,Atr0,nChars,NoTrenn,Line,cLine);
731 AbsEnd=(ct==AbsatzEnd) || (ct==TextEnd) || (nChars>=MaxLineChars);
733 Border=TRrec->ChrXP>UmbWdt;
734 WordEnd=AbsEnd || ((AbsEnd || (c==' ')) && (c0!=' ') && (c0!=0));
735 Trenn=ct=='-';
736 if (WordEnd && (!Border0 || (WordEndCnt==0))) {
737 WordEndCnt++;
738 (*WErec)=(*R0);
739 if (AbsEnd) WEnChar=nChars; else WEnChar=nChars-1;
740 (*TRrec)=(*R); TRnChar=nChars; // to continue searching
742 if (Trenn && (!Border || (WordEndCnt==0))) {
743 WordEndCnt++; // remember we can separate here
744 (*WErec)=(*TRrec);
745 WEnChar=TRnChar;
746 (*TRrec)=(*R); TRnChar=nChars; // continue searching
748 (*R0)=(*R); c0=c;
749 Border0=Border;
750 Border=R->ChrXP>UmbWdt;
751 } while (!(AbsEnd || (Border && ((WordEndCnt>0) || WordEnd || Trenn))));
753 while (WErec0->Index<WErec->Index) { // to assure Line[] matches }
754 (void)ProcessChar(*vOut.get(),TBuf,*WErec0,Atr0,WEnChar0,WEnChar-WEnChar0-1,Line,cLine);
757 (*R)=(*WErec); nChars=WEnChar;
759 if (UmbWdt<R->ChrXP) {
760 BoxRest=R->ChrXP-UmbWdt; // so much should be crushed
761 for (i=2;i<=nChars;i++) { // first character position remains!
762 Line[i]-=(i-1)*(BoxRest) /(nChars-1);
764 R->ChrXP=UmbWdt;
765 Line[nChars+1]=UmbWdt;
769 if (!AbsEnd) {
770 do { // read empty characters
771 (*WErec)=(*R);
772 c=GetTextChar(TBuf,R->Index,Atr0,R->Attrib,NoTrenn,false);
773 nChars++;
774 Line[nChars]=R->ChrXP;
775 cLine[nChars]=c;
776 } while (c==' ');
777 if (c!=' ' && c!=AbsatzEnd && c!=TextEnd) {
778 nChars--;
779 (*R)=(*WErec);
783 if (AbsEnd && nChars<MaxLineChars) { // align, left aligned instead of block
784 if (Just==3) Just=0;
785 nChars++; Line[nChars]=R->ChrXP; // to assure AbsatzEnde is read
786 Line[nChars+1]=R->ChrXP; // as the width of CR or #0 is very small
787 if (TBuf[R->Index-1]!=AbsatzEnd && TBuf[R->Index-1]!=TextEnd) {
788 GetTextChar(TBuf,R->Index,Atr0,R->Attrib,NoTrenn,false); // small correction needed, if 1st word read
792 BoxRest=AdjWdt-R->ChrXP;
793 if (TextFit) Just=THJustLeft;
795 switch (Just) {
796 case THJustLeft: break; // left
797 case THJustCenter: {
798 BoxRest=BoxRest /2; // middle
799 for (i=1;i<=nChars;i++) Line[i]=Line[i]+BoxRest;
800 } break;
801 case THJustRight: { // right
802 for (i=1;i<=nChars;i++) Line[i]=Line[i]+BoxRest;
803 } break;
804 case THJustDrvOut:
805 case THJustBlock: { // block and justified
806 re=nChars;
807 if (Just==THJustDrvOut) re--;
808 while (re>=1 && (cLine[re]==' ' || cLine[re]==TextEnd || cLine[re]==AbsatzEnd)) re--;
809 li=1;
810 while (li<=re && (cLine[li]==' ' || cLine[li]==TextEnd || cLine[li]==AbsatzEnd)) li++;
811 if (Just==THJustDrvOut) BoxRest=AdjWdt-Line[re+1];
813 j=0; // get number of spaces
814 for (i=li;i<=re;i++) {
815 if (cLine[i]==' ') {
816 j++;
820 if (j==0) { // only one word ? -> stretch !
821 for (i=li+1;i<=re;i++) { // from left to right
822 Line[i]=Line[i]+MulDiv(i-li,BoxRest,re-li+1-1);
824 } else {
825 k=0; h=0;
826 for (i=li;i<=re;i++) { // j drill spaces !
827 if (cLine[i]==' ') { // space found !
828 k++;
829 h=MulDiv(k,BoxRest,j);
831 Line[i]=Line[i]+h;
834 for (i=re+1;i<=nChars;i++) Line[i]=Line[i]+BoxRest; // adapt the rest
835 Line[nChars+1]=AdjWdt;
836 } break;
837 case THJustLocked: { // locked out
838 re=nChars-1;
839 while (re>=1 && (cLine[re]==' ' || cLine[re]==TextEnd || cLine[re]==AbsatzEnd)) re--;
840 li=1;
841 while (li<=re && (cLine[li]==' ' || cLine[li]==TextEnd || cLine[li]==AbsatzEnd)) li++;
842 BoxRest=AdjWdt-Line[re+1];
843 for (i=li+1;i<=re;i++) { // stretch from left to right
844 Line[i]=Line[i]+MulDiv(i-li,BoxRest,re-li+1-1);
846 for (i=re+1;i<=nChars;i++) Line[i]=Line[i]+BoxRest; // adapt the rest
847 Line[nChars+1]=AdjWdt;
848 } break;
850 Index=R->Index;
851 AktAtr=R->Attrib;
854 // End of Absatz.Pas
856 // Start of DrawText.Pas
858 void DrawChar(OutputDevice& rOut, UCHAR c, ObjTextType T, PointType Pos, sal_uInt16 RotationAngle,
859 sal_uInt16 FitXMul, sal_uInt16 FitXDiv, sal_uInt16 FitYMul, sal_uInt16 FitYDiv)
861 SetTextContext(rOut,T,UpcasePossible(c),RotationAngle,FitXMul,FitXDiv,FitYMul,FitYDiv);
862 if ((T.Schnitt & TextKaptBit)!=0 && UpcasePossible(c)) c=Upcase(c);
863 OUString s(reinterpret_cast<const sal_Char*>(&c), 1,
864 RTL_TEXTENCODING_IBM_437);
865 rOut.DrawText( Point( Pos.x, Pos.y ), s );
868 void TextType::Draw(OutputDevice& rOut)
870 if ((Flags & TextOutlBit)!=0) return; // source text for Outliner !!
872 ObjTextType T1,T2;
873 sal_uInt16 Index1;
874 sal_uInt16 Index2;
875 UCHAR c = TextEnd;
876 sal_uInt16 l; // number of characters on the line
877 sal_uInt16 i;
878 short yPos0;
879 short xPos;
880 short yPos;
881 sal_uInt16 LF;
882 sal_uInt16 MaxGrad;
883 short xSize;
884 short xSAdj;
885 short ySize;
886 double sn,cs;
887 sal_uInt16 TopToBase;
888 bool Ende = false;
889 sal_uInt16 lc;
890 bool TextFit;
891 std::unique_ptr<short[]> xLine;
892 std::unique_ptr<UCHAR[]> cLine; // Buffer for FormatLine
893 sal_uInt16 FitXMul;
894 sal_uInt16 FitXDiv;
895 sal_uInt16 FitYMul;
896 sal_uInt16 FitYDiv;
897 bool Fehler;
898 UCHAR* Buf=Buffer; // pointer to the letters
900 pSgfFonts->ReadList();
901 xLine.reset(new short[ChrXPosArrSize]);
902 cLine.reset(new UCHAR[CharLineSize]);
904 TextFit=(Flags & TextFitBits)!=0;
905 bool LineFit=((Flags & TextFitZBit)!=0); // FitSize.x=0? or flags -> stretch each line
906 if (TextFit && FitSize.x==0) LineFit=true;
908 if (RotationAngle==0) {
909 sn=0.0;
910 cs=1.0;
911 } else {
912 sn=sin(double(RotationAngle)*3.14159265359/18000);
913 cs=cos(double(RotationAngle)*3.14159265359/18000);
916 T1=T; Index1=0; yPos=0; xPos=0;
917 if (TextFit) {
918 ySize=Pos2.y-Pos1.y;
919 xSize=32000 /2; // break
920 xSAdj=Pos2.x-Pos1.x; // to align for center/block
921 //if (xSize<=0) { xSize=32000 /2; LineFit=true; }
922 FitXMul=sal::static_int_cast< sal_uInt16 >(std::abs(Pos2.x-Pos1.x)); FitXDiv=FitSize.x; if (FitXDiv==0) FitXDiv=1;
923 FitYMul=sal::static_int_cast< sal_uInt16 >(std::abs(Pos2.y-Pos1.y)); FitYDiv=FitSize.y; if (FitYDiv==0) FitYDiv=1;
924 } else {
925 xSize=Pos2.x-Pos1.x;
926 xSAdj=xSize;
927 ySize=Pos2.y-Pos1.y;
928 FitXMul=1; FitXDiv=1;
929 FitYMul=1; FitYDiv=1;
931 if (xSize<0) xSize=0;
932 if (xSAdj<0) xSAdj=0;
934 do {
935 T2=T1; Index2=Index1;
936 FormatLine(Buf,Index2,T,T2,xSize,xSAdj,xLine.get(),l,sn,cs,cLine.get(),LineFit);
937 Fehler=(Index2==Index1);
938 if (!Fehler) {
939 lc=GetLineFeed(Buf,Index1,T,T1,l,LF,MaxGrad);
940 if (TextFit) {
941 if (LineFit) FitXDiv=xLine[lc+1];
942 if (FitXDiv>0) {
943 for (i=1;i<=l+1;i++) {
944 const long Temp=long(xLine[i])*long(FitXMul) /long(FitXDiv);
945 xLine[i]=short(Temp);
947 LF=MulDiv(LF,FitYMul,FitYDiv);
948 MaxGrad=MulDiv(MaxGrad,FitYMul,FitYDiv);
949 } else {
950 FitXDiv=1; // 0 does not exist
953 yPos0=yPos;
954 TopToBase=GetTopToBaseLine(MaxGrad);
955 yPos=yPos+TopToBase;
956 Ende=(yPos0+short(MulDiv(MaxGrad,CharTopToBtm,100))>ySize) && !TextFit;
957 if (!Ende) {
958 T2=T1; Index2=Index1;
959 i=1;
960 while (i<=l) {
961 c=GetTextCharConv(Buf,Index2,T,T2,l-i,false);
962 long xp1,yp1; // due to overflow danger
963 PointType Pos;
964 xp1=long(Pos1.x)+xPos+long(xLine[i]);
965 yp1=long(Pos1.y)+yPos;
966 if (xp1>32000) xp1=32000;
967 if (xp1<-12000) xp1=-12000;
968 if (yp1>32000) yp1=32000;
969 if (yp1<-12000) yp1=-12000;
970 Pos.x=short(xp1);
971 Pos.y=short(yp1);
973 if (RotationAngle!=0) RotatePoint(Pos,Pos1.x,Pos1.y,sn,cs);
974 DrawChar(rOut,c,T2,Pos,RotationAngle,FitXMul,FitXDiv,FitYMul,FitYDiv);
975 i++;
976 } // while i<=l
977 yPos=yPos0+LF;
978 T1=T2; Index1=Index2; // for next line
979 } // if ObjMin.y+yPos<=Obj_Max.y
980 } // if !Fehler
981 } while (c!=TextEnd && !Ende && !Fehler);
984 // End of DrawText.Pas
986 sal_uInt32 ObjTextType::GetFont()
988 return sal_uLong(FontLo)+0x00010000*sal_uLong(FontHi);
991 void ObjTextType::SetFont(sal_uInt32 FontID)
993 FontLo=sal_uInt16(FontID & 0x0000FFFF);
994 FontHi=sal_uInt16((FontID & 0xFFFF0000)>>16);
997 // SGF.Ini lesen
998 SgfFontOne::SgfFontOne()
1000 Next=nullptr;
1001 IFID=0;
1002 Bold=false;
1003 Ital=false;
1004 Sans=false;
1005 Serf=false;
1006 Fixd=false;
1007 SVFamil=FAMILY_DONTKNOW;
1008 SVChSet=RTL_TEXTENCODING_DONTKNOW;
1009 SVWidth=40;
1012 void SgfFontOne::ReadOne( const OString& rID, OString& Dsc )
1014 if ( Dsc.getLength() < 4 || ( Dsc[0] != '(' ) )
1015 return;
1016 sal_Int32 i=1; // first letter of IF fontname. In front is a '('
1017 while ( i < Dsc.getLength() && ( Dsc[i] !=')' ) )
1018 i++;
1019 Dsc = Dsc.copy(i+1); // delete IF fontname incl. ()
1021 if ( Dsc.getLength() < 2 || ( Dsc[Dsc.getLength() - 1] !=')' ) )
1022 return;
1023 i = Dsc.getLength()-2; // here is the ')' of the SV fontname
1024 sal_Int32 j=0;
1025 while ( i > 0 && ( Dsc[i] != '(' ) )
1027 i--;
1028 j++;
1030 SVFName = OStringToOUString(Dsc.copy(i+1,j), RTL_TEXTENCODING_IBM_437); // retrieve SV fontname
1031 Dsc = OStringBuffer(Dsc).remove(i,j).makeStringAndClear();
1033 IFID = (sal_uInt32)rID.toInt32();
1034 sal_Int32 nTokenCount = comphelper::string::getTokenCount(Dsc, ' ');
1035 for (sal_Int32 nIdx = 0; nIdx < nTokenCount; ++nIdx)
1037 OString s(Dsc.getToken(nIdx, ' '));
1038 if (!s.isEmpty())
1040 s = s.toAsciiUpperCase();
1041 if (s.match("BOLD")) Bold=true;
1042 else if (s.match("ITAL")) Ital=true;
1043 else if (s.match("SERF")) Serf=true;
1044 else if (s.match("SANS")) Sans=true;
1045 else if (s.match("FIXD")) Fixd=true;
1046 else if (s.match("ROMAN")) SVFamil=FAMILY_ROMAN;
1047 else if (s.match("SWISS")) SVFamil=FAMILY_SWISS;
1048 else if (s.match("MODERN")) SVFamil=FAMILY_MODERN;
1049 else if (s.match("SCRIPT")) SVFamil=FAMILY_SCRIPT;
1050 else if (s.match("DECORA")) SVFamil=FAMILY_DECORATIVE;
1051 else if (s.match("ANSI")) SVChSet=RTL_TEXTENCODING_MS_1252;
1052 else if (s.match("IBMPC")) SVChSet=RTL_TEXTENCODING_IBM_850;
1053 else if (s.match("MAC")) SVChSet=RTL_TEXTENCODING_APPLE_ROMAN;
1054 else if (s.match("SYMBOL")) SVChSet=RTL_TEXTENCODING_SYMBOL;
1055 else if (s.match("SYSTEM")) SVChSet = osl_getThreadTextEncoding();
1056 else if (comphelper::string::isdigitAsciiString(s) ) SVWidth=sal::static_int_cast< sal_uInt16 >(s.toInt32());
1061 SgfFontLst::SgfFontLst()
1063 pList=nullptr;
1064 Last=nullptr;
1065 LastID=0;
1066 LastLn=nullptr;
1067 Tried=false;
1070 SgfFontLst::~SgfFontLst()
1072 RausList();
1075 void SgfFontLst::RausList()
1077 SgfFontOne* P;
1078 SgfFontOne* P1;
1079 P=pList;
1080 while (P!=nullptr) {
1081 P1=P->Next;
1082 delete P;
1083 P=P1;
1085 pList=nullptr;
1086 Last=nullptr;
1087 Tried=false;
1088 LastID=0;
1089 LastLn=nullptr;
1092 void SgfFontLst::AssignFN(const OUString& rFName)
1093 { FNam=rFName; }
1095 void SgfFontLst::ReadList()
1097 if (!Tried)
1099 Tried=true;
1100 LastID=0;
1101 LastLn=nullptr;
1102 SgfFontOne* P,P1;
1103 Config aCfg(FNam);
1104 aCfg.SetGroup("SGV Fonts for StarView");
1105 sal_uInt16 Anz=aCfg.GetKeyCount();
1106 sal_uInt16 i;
1107 OString FID;
1108 OString Dsc;
1110 for (i=0;i<Anz;i++)
1112 FID = aCfg.GetKeyName(i).replaceAll(" ", "");
1113 Dsc = aCfg.ReadKey( i );
1114 if (comphelper::string::isdigitAsciiString(FID))
1116 P=new SgfFontOne; // new entry
1117 if (Last!=nullptr) Last->Next=P; else pList=P; Last=P; // link it
1118 P->ReadOne(FID,Dsc); // interpret line
1124 SgfFontOne* SgfFontLst::GetFontDesc(sal_uInt32 ID)
1126 if (ID!=LastID) {
1127 SgfFontOne* P;
1128 P=pList;
1129 while (P!=nullptr && P->IFID!=ID) P=P->Next;
1130 LastID=ID;
1131 LastLn=P;
1133 return LastLn;
1136 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */