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