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 :
21 : #include <rtl/math.h>
22 : #include <comphelper/string.hxx>
23 : #include <tools/config.hxx>
24 : #include <svtools/filter.hxx>
25 : #include "sgffilt.hxx"
26 : #include "sgfbram.hxx"
27 : #include "sgvmain.hxx"
28 :
29 : extern SgfFontLst* pSgfFonts;
30 :
31 : #ifndef abs
32 : #define abs(x) ((x)<0 ? -(x) : (x))
33 : #endif
34 :
35 :
36 : ////////////////////////////////////////////////////////////////////////////////////////////////////
37 : //
38 : // Einschraenkungen: Schatten nur grau, 2D und mit fixem Abstand.
39 : //
40 : //
41 : //
42 : //
43 : ////////////////////////////////////////////////////////////////////////////////////////////////////
44 :
45 : /////////////////////////////////////////////////////////////////////////////////
46 : /////////////////////////////////////////////////////////////////////////////////
47 : /////////////////////////////////////////////////////////////////////////////////
48 : // AbsBase.Pas
49 :
50 : // die folgenden Werte sind in % vom maximalen Schriftgrad der Zeile */
51 : #define UndlSpace 5 /* Untersteichungsabstand von der Baseline */
52 : #define UndlWidth 6 /* Untersteichungsdicke */
53 : #define UndlSpac2 7 /* Zwischenraum bei doppelter Unterstreichung */
54 : #define StrkSpace 25 /* Abstand der Durchstreichlinie von der Baseline*/
55 : #define StrkWidth 5 /* Durchstreichungsliniendicke */
56 : #define StrkSpac2 7 /* Zwischenraum bei doppelter Durchstreichung */
57 : #define OutlWidth 2 /* Strichstaerke ist 2% vom Schriftgrad */
58 :
59 : // vvv Sonderzeichen im TextBuffer vvv
60 : #define TextEnd 0 /* ^@ Ende der Zeichenkette */
61 : #define HardSpace 6 /* ^F Hartspace (wird nicht umbrochen) ,' ' */
62 : #define GrafText 7 /* ^G Im Text eingebundene Grafik (future) */
63 : #define Tabulator 9 /* ^I Tabulatorzeichen, Pfeil */
64 : #define LineFeed 10 /* ^J Neue Zeile */
65 : #define SoftTrennK 11 /* ^K Zeichen fuer k-c-Austausch bei Trennung, 'k' */
66 : #define AbsatzEnd 13 /* ^M Neuer Absatz =CR */
67 : #define HardTrenn 16 /* ^P Hartes Trennzeichen (wird nicht umbrochen), '-' */
68 : #define SoftTrennAdd 19 /* ^S Zusatz-Zeichen Trennung von z.b."Schiff-fahrt" */
69 : #define Paragraf 21 /* ^U Zeichen welches fuer Paragraf-Zeichen */
70 : #define Escape 27 /* ^[ Escapesequenz einleiten */
71 : #define SoftTrenn 31 /* ^_ Weiches Trennzeichen, '-' nur Zeilenende */
72 : #define MaxEscValLen 8
73 : #define MaxEscLen (MaxEscValLen+3)
74 :
75 : //==============================================================================
76 : // Escapesequenzen: [Esc]<Ident><Value>[Esc] also mind. 4 Char
77 : // Max. Laenge von Value soll sein: 8 Char (7+Vorzeichen). Demnach max. Laenge
78 : // einer Escapesequenz: 11 Char.
79 : // Identifer:
80 :
81 : #define EscFont 'F' /* FontID, z.B. 92500 fuer CG Times */
82 : #define EscGrad 'G' /* Schriftgrad 1..255 fuer <<Pt-127<<Pt */
83 : #define EscBreit 'B' /* Breite 1..255% des Schriftgrades */
84 : #define EscKaptS 'K' /* Kapitaelchengroesse 1..255% des Schriftgrades */
85 : #define EscLFeed 'L' /* Zeilenabstand 1..32767% vom max. Schriftgrad der Zeile */
86 : // oder 1..32767 fuer 1..16383<<Pt absolut (Wenn Bit 15=1)
87 : #define EscSlant 'S' /* Kursiv(Winkel) 1..8999 fuer 0.01deg..89.99deg */
88 : #define EscVPos 'V' /* Zeichen Vertikal-Position 1..255 fuer <<Pt..127<<Pt */
89 : #define EscZAbst 'Z' /* Zeichenabstand -128..127% */
90 : #define EscHJust 'A' /* H-Justify Absatz: Links, Zentr, Rechts, Block, Austreibend, Gesperrt (0..5)*/
91 :
92 : #define EscFarbe 'C' /* Farbe 0..7 */
93 : #define EscBFarb 'U' /* BackFarbe 0..7 */
94 : #define EscInts 'I' /* Farbintensitaet 0..100% */
95 : #define EscMustr 'M' /* Muster 0..? inkl. Transp... */
96 : #define EscMFarb 'O' /* Musterfarbe 0..7 */
97 : #define EscMBFrb 'P' /* 2. Musterfarbe 0..7 */
98 : #define EscMInts 'W' /* Musterintensitaet 0..7 */
99 :
100 : #define EscSMstr 'E' /* Schattenmuster 0..? inkl. Transp... */
101 : #define EscSFarb 'R' /* Schattenfarbe 0..7 */
102 : #define EscSBFrb 'T' /* 2. Schattenfarbe 0..7 */
103 : #define EscSInts 'Q' /* Schattenintensitaet 0..7 */
104 :
105 : #define EscSXDst 'X' /* Schattenversatz X 0..100% */
106 : #define EscSYDst 'Y' /* Schattenversatz Y 0..100% */
107 : #define EscSDist 'D' /* Schattenversatz X-Y 0..100% */
108 :
109 : #define EscBold 'f' /* Fett */
110 : #define EscLSlnt 'l' /* LKursiv */
111 : #define EscRSlnt 'r' /* RKursiv */
112 : #define EscUndln 'u' /* Unterstrichen */
113 : #define EscDbUnd 'p' /* doppelt Unterstrichen */
114 : #define EscKaptF 'k' /* Kapitaelchenflag */
115 : #define EscStrik 'd' /* Durchgestrichen */
116 : #define EscDbStk 'e' /* doppelt Durchgestrichen */
117 : #define EscSupSc 'h' /* Hochgestellt */
118 : #define EscSubSc 't' /* Tiefgestellt */
119 : #define Esc2DShd 's' /* 2D-Schatten */
120 : #define Esc3DShd 'j' /* 3D-Schatten */
121 : #define Esc4DShd 'i' /* 4D-Schatten */
122 : #define EscEbShd 'b' /* Embossed */
123 :
124 : // AllEscIdent =[EscFont, EscGrad, EscBreit,EscKaptS,EscLFeed,EscSlant,EscVPos, EscZAbst,EscHJust,
125 : // EscFarbe,EscBFarb,EscInts, EscMustr,EscMFarb,EscMBFrb,EscMInts,
126 : // EscSMstr,EscSFarb,EscSBFrb,EscSInts,EscSXDst,EscSYDst,EscSDist,
127 : // EscBold, EscLSlnt,EscRSlnt,EscUndln,EscDbUnd,EscKaptF,EscStrik,EscDbStk,
128 : // EscSupSc,EscSubSc,Esc2DShd,Esc3DShd,Esc4DShd];
129 : // Justify muss spaetestens am Anfang des Absatzes stehen
130 : #define EscSet '\x1e' /* Flag setzen */
131 : #define EscReset '\x1f' /* Flag loeschen */
132 : #define EscDeflt '\x11' /* Flag auf default setzen */
133 : #define EscToggl '\x1d' /* Flag Toggeln */
134 : #define EscNoFlg 0
135 : #define EscNoVal -2147483647 /* -MaxLongInt */
136 : //==============================================================================
137 : #define NoTrenn 0xFFFF /* Wert fuer Parameter 'Rest' von GetTextChar(), wenn auf keinen Fall getrennt werden soll */
138 : #define DoTrenn 0xFFFE /* Wert fuer Parameter 'Rest' von GetTextChar(), wenn getrennt werden soll */
139 :
140 : #define MaxLineChars 1024
141 :
142 : #define ChrXPosArrSize (MaxLineChars+1+1) /* 2k - Beginnt mit 0 im gegensatz zu StarDraw */
143 : #define CharLineSize (MaxLineChars+1+1)
144 :
145 : #define MinChar 32
146 : #define MaxChar 255
147 :
148 :
149 : //==============================================================================
150 :
151 : #define GradDiv 2
152 : #define CharTopToBase 100 /* wegen Apostrophe und Umlaute mehr als 75% */
153 : #define CharTopToBtm 120 /* Zeilenhoehe ist groesser als Schriftgrad */
154 : // bei Avanti-Bold 'ue' eigentlich sogar 130%
155 :
156 : // end of AbsBase.Pas
157 : /////////////////////////////////////////////////////////////////////////////////
158 : /////////////////////////////////////////////////////////////////////////////////
159 : /////////////////////////////////////////////////////////////////////////////////
160 :
161 :
162 :
163 : /////////////////////////////////////////////////////////////////////////////////
164 : /////////////////////////////////////////////////////////////////////////////////
165 : /////////////////////////////////////////////////////////////////////////////////
166 : // DefBase.Pas
167 :
168 : #define TextBoldBit 0x0001 /* Fett */
169 : #define TextRSlnBit 0x0002 /* Kursiv */
170 : #define TextUndlBit 0x0004 /* Unterstrichen */
171 : #define TextStrkBit 0x0008 /* Durchgesteichen */
172 : #define TextSupSBit 0x0010 /* Hocgestellt */
173 : #define TextSubSBit 0x0020 /* Tiefgestellt */
174 : #define TextKaptBit 0x0040 /* Kapitaelchen */
175 : #define TextLSlnBit 0x0080 /* Linkskursiv */
176 : #define TextDbUnBit 0x0100 /* Doppelt unterstrichen */
177 : #define TextDbStBit 0x0200 /* Doppelt durchgestrichen */
178 : #define TextSh2DBit 0x0400 /* 2D-Schatten 2.0 */
179 : #define TextSh3DBit 0x0800 /* 3D-Schatten 2.0 */
180 : #define TextSh4DBit 0x1000 /* 4D-Schatten 2.0 */
181 : #define TextShEbBit 0x2000 /* Embossed-Schatten 2.0 */
182 : #define FontAtrBits (TextBoldBit | TextRSlnBit)
183 :
184 : #define THJustLeft 0x00
185 : #define THJustCenter 0x01
186 : #define THJustRight 0x02
187 : #define THJustBlock 0x03
188 : #define THJustDrvOut 0x04 /* Austreibend Formatiert */
189 : #define THJustLocked 0x05 /* A l s S p e r r s c h r i f t */
190 : #define TVJustTop 0x00 /* Future */
191 : #define TVJustCenter 0x10 /* Future */
192 : #define TVJustBottom 0x20 /* Future */
193 : #define TVJustBlock 0x30 /* Future */
194 :
195 : #define MaxCharSlant 4200 /* Maximal 42deg kursiv ! */
196 :
197 : // end of DefBase.Pas
198 : /////////////////////////////////////////////////////////////////////////////////
199 : /////////////////////////////////////////////////////////////////////////////////
200 : /////////////////////////////////////////////////////////////////////////////////
201 :
202 :
203 : sal_Bool CheckTextOutl(ObjAreaType& F, ObjLineType& L);
204 :
205 0 : sal_Bool CheckTextOutl(ObjAreaType& F, ObjLineType& L)
206 : {
207 : return (F.FIntens!=L.LIntens) ||
208 : ((F.FFarbe!=L.LFarbe) && (F.FIntens>0)) ||
209 0 : ((F.FBFarbe!=L.LBFarbe) && (F.FIntens<100));
210 : }
211 :
212 :
213 : /////////////////////////////////////////////////////////////////////////////////
214 : /////////////////////////////////////////////////////////////////////////////////
215 : /////////////////////////////////////////////////////////////////////////////////
216 : // Misc.Pas
217 :
218 0 : short hPoint2Sgf(short a)
219 : {
220 : long b;
221 0 : b=long(a)*127*SgfDpmm/(144*5);
222 0 : return short(b);
223 : }
224 :
225 : // End of Misc.Pas
226 : // AbsRead.Pas
227 :
228 : // ======================================================================
229 : // Function GetTopToBaseLine() Function GetBaseLineToBtm()
230 : //
231 : // Abstand von Zeilenoberkante bis BaseLine bzw. von BaseLine bis
232 : // Unterkante berechnen. Alles in SGF-Units.
233 : // ======================================================================
234 :
235 0 : sal_uInt16 GetTopToBaseLine(sal_uInt16 MaxGrad)
236 : {
237 : long ret;
238 0 : ret=long(MaxGrad)*long(CharTopToBase) /long(100);
239 0 : return sal_uInt16(ret);
240 : }
241 :
242 : // ======================================================================
243 : // Function GetTextChar() Function GetTextCharConv()
244 : //
245 : // Liest ein Zeichen aus dem Textbuffer, wertet dabei eventuell
246 : // auftretende Escapesequenzen aus und setzt dementsprechend den
247 : // Ein-/Ausgabeparameter AktAtr. Index wird entsprechend erhoeht.
248 : // Der Parameter Rest muss immer die Anzahl der Zeichen beinhalten,
249 : // den angeforderten Zeichen in der aktuellen Zeile noch folgen.
250 : // Ansonsten funktioniert die Silbentrennung nicht richtig. Gibt man
251 : // stattdessen die Konstante NoTrenn an, wird in keinem Fall
252 : // getrennt, die Konstante DoTrenn bewirkt dagegen, dass ueberall dort
253 : // getrennt wird, wo ein SoftTrenner vorkommt.
254 : //
255 : // SoftTrenner werden immer in ein Minuszeichen konvertiert.
256 : // GetTextCharConv() konvertiert zusaetzlich HardSpace und AbsatzEnde
257 : // in Spaces sowie HardTrenner in Minuszeichen. TextEnde wird immer
258 : // als Char(0) geliefert.
259 : // ======================================================================
260 :
261 :
262 :
263 0 : UCHAR ConvertTextChar(UCHAR c)
264 : {
265 0 : if (c<32) {
266 0 : switch (c) {
267 0 : case HardSpace : c=' '; break;
268 0 : case AbsatzEnd : c=' '; break;
269 0 : case SoftTrenn : c='-'; break;
270 0 : case HardTrenn : c='-'; break;
271 0 : case SoftTrennK : c='-'; break;
272 0 : case SoftTrennAdd: c='-';
273 : }
274 : }
275 0 : return c;
276 : }
277 :
278 0 : long ChgValue(long Def, long Min, long Max, UCHAR FlgVal, long NumVal)
279 : {
280 0 : long r=0;
281 :
282 0 : if (FlgVal==EscDeflt) {
283 0 : r=Def; // zurueck auf Default
284 : } else {
285 0 : if (NumVal!=EscNoVal) r=NumVal; // Hart setzen
286 : }
287 :
288 0 : if (Min!=0 || Max!=0) {
289 0 : if (r>Max) r=Max;
290 0 : if (r<Min) r=Min;
291 : }
292 0 : return r;
293 : }
294 :
295 :
296 :
297 0 : void ChgSchnittBit(sal_uInt16 Bit, sal_uInt16 Radio1, sal_uInt16 Radio2, sal_uInt16 Radio3,
298 : UCHAR FlgVal, sal_uInt16 Schnitt0, sal_uInt16& Schnitt)
299 : {
300 : sal_uInt16 All,Rad;
301 :
302 0 : Rad=Radio1 | Radio2 | Radio3;
303 0 : All=Bit | Rad;
304 :
305 0 : switch (FlgVal) {
306 0 : case EscSet : Schnitt=(Schnitt & ~All) | Bit; break;
307 0 : case EscReset: Schnitt=(Schnitt & ~All); break;
308 0 : case EscDeflt: Schnitt=(Schnitt & ~All) | (Schnitt0 & All); break;
309 0 : case EscToggl: Schnitt=(Schnitt & ~Rad) ^ Bit;
310 : }
311 0 : }
312 :
313 :
314 :
315 0 : UCHAR GetNextChar(UCHAR* TBuf, sal_uInt16 Index)
316 : {
317 : sal_uInt16 Cnt;
318 0 : while (TBuf[Index]==Escape) {
319 0 : Index++;
320 0 : Cnt=0;
321 0 : while (TBuf[Index]!=Escape && Cnt<=MaxEscLen) {
322 0 : Index++; Cnt++; }
323 0 : Index++;
324 : }
325 0 : return TBuf[Index];
326 : }
327 :
328 :
329 :
330 0 : UCHAR ProcessOne(UCHAR* TBuf, sal_uInt16& Index,
331 : ObjTextType& Atr0, ObjTextType& AktAtr,
332 : sal_Bool ScanEsc)
333 : {
334 : UCHAR c;
335 : UCHAR Ident;
336 : sal_Bool Ende;
337 : sal_Bool q;
338 : UCHAR FlgVal;
339 : long NumVal;
340 : long Sgn;
341 : short i;
342 : sal_Bool EoVal;
343 :
344 0 : do {
345 0 : c=TBuf[Index]; Index++;
346 0 : Ende=(c!=Escape);
347 0 : if (Ende==sal_False) {
348 0 : c=TBuf[Index]; Index++;
349 0 : Ident=c; // Identifer merken
350 0 : FlgVal=EscNoFlg;
351 0 : NumVal=EscNoVal;
352 0 : c=TBuf[Index]; Index++; // Hier faengt der Wert an
353 0 : if (c==EscSet || c==EscReset || c==EscDeflt || c==EscToggl) FlgVal=c; else {
354 0 : if (c=='-') Sgn=-1; else Sgn=1;
355 0 : if (c=='+' || c=='-') { c=TBuf[Index]; Index++; }
356 0 : i=MaxEscValLen;
357 0 : NumVal=0;
358 0 : do {
359 0 : NumVal=10*NumVal+c-'0';
360 0 : EoVal=(TBuf[Index]<'0' || TBuf[Index]>'9');
361 0 : if (EoVal==sal_False) { c=TBuf[Index]; Index++; }
362 0 : i--;
363 : } while (i>0 && EoVal==sal_False);
364 0 : NumVal=Sgn*NumVal;
365 : }
366 0 : q=!CheckTextOutl(AktAtr.F,AktAtr.L);
367 :
368 0 : switch (Ident) {
369 0 : case EscFont : AktAtr.SetFont(sal_uLong (ChgValue(Atr0.GetFont(),0,0 ,FlgVal,NumVal)));break;
370 0 : case EscGrad : AktAtr.Grad =sal_uInt16(ChgValue(Atr0.Grad, 2,2000 ,FlgVal,NumVal)); break;
371 0 : case EscBreit: AktAtr.Breite =sal_uInt16(ChgValue(Atr0.Breite, 1,1000 ,FlgVal,NumVal)); break;
372 0 : case EscKaptS: AktAtr.Kapit =(sal_uInt8)(ChgValue(Atr0.Kapit, 1,255 ,FlgVal,NumVal)); break;
373 0 : case EscLFeed: AktAtr.LnFeed =sal_uInt16(ChgValue(Atr0.LnFeed, 1,65535 ,FlgVal,NumVal)); break;
374 0 : case EscSlant: AktAtr.Slant =sal_uInt16(ChgValue(Atr0.Slant, 1,MaxCharSlant ,FlgVal,NumVal)); break;
375 0 : case EscVPos : AktAtr.ChrVPos=char (ChgValue(Atr0.ChrVPos,-128,127 ,FlgVal,NumVal)); break;
376 0 : case EscZAbst: AktAtr.ZAbst =(sal_uInt8)(ChgValue(Atr0.ZAbst, 1,255 ,FlgVal,NumVal)); break;
377 0 : case EscHJust: AktAtr.Justify=(sal_uInt8)(ChgValue(Atr0.Justify & 0x0F,0,5 ,FlgVal,NumVal)); break;
378 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;
379 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;
380 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;
381 :
382 0 : case EscMustr: { AktAtr.F.FMuster=sal_uInt16(ChgValue(Atr0.F.FMuster,0,65535,FlgVal,NumVal)); } break;
383 0 : case EscMFarb: { AktAtr.F.FFarbe =(sal_uInt8)(ChgValue(Atr0.F.FFarbe,0,7 ,FlgVal,NumVal)); } break;
384 0 : case EscMBFrb: { AktAtr.F.FBFarbe=(sal_uInt8)(ChgValue(Atr0.F.FBFarbe,0,255,FlgVal,NumVal)); } break;
385 0 : case EscMInts: { AktAtr.F.FIntens=(sal_uInt8)(ChgValue(Atr0.F.FIntens,0,100,FlgVal,NumVal)); } break;
386 :
387 0 : case EscSMstr: { AktAtr.ShdF.FMuster=sal_uInt16(ChgValue(Atr0.ShdF.FMuster,0,65535,FlgVal,NumVal)); } break;
388 0 : case EscSFarb: { AktAtr.ShdL.LFarbe =(sal_uInt8)(ChgValue(Atr0.ShdL.LFarbe,0,7 ,FlgVal,NumVal)); AktAtr.ShdF.FFarbe =AktAtr.ShdL.LFarbe; } break;
389 0 : case EscSBFrb: { AktAtr.ShdL.LBFarbe=(sal_uInt8)(ChgValue(Atr0.ShdL.LBFarbe,0,255,FlgVal,NumVal)); AktAtr.ShdF.FBFarbe=AktAtr.ShdL.LBFarbe; } break;
390 0 : case EscSInts: { AktAtr.ShdL.LIntens=(sal_uInt8)(ChgValue(Atr0.ShdL.LIntens,0,100,FlgVal,NumVal)); AktAtr.ShdF.FIntens=AktAtr.ShdL.LIntens; } break;
391 0 : case EscSDist: { AktAtr.ShdVers.x=(short)ChgValue(Atr0.ShdVers.x,0,30000,FlgVal,NumVal); AktAtr.ShdVers.y=AktAtr.ShdVers.x; } break;
392 0 : case EscSXDst: { AktAtr.ShdVers.x=(short)ChgValue(Atr0.ShdVers.x,0,30000,FlgVal,NumVal); } break;
393 0 : case EscSYDst: { AktAtr.ShdVers.y=(short)ChgValue(Atr0.ShdVers.y,0,30000,FlgVal,NumVal); } break;
394 :
395 0 : case EscBold : ChgSchnittBit(TextBoldBit,0,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
396 0 : case EscRSlnt: ChgSchnittBit(TextRSlnBit,TextLSlnBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
397 0 : case EscUndln: ChgSchnittBit(TextUndlBit,TextDbUnBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
398 0 : case EscStrik: ChgSchnittBit(TextStrkBit,TextDbStBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
399 0 : case EscDbUnd: ChgSchnittBit(TextDbUnBit,TextUndlBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
400 0 : case EscDbStk: ChgSchnittBit(TextDbStBit,TextStrkBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
401 0 : case EscSupSc: ChgSchnittBit(TextSupSBit,TextSubSBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
402 0 : case EscSubSc: ChgSchnittBit(TextSubSBit,TextSupSBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
403 0 : case EscKaptF: ChgSchnittBit(TextKaptBit,0,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
404 0 : case EscLSlnt: ChgSchnittBit(TextLSlnBit,TextRSlnBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
405 0 : case Esc2DShd: ChgSchnittBit(TextSh2DBit,TextSh3DBit,TextSh4DBit,TextShEbBit,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
406 0 : case Esc3DShd: ChgSchnittBit(TextSh3DBit,TextSh2DBit,TextSh4DBit,TextShEbBit,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
407 0 : case Esc4DShd: ChgSchnittBit(TextSh4DBit,TextSh2DBit,TextSh3DBit,TextShEbBit,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
408 0 : case EscEbShd: ChgSchnittBit(TextShEbBit,TextSh2DBit,TextSh3DBit,TextSh4DBit,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
409 : } //endcase
410 0 : if (TBuf[Index]==Escape) Index++; // zweites Esc weglesen }
411 : } // if Ende==sal_False
412 : } while (Ende==sal_False && ScanEsc==sal_False);
413 0 : if (Ende==sal_False) c=Escape;
414 0 : return c;
415 : } // end of ProcessOne
416 :
417 :
418 0 : UCHAR GetTextChar(UCHAR* TBuf, sal_uInt16& Index,
419 : ObjTextType& Atr0, ObjTextType& AktAtr,
420 : sal_uInt16 Rest, sal_Bool ScanEsc)
421 : {
422 : UCHAR c,c0,nc;
423 :
424 0 : c=ProcessOne(TBuf,Index,Atr0,AktAtr,ScanEsc);
425 0 : if (ScanEsc==sal_False) {
426 0 : if (c==SoftTrennAdd || c==SoftTrennK || c==SoftTrenn) {
427 0 : nc=GetNextChar(TBuf,Index);
428 0 : c0=c;
429 0 : if (Rest==0 || Rest==DoTrenn ||
430 0 : nc==' ' || nc==AbsatzEnd || nc==TextEnd) c='-';
431 : else {
432 0 : c=ProcessOne(TBuf,Index,Atr0,AktAtr,ScanEsc); // den Trenner ueberspringen
433 0 : if (c0==SoftTrennAdd) {
434 0 : if (c>=32) c=ProcessOne(TBuf,Index,Atr0,AktAtr,ScanEsc); // und hier noch 'nen Buchstaben ueberspringen
435 : }
436 : }
437 : }
438 0 : if ((Rest==1 || Rest==DoTrenn) && GetNextChar(TBuf,Index)==SoftTrennK) {
439 0 : if (c=='c') c='k';
440 0 : else if (c=='C') c='K';
441 : }
442 : }
443 0 : return c;
444 : }
445 :
446 : // HardSpace und HardTrenn muessen explizit konvertiert werden ! }
447 : // if AktAtr.Schnitt and TextKaptBit =TextKaptBit then c:=UpCase(c);(explizit) }
448 :
449 : // Bei der Trennmethode SoftTrennAdd wird davon ausgegangen, dass der zu }
450 : // trennende Konsonant bereits 3x mal im TextBuf vorhanden ist, z.b.: }
451 : // "Schiff-fahrt". Wenn nicht getrennt, dann wird "-f" entfernt. }
452 :
453 :
454 :
455 0 : UCHAR GetTextCharConv(UCHAR* TBuf, sal_uInt16& Index,
456 : ObjTextType& Atr0, ObjTextType& AktAtr,
457 : sal_uInt16 Rest, sal_Bool ScanEsc)
458 : {
459 : UCHAR c;
460 :
461 0 : c=GetTextChar(TBuf,Index,Atr0,AktAtr,Rest,ScanEsc);
462 0 : if (c<32) {
463 0 : switch (c) {
464 0 : case HardSpace : c=' '; break;
465 0 : case AbsatzEnd : c=' '; break;
466 0 : case HardTrenn : c='-';
467 : }
468 : }
469 0 : return c;
470 : }
471 :
472 :
473 : // ======================================================================
474 : // Function GetLineFeed()
475 : //
476 : // Benoetigter Zeilenabstand in SGF-Units. ChrVPos wird beruecksichtigt.
477 : // ======================================================================
478 0 : sal_uInt16 GetLineFeed(UCHAR* TBuf, sal_uInt16 Index, ObjTextType Atr0, ObjTextType AktAtr,
479 : sal_uInt16 nChar, sal_uInt16& LF, sal_uInt16& MaxGrad)
480 : {
481 0 : UCHAR c=0;
482 0 : sal_Bool AbsEnd=sal_False;
483 0 : sal_uLong LF100=0;
484 0 : sal_uLong MaxLF100=0;
485 0 : sal_Bool LFauto=0;
486 0 : sal_Bool First=sal_True;
487 : sal_uInt16 Grad;
488 0 : sal_uInt16 i=0;
489 0 : sal_uInt16 r=1;
490 :
491 0 : MaxGrad=0;
492 0 : while (!AbsEnd && nChar>0) {
493 0 : nChar--;
494 0 : c=GetTextChar(TBuf,Index,Atr0,AktAtr,nChar,sal_False);
495 0 : i++;
496 0 : AbsEnd=(c==TextEnd || c==AbsatzEnd);
497 0 : if (First || (!AbsEnd && c!=' ' && c!=HardTrenn)) {
498 0 : LFauto=(AktAtr.LnFeed & 0x8000)==0;
499 0 : LF100=AktAtr.LnFeed & 0x7FFF;
500 0 : if (LFauto) LF100=LF100*AktAtr.Grad; else LF100*=LF100;
501 0 : if (AktAtr.ChrVPos>0) LF100-=AktAtr.ChrVPos*100;
502 0 : if (LF100>MaxLF100) MaxLF100=LF100;
503 0 : Grad=AktAtr.Grad;
504 0 : if (AktAtr.ChrVPos>0) Grad=Grad-AktAtr.ChrVPos;
505 0 : if (Grad>MaxGrad) MaxGrad=Grad;
506 0 : First=sal_False;
507 : }
508 0 : if (!AbsEnd && c!=' ') r=i;
509 : }
510 0 : MaxGrad=hPoint2Sgf(MaxGrad);
511 0 : if (MaxLF100<=4000) { // sonst Overflowgefahr
512 0 : LF=sal_uInt16(hPoint2Sgf(short(MaxLF100)) /100);
513 : } else {
514 0 : LF=sal_uInt16(hPoint2Sgf(short(MaxLF100) /100));
515 : }
516 :
517 0 : return r;
518 : }
519 :
520 : // End of AbsRead.Pas
521 : /////////////////////////////////////////////////////////////////////////////////
522 : /////////////////////////////////////////////////////////////////////////////////
523 : /////////////////////////////////////////////////////////////////////////////////
524 :
525 :
526 :
527 : /////////////////////////////////////////////////////////////////////////////////
528 : /////////////////////////////////////////////////////////////////////////////////
529 : /////////////////////////////////////////////////////////////////////////////////
530 : // iFont.Pas
531 :
532 : #define DefaultSlant 1500 /* Default: Italic ist 15deg */
533 : #define SuperSubFact 60 /* SuperScript/SubScript: 60% vom Schriftgrad */
534 : #define DefaultSpace 40 /* Default: Space ist 40% vom SchriftGrad */
535 :
536 0 : sal_uInt16 SetTextContext(OutputDevice& rOut, ObjTextType& Atr, sal_Bool Kapt, sal_uInt16 Dreh,
537 : sal_uInt16 FitXMul, sal_uInt16 FitXDiv, sal_uInt16 FitYMul, sal_uInt16 FitYDiv)
538 : {
539 : SgfFontOne* pSgfFont; // Font aus dem IniFile
540 0 : Font aFont;
541 0 : Color aColor;
542 : sal_uLong Grad;
543 : sal_uLong Brei;
544 0 : String FNam;
545 0 : sal_uInt16 StdBrei=50; // Durchschnittliche Zeichenbreite in % von Schriftgrad
546 0 : sal_Bool bFit=(FitXMul!=1 || FitXDiv!=1 || FitYMul!=1 || FitYDiv!=1);
547 :
548 0 : pSgfFont = pSgfFonts->GetFontDesc(Atr.GetFont());
549 :
550 0 : if ( pSgfFont!=NULL )
551 : {
552 0 : FNam =pSgfFont->SVFName;
553 0 : StdBrei=pSgfFont->SVWidth;
554 0 : if (pSgfFont->Fixd) aFont.SetPitch(PITCH_FIXED); else aFont.SetPitch(PITCH_VARIABLE);
555 0 : aFont.SetFamily(pSgfFont->SVFamil);
556 0 : aFont.SetCharSet(pSgfFont->SVChSet);
557 0 : aFont.SetName(FNam);
558 : }
559 : else
560 : { // Falls nich im Inifile, sind hier einige Fonts hart kodiert
561 0 : aFont.SetPitch(PITCH_VARIABLE);
562 0 : switch (Atr.GetFont()) {
563 : case 92500: case 92501: case 92504: case 92505:
564 : {
565 : #if defined(WNT)
566 : FNam=rtl::OUString("Times New Roman"); // CG Times ist unter Windows Times New Roman
567 : #else
568 0 : FNam=rtl::OUString("Times"); // ansonsten ist das einfach Times
569 : #endif
570 0 : StdBrei=40;
571 0 : aFont.SetFamily(FAMILY_ROMAN);
572 0 : } break;
573 : case 94021: case 94022: case 94023: case 94024: {
574 : #if defined(WNT)
575 : FNam=rtl::OUString("Arial"); // Univers ist unter Windows Arial
576 : #else
577 0 : FNam=rtl::OUString("Helvetica"); // und ansonsten Helvetica
578 : #endif
579 0 : aFont.SetFamily(FAMILY_SWISS);
580 0 : StdBrei=47;
581 0 : } break;
582 : case 93950: case 93951: case 93952: case 93953: {
583 : #if defined(WNT)
584 : FNam=rtl::OUString("Courier New"); // Der Vector-Courierfont unter Windows heisst Courier New
585 : #else
586 0 : FNam=rtl::OUString("Courier"); // ansonsten ist und bleibt Courier immer Courier
587 : #endif
588 0 : aFont.SetFamily(FAMILY_ROMAN);
589 0 : aFont.SetPitch(PITCH_FIXED);
590 0 : } break;
591 0 : default: FNam = rtl::OUString("Helvetica");
592 : }
593 0 : aFont.SetName(FNam);
594 : //aFont.SetCharSet(CHARSET_SYSTEM);
595 : }
596 :
597 0 : Grad=sal_uLong(Atr.Grad);
598 0 : if ((Atr.Schnitt & TextKaptBit) !=0 && Kapt) Grad=Grad*sal_uLong(Atr.Kapit)/100;
599 0 : if ((Atr.Schnitt & TextSupSBit) !=0 || (Atr.Schnitt & TextSubSBit) !=0) Grad=Grad*SuperSubFact/100;
600 0 : Brei=Grad;
601 0 : if (Atr.Breite!=100 || bFit) {
602 0 : if (bFit) {
603 0 : Grad=Grad*sal_uLong(FitYMul)/sal_uLong(FitYDiv);
604 0 : Brei=Brei*sal_uLong(FitXMul)/sal_uLong(FitXDiv);
605 : }
606 0 : Brei=Brei*sal_uLong(Atr.Breite)/100;
607 0 : Brei=Brei*sal_uLong(StdBrei)/100;
608 0 : aFont.SetSize(Size(hPoint2Sgf(sal_uInt16(Brei)),hPoint2Sgf(sal_uInt16(Grad))));
609 : } else {
610 0 : aFont.SetSize(Size(0,hPoint2Sgf(sal_uInt16(Grad))));
611 : }
612 :
613 0 : aColor=Sgv2SvFarbe(Atr.L.LFarbe,Atr.L.LBFarbe,Atr.L.LIntens); aFont.SetColor(aColor);
614 0 : aColor=Sgv2SvFarbe(Atr.F.FFarbe,Atr.F.FBFarbe,Atr.F.FIntens); aFont.SetFillColor(aColor);
615 0 : aFont.SetTransparent(sal_True);
616 0 : aFont.SetAlign(ALIGN_BASELINE);
617 :
618 0 : Dreh/=10; Dreh=3600-Dreh; if (Dreh==3600) Dreh=0;
619 0 : aFont.SetOrientation(Dreh);
620 :
621 0 : if ((Atr.Schnitt & TextBoldBit) !=0) aFont.SetWeight(WEIGHT_BOLD);
622 0 : if ((Atr.Schnitt & TextRSlnBit) !=0) aFont.SetItalic(ITALIC_NORMAL);
623 0 : if ((Atr.Schnitt & TextUndlBit) !=0) aFont.SetUnderline(UNDERLINE_SINGLE);
624 0 : if ((Atr.Schnitt & TextDbUnBit) !=0) aFont.SetUnderline(UNDERLINE_DOUBLE);
625 0 : if ((Atr.Schnitt & TextStrkBit) !=0) aFont.SetStrikeout(STRIKEOUT_SINGLE);
626 0 : if ((Atr.Schnitt & TextDbStBit) !=0) aFont.SetStrikeout(STRIKEOUT_DOUBLE);
627 0 : if ((Atr.Schnitt & TextSh2DBit) !=0) aFont.SetShadow(sal_True);
628 0 : if ((Atr.Schnitt & TextSh3DBit) !=0) aFont.SetShadow(sal_True);
629 0 : if ((Atr.Schnitt & TextSh4DBit) !=0) aFont.SetShadow(sal_True);
630 0 : if ((Atr.Schnitt & TextShEbBit) !=0) aFont.SetShadow(sal_True);
631 0 : if (CheckTextOutl(Atr.F,Atr.L)) aFont.SetOutline(sal_True);
632 :
633 0 : if (aFont!=rOut.GetFont()) rOut.SetFont(aFont);
634 :
635 0 : return 0;
636 : }
637 :
638 : // iFont.Pas
639 : /////////////////////////////////////////////////////////////////////////////////
640 : /////////////////////////////////////////////////////////////////////////////////
641 : /////////////////////////////////////////////////////////////////////////////////
642 :
643 :
644 : /////////////////////////////////////////////////////////////////////////////////
645 : /////////////////////////////////////////////////////////////////////////////////
646 : /////////////////////////////////////////////////////////////////////////////////
647 : // Absatz.Pas
648 :
649 : struct ProcChrSta {
650 : sal_uInt16 Index;
651 : sal_uInt16 ChrXP;
652 : UCHAR OutCh;
653 : sal_Bool Kapt;
654 : ObjTextType Attrib;
655 : };
656 :
657 0 : void InitProcessCharState(ProcChrSta& State, ObjTextType& AktAtr, sal_uInt16 IndexA)
658 : {
659 0 : State.Attrib=AktAtr;
660 0 : State.OutCh=0;
661 0 : State.Index=IndexA;
662 0 : State.ChrXP=0;
663 0 : State.Kapt=sal_False;
664 0 : }
665 :
666 0 : sal_Bool UpcasePossible(UCHAR c)
667 : {
668 0 : if ((c>='a' && c<='z') || c == 0xe4 || c == 0xf6 || c == 0xfc ) return sal_True;
669 0 : else return sal_False;
670 : }
671 :
672 0 : UCHAR Upcase(UCHAR c)
673 : {
674 0 : if ((c>=(UCHAR)'a' && c<=(UCHAR)'z')) c=(c-(UCHAR)'a')+(UCHAR)'A';
675 0 : else if ( c == 0xe4 ) c = 0xc4;
676 0 : else if ( c == 0xf6 ) c = 0xd6;
677 0 : else if ( c == 0xfc ) c = 0xdc;
678 0 : return c;
679 : }
680 :
681 0 : sal_uInt16 GetCharWidth(OutputDevice& rOut, UCHAR c)
682 : {
683 : sal_uInt16 ChrWidth;
684 :
685 0 : if (c==' ')
686 : {
687 0 : ChrWidth=(sal_uInt16)rOut.GetTextWidth( rtl::OUString('A') );
688 0 : if (rOut.GetFont().GetPitch()!=PITCH_FIXED) {
689 0 : ChrWidth=MulDiv(ChrWidth,DefaultSpace,100);
690 : }
691 : }
692 : else
693 : {
694 : // with MaxChar == 255 c cannot be greater than MaxChar
695 : // assert if MaxChar is ever changed
696 : OSL_ENSURE( MaxChar == 255, "MaxChar not 255" );
697 : OSL_ENSURE(sizeof(UCHAR) == 1, "should be 1");
698 0 : if (c>=MinChar /*&& c<=MaxChar*/)
699 : {
700 0 : ChrWidth=(sal_uInt16)rOut.GetTextWidth(rtl::OUString(reinterpret_cast<sal_Char*>(&c), 1, RTL_TEXTENCODING_IBM_437));
701 : }
702 : else
703 : {
704 0 : ChrWidth=(sal_uInt16)rOut.GetTextWidth(rtl::OUString(static_cast<sal_Unicode>('A')));
705 : }
706 : }
707 0 : return ChrWidth;
708 : }
709 :
710 0 : UCHAR ProcessChar(OutputDevice& rOut, UCHAR* TBuf, ProcChrSta& R, ObjTextType& Atr0,
711 : sal_uInt16& nChars, sal_uInt16 Rest,
712 : short* Line, UCHAR* cLine)
713 : {
714 0 : sal_uInt16 KernDist=0; // Wert fuer Kerning
715 : sal_uInt16 ChrWidth;
716 : UCHAR c;
717 : UCHAR c1;
718 : sal_Bool AbsEnd;
719 :
720 0 : c=GetTextChar(TBuf,R.Index,Atr0,R.Attrib,Rest,sal_False); // versucht evtl. zu trennen, wenn Rest entsprechenden Wert besitzt
721 :
722 0 : AbsEnd=(c==AbsatzEnd || c==TextEnd);
723 0 : if (AbsEnd==sal_False) {
724 0 : R.OutCh=ConvertTextChar(c); // von HardTrenn nach '-', ...
725 0 : R.Kapt=(R.Attrib.Schnitt & TextKaptBit) !=0 && UpcasePossible(R.OutCh);
726 0 : if (R.Kapt) R.OutCh=Upcase(R.OutCh);
727 0 : SetTextContext(rOut,R.Attrib,R.Kapt,0,1,1,1,1);
728 :
729 0 : if (R.Kapt) c1=Upcase(c); else c1=c;
730 0 : ChrWidth=GetCharWidth(rOut,c1);
731 :
732 0 : if (R.Attrib.ZAbst!=100) { // Spezial-Zeichenabstand ?
733 : sal_uLong Temp;
734 0 : Temp=sal_uLong(ChrWidth)*sal_uLong(R.Attrib.ZAbst)/100;
735 0 : ChrWidth=sal_uInt16(Temp);
736 : }
737 0 : nChars++;
738 0 : if (R.ChrXP>32000) R.ChrXP=32000;
739 0 : Line[nChars]=R.ChrXP-KernDist;
740 0 : cLine[nChars]=c;
741 0 : R.ChrXP+=ChrWidth-KernDist; // Position fuer den naechsten Character
742 : }
743 0 : return c;
744 : }
745 :
746 0 : void FormatLine(UCHAR* TBuf, sal_uInt16& Index, ObjTextType& Atr0, ObjTextType& AktAtr,
747 : sal_uInt16 UmbWdt, sal_uInt16 AdjWdt,
748 : short* Line, sal_uInt16& nChars,
749 : double, double,
750 : UCHAR* cLine, sal_Bool TextFit)
751 : {
752 0 : VirtualDevice vOut;
753 : UCHAR c,c0;
754 : UCHAR ct;
755 : sal_Bool First; // erster Char ?
756 0 : sal_uInt8 Just = 0; // Absatzformatierung
757 : sal_Bool Border; // Rand der Box erreicht ?
758 : sal_Bool Border0;
759 : sal_Bool AbsEnd; // Ende des Absatzes erreicht ?
760 0 : ProcChrSta* R=new ProcChrSta;
761 0 : ProcChrSta* R0=new ProcChrSta;
762 0 : ProcChrSta* WErec=new ProcChrSta;
763 : sal_uInt16 WEnChar;
764 0 : ProcChrSta* WErec0=new ProcChrSta;
765 : sal_uInt16 WEnChar0;
766 0 : ProcChrSta* TRrec=new ProcChrSta;
767 : sal_uInt16 TRnChar;
768 :
769 : sal_uInt16 WordEndCnt; // Justieren und Trennen
770 : sal_Bool WordEnd;
771 : sal_Bool Trenn;
772 :
773 : short BoxRest; // zum Quetschen und formatieren
774 : sal_uInt16 i,j,k,h;
775 : sal_uInt16 re,li;
776 :
777 0 : vOut.SetMapMode(MapMode(MAP_10TH_MM,Point(),Fraction(1,4),Fraction(1,4)));
778 :
779 0 : nChars=0;
780 0 : SetTextContext(vOut,AktAtr,sal_False,0,1,1,1,1);
781 0 : InitProcessCharState(*R,AktAtr,Index);
782 0 : (*R0)=(*R); (*WErec)=(*R); WEnChar=0; c0=0; Border0=sal_False;
783 0 : Border=sal_False; First=sal_True;
784 0 : WordEndCnt=0;
785 :
786 0 : do { // mal schauen, wieviele Worte so in die Zeile passen
787 0 : if (Border) c=ProcessChar(vOut,TBuf,*R,Atr0,nChars,DoTrenn,Line,cLine);
788 0 : else c=ProcessChar(vOut,TBuf,*R,Atr0,nChars,NoTrenn,Line,cLine);
789 0 : AbsEnd=(c==AbsatzEnd || c==TextEnd);
790 : //if not AbsEnd then
791 : {
792 0 : if (First) {
793 0 : Just=R->Attrib.Justify & 0x0F; // Absatzformat steht wenn, dann am Anfang
794 : }
795 0 : Border=R->ChrXP>UmbWdt;
796 0 : WordEnd=(AbsEnd || (c==' ')) && (c0!=' ') && (c0!=0);
797 0 : Trenn=c=='-';
798 0 : if (WordEnd && !Border0) {
799 0 : WordEndCnt++;
800 0 : (*WErec)=(*R0);
801 0 : WEnChar=nChars-1;
802 : }
803 0 : if (Trenn && !Border) {
804 0 : WordEndCnt++;
805 0 : (*WErec)=(*R);
806 0 : WEnChar=nChars;
807 : }
808 : }
809 0 : (*R0)=(*R); c0=c;
810 0 : Border0=Border;
811 0 : First=sal_False;
812 0 : AbsEnd=AbsEnd || (nChars>=MaxLineChars);
813 0 : } while (!(AbsEnd || (Border && ((WordEndCnt>0) || WordEnd || Trenn))));
814 :
815 0 : if (Border) { // Trennen und Quetschen
816 0 : (*WErec0)=(*WErec); WEnChar0=WEnChar;
817 0 : AbsEnd=sal_False; c0=0;
818 0 : (*R)=(*WErec); nChars=WEnChar;
819 0 : (*TRrec)=(*R); TRnChar=nChars;
820 0 : Border0=sal_False; Border=sal_False;
821 0 : do { // erst mal gucken wieviele Silben noch reinpassen
822 0 : ct=ProcessChar(vOut,TBuf,*TRrec,Atr0,TRnChar,DoTrenn,Line,cLine);
823 0 : c=ProcessChar(vOut,TBuf,*R,Atr0,nChars,NoTrenn,Line,cLine);
824 0 : AbsEnd=(ct==AbsatzEnd) || (ct==TextEnd) || (nChars>=MaxLineChars);
825 :
826 0 : Border=TRrec->ChrXP>UmbWdt;
827 0 : WordEnd=AbsEnd || ((AbsEnd || (c==' ')) && (c0!=' ') && (c0!=0));
828 0 : Trenn=ct=='-';
829 0 : if (WordEnd && (!Border0 || (WordEndCnt==0))) {
830 0 : WordEndCnt++;
831 0 : (*WErec)=(*R0);
832 0 : if (AbsEnd) WEnChar=nChars; else WEnChar=nChars-1;
833 0 : (*TRrec)=(*R); TRnChar=nChars; // zum weitersuchen
834 : }
835 0 : if (Trenn && (!Border || (WordEndCnt==0))) {
836 0 : WordEndCnt++; // merken, dass man hier trennen kann
837 0 : (*WErec)=(*TRrec);
838 0 : WEnChar=TRnChar;
839 0 : (*TRrec)=(*R); TRnChar=nChars; // zum weitersuchen
840 : }
841 0 : (*R0)=(*R); c0=c;
842 0 : Border0=Border;
843 0 : Border=R->ChrXP>UmbWdt;
844 0 : } while (!(AbsEnd || (Border && ((WordEndCnt>0) || WordEnd || Trenn))));
845 :
846 0 : while (WErec0->Index<WErec->Index) { // damit Line[] auch garantiert stimmt }
847 0 : c=ProcessChar(vOut,TBuf,*WErec0,Atr0,WEnChar0,WEnChar-WEnChar0-1,Line,cLine);
848 : }
849 :
850 0 : (*R)=(*WErec); nChars=WEnChar;
851 :
852 0 : if (UmbWdt>=R->ChrXP) {
853 0 : BoxRest=UmbWdt-R->ChrXP;
854 : } else { // Zusammenquetschen
855 0 : BoxRest=R->ChrXP-UmbWdt; // um soviel muss gequetscht werden
856 0 : for (i=2;i<=nChars;i++) { // 1. CharPosition bleibt !
857 0 : Line[i]-=(i-1)*(BoxRest) /(nChars-1);
858 : }
859 0 : R->ChrXP=UmbWdt;
860 0 : Line[nChars+1]=UmbWdt;
861 : }
862 : }
863 :
864 0 : if (!AbsEnd) {
865 0 : do { // Leerzeichen weglesen
866 0 : (*WErec)=(*R);
867 0 : c=GetTextChar(TBuf,R->Index,Atr0,R->Attrib,NoTrenn,sal_False);
868 0 : nChars++;
869 0 : Line[nChars]=R->ChrXP;
870 0 : cLine[nChars]=c;
871 : } while (c==' ');
872 0 : if (c!=' ' && c!=AbsatzEnd && c!=TextEnd) {
873 0 : nChars--;
874 0 : (*R)=(*WErec);
875 : }
876 : }
877 :
878 0 : if (AbsEnd && nChars<MaxLineChars) { // Ausrichten, statt Blocksatz aber linksbuendig
879 0 : if (Just==3) Just=0;
880 0 : nChars++; Line[nChars]=R->ChrXP; // Damit AbsatzEnde auch weggelesen wird
881 0 : Line[nChars+1]=R->ChrXP; // denn die Breite von CR oder #0 ist nun mal sehr klein
882 0 : if (TBuf[R->Index-1]!=AbsatzEnd && TBuf[R->Index-1]!=TextEnd) {
883 0 : c=GetTextChar(TBuf,R->Index,Atr0,R->Attrib,NoTrenn,sal_False); // Kleine Korrektur. Notig, wenn nur 1 Wort in
884 : }
885 : }
886 :
887 0 : BoxRest=AdjWdt-R->ChrXP;
888 0 : if (TextFit) Just=THJustLeft;
889 :
890 0 : switch (Just) {
891 0 : case THJustLeft: break; // Links
892 : case THJustCenter: {
893 0 : BoxRest=BoxRest /2; // Mitte
894 0 : for (i=1;i<=nChars;i++) Line[i]=Line[i]+BoxRest;
895 0 : } break;
896 : case THJustRight: { // Rechts
897 0 : for (i=1;i<=nChars;i++) Line[i]=Line[i]+BoxRest;
898 0 : } break;
899 : case THJustDrvOut:
900 : case THJustBlock: { // Block und Austreibend
901 0 : re=nChars;
902 0 : if (Just==THJustDrvOut) re--;
903 0 : while (re>=1 && (cLine[re]==' ' || cLine[re]==TextEnd || cLine[re]==AbsatzEnd)) re--;
904 0 : li=1;
905 0 : while (li<=re && (cLine[li]==' ' || cLine[li]==TextEnd || cLine[li]==AbsatzEnd)) li++;
906 0 : if (Just==THJustDrvOut) BoxRest=AdjWdt-Line[re+1];
907 :
908 0 : j=0; // Anzahl der Spaces ermitteln
909 0 : for (i=li;i<=re;i++) {
910 0 : if (cLine[i]==' ') {
911 0 : j++;
912 : }
913 : }
914 :
915 0 : if (j==0) { // nur 1 Wort ? -> Strecken !
916 0 : for (i=li+1;i<=re;i++) { // von links nach rechts
917 0 : Line[i]=Line[i]+MulDiv(i-li,BoxRest,re-li+1-1);
918 : }
919 : } else {
920 0 : k=0; h=0;
921 0 : for (i=li;i<=re;i++) { // j Spaces aufbohren !
922 0 : if (cLine[i]==' ') { // Space gefunden !
923 0 : k++;
924 0 : h=MulDiv(k,BoxRest,j);
925 : }
926 0 : Line[i]=Line[i]+h;
927 : }
928 : }
929 0 : for (i=re+1;i<=nChars;i++) Line[i]=Line[i]+BoxRest; // und den Rest anpassen
930 0 : Line[nChars+1]=AdjWdt;
931 0 : } break;
932 : case THJustLocked: { //Gesperrt
933 0 : re=nChars-1;
934 0 : while (re>=1 && (cLine[re]==' ' || cLine[re]==TextEnd || cLine[re]==AbsatzEnd)) re--;
935 0 : li=1;
936 0 : while (li<=re && (cLine[li]==' ' || cLine[li]==TextEnd || cLine[li]==AbsatzEnd)) li++;
937 0 : BoxRest=AdjWdt-Line[re+1];
938 0 : for (i=li+1;i<=re;i++) { // Strecken von links nach rechts
939 0 : Line[i]=Line[i]+MulDiv(i-li,BoxRest,re-li+1-1);
940 : }
941 0 : for (i=re+1;i<=nChars;i++) Line[i]=Line[i]+BoxRest; // und den Rest anpassen
942 0 : Line[nChars+1]=AdjWdt;
943 0 : } break;
944 : }
945 0 : Index=R->Index;
946 0 : AktAtr=R->Attrib;
947 0 : delete R;
948 0 : delete R0;
949 0 : delete WErec;
950 0 : delete WErec0;
951 0 : delete TRrec;
952 0 : }
953 :
954 :
955 :
956 : // End of Absatz.Pas
957 : /////////////////////////////////////////////////////////////////////////////////
958 : /////////////////////////////////////////////////////////////////////////////////
959 : /////////////////////////////////////////////////////////////////////////////////
960 :
961 :
962 : /////////////////////////////////////////////////////////////////////////////////
963 : /////////////////////////////////////////////////////////////////////////////////
964 : /////////////////////////////////////////////////////////////////////////////////
965 : // DrawText.Pas
966 :
967 0 : void DrawChar(OutputDevice& rOut, UCHAR c, ObjTextType T, PointType Pos, sal_uInt16 DrehWink,
968 : sal_uInt16 FitXMul, sal_uInt16 FitXDiv, sal_uInt16 FitYMul, sal_uInt16 FitYDiv)
969 : {
970 0 : SetTextContext(rOut,T,UpcasePossible(c),DrehWink,FitXMul,FitXDiv,FitYMul,FitYDiv);
971 0 : if ((T.Schnitt & TextKaptBit)!=0 && UpcasePossible(c)) c=Upcase(c);
972 : rtl::OUString s(reinterpret_cast<const sal_Char*>(&c), 1,
973 0 : RTL_TEXTENCODING_IBM_437);
974 0 : rOut.DrawText( Point( Pos.x, Pos.y ), s );
975 0 : }
976 :
977 : /*************************************************************************
978 : |*
979 : |* TextType::Draw()
980 : |*
981 : *************************************************************************/
982 0 : void TextType::Draw(OutputDevice& rOut)
983 : {
984 0 : if ((Flags & TextOutlBit)!=0) return; // Sourcetext fuer Outliner !!
985 :
986 : ObjTextType T1,T2;
987 : sal_uInt16 Index1;
988 : sal_uInt16 Index2;
989 0 : UCHAR c = TextEnd;
990 : sal_uInt16 l; // Anzahl der Zeichen in der Zeile
991 : sal_uInt16 i;
992 : short yPos0;
993 : short xPos;
994 : short yPos;
995 : sal_uInt16 LF;
996 : sal_uInt16 MaxGrad;
997 : short xSize;
998 : short xSAdj;
999 : short ySize;
1000 : double sn,cs;
1001 : sal_uInt16 TopToBase;
1002 0 : sal_Bool Ende = 0;
1003 : sal_uInt16 lc;
1004 : sal_Bool LineFit; // FitSize.x=0? oder Flags -> jede Zeile stretchen
1005 : sal_Bool TextFit;
1006 : short* xLine;
1007 : UCHAR* cLine; // Buffer fuer FormatLine
1008 : sal_uInt16 FitXMul;
1009 : sal_uInt16 FitXDiv;
1010 : sal_uInt16 FitYMul;
1011 : sal_uInt16 FitYDiv;
1012 : sal_Bool Fehler;
1013 0 : UCHAR* Buf=Buffer; // Zeiger auf die Buchstaben
1014 :
1015 0 : pSgfFonts->ReadList();
1016 0 : xLine=new short[ChrXPosArrSize];
1017 0 : cLine=new UCHAR[CharLineSize];
1018 :
1019 0 : TextFit=(Flags & TextFitBits)!=0;
1020 0 : LineFit=sal_False;
1021 0 : LineFit=((Flags & TextFitZBit)!=0);
1022 0 : if (TextFit && FitSize.x==0) LineFit=sal_True;
1023 :
1024 0 : if (DrehWink==0) {
1025 0 : sn=0.0;
1026 0 : cs=1.0;
1027 : } else {
1028 0 : sn=sin(double(DrehWink)*3.14159265359/18000);
1029 0 : cs=cos(double(DrehWink)*3.14159265359/18000);
1030 : }
1031 :
1032 0 : T1=T; Index1=0; yPos=0; xPos=0;
1033 0 : if (TextFit) {
1034 0 : ySize=Pos2.y-Pos1.y;
1035 0 : xSize=32000 /2; // Umbruch
1036 0 : xSAdj=Pos2.x-Pos1.x; // zum Ausrichten bei Zentriert/Blocksatz
1037 : //if (xSize<=0) { xSize=32000 /2; LineFit=sal_True; }
1038 0 : FitXMul=sal::static_int_cast< sal_uInt16 >(abs(Pos2.x-Pos1.x)); FitXDiv=FitSize.x; if (FitXDiv==0) FitXDiv=1;
1039 0 : FitYMul=sal::static_int_cast< sal_uInt16 >(abs(Pos2.y-Pos1.y)); FitYDiv=FitSize.y; if (FitYDiv==0) FitYDiv=1;
1040 : } else {
1041 0 : xSize=Pos2.x-Pos1.x;
1042 0 : xSAdj=xSize;
1043 0 : ySize=Pos2.y-Pos1.y;
1044 0 : FitXMul=1; FitXDiv=1;
1045 0 : FitYMul=1; FitYDiv=1;
1046 : }
1047 0 : if (xSize<0) xSize=0;
1048 0 : if (xSAdj<0) xSAdj=0;
1049 :
1050 0 : do {
1051 0 : T2=T1; Index2=Index1;
1052 0 : FormatLine(Buf,Index2,T,T2,xSize,xSAdj,xLine,l,sn,cs,cLine,LineFit);
1053 0 : Fehler=(Index2==Index1);
1054 0 : if (!Fehler) {
1055 0 : lc=GetLineFeed(Buf,Index1,T,T1,l,LF,MaxGrad);
1056 0 : if (TextFit) {
1057 0 : if (LineFit) FitXDiv=xLine[lc+1];
1058 0 : if (FitXDiv>0) {
1059 : long Temp;
1060 0 : for (i=1;i<=l+1;i++) {
1061 0 : Temp=long(xLine[i])*long(FitXMul) /long(FitXDiv);
1062 0 : xLine[i]=short(Temp);
1063 : }
1064 0 : LF=MulDiv(LF,FitYMul,FitYDiv);
1065 0 : MaxGrad=MulDiv(MaxGrad,FitYMul,FitYDiv);
1066 : } else {
1067 0 : FitXDiv=1; // 0 gibts nicht
1068 : }
1069 : }
1070 0 : yPos0=yPos;
1071 0 : TopToBase=GetTopToBaseLine(MaxGrad);
1072 0 : yPos=yPos+TopToBase;
1073 0 : Ende=(yPos0+short(MulDiv(MaxGrad,CharTopToBtm,100))>ySize) && !TextFit;
1074 0 : if (!Ende) {
1075 0 : T2=T1; Index2=Index1;
1076 0 : i=1;
1077 0 : while (i<=l) {
1078 0 : c=GetTextCharConv(Buf,Index2,T,T2,l-i,sal_False);
1079 : long xp1,yp1; // wegen Overflowgefahr
1080 : PointType Pos;
1081 0 : xp1=long(Pos1.x)+xPos+long(xLine[i]);
1082 0 : yp1=long(Pos1.y)+yPos;
1083 0 : if (xp1>32000) xp1=32000; if (xp1<-12000) xp1=-12000;
1084 0 : if (yp1>32000) yp1=32000; if (yp1<-12000) yp1=-12000;
1085 0 : Pos.x=short(xp1);
1086 0 : Pos.y=short(yp1);
1087 :
1088 0 : if (DrehWink!=0) RotatePoint(Pos,Pos1.x,Pos1.y,sn,cs);
1089 0 : DrawChar(rOut,c,T2,Pos,DrehWink,FitXMul,FitXDiv,FitYMul,FitYDiv);
1090 0 : i++;
1091 : } // while i<=l
1092 0 : yPos=yPos0+LF;
1093 0 : T1=T2; Index1=Index2; // Fuer die naechste Zeile
1094 : } // if ObjMin.y+yPos<=Obj_Max.y
1095 : } // if !Fehler
1096 : } while (c!=TextEnd && !Ende && !Fehler);
1097 0 : delete[] cLine;
1098 0 : delete[] xLine;
1099 : }
1100 :
1101 : // End of DrawText.Pas
1102 : /////////////////////////////////////////////////////////////////////////////////
1103 : /////////////////////////////////////////////////////////////////////////////////
1104 : /////////////////////////////////////////////////////////////////////////////////
1105 :
1106 : // nicht mehr benoetigt, da der Pointer nun extra gefuehrt wird
1107 : // (DEC Alpha hat naemlich 64Bit-Pointer!)
1108 : //UCHAR* TextType::GetBufPtr()
1109 : //{
1110 : // sal_uLong Temp;
1111 : // Temp=sal_uLong(BufLo)+0x00010000*sal_uLong(BufHi);
1112 : // return (UCHAR*)Temp;
1113 : //}
1114 : //
1115 : //void TextType::SetBufPtr(UCHAR* Ptr)
1116 : //{
1117 : // sal_uLong Temp=(sal_uLong)Ptr;
1118 : // BufLo=sal_uInt16(Temp & 0x0000FFFF);
1119 : // BufHi=sal_uInt16((Temp & 0xFFFF0000)>>16);
1120 : //}
1121 :
1122 0 : sal_uInt32 ObjTextType::GetFont()
1123 : {
1124 0 : return sal_uLong(FontLo)+0x00010000*sal_uLong(FontHi);
1125 : }
1126 :
1127 0 : void ObjTextType::SetFont(sal_uInt32 FontID)
1128 : {
1129 0 : FontLo=sal_uInt16(FontID & 0x0000FFFF);
1130 0 : FontHi=sal_uInt16((FontID & 0xFFFF0000)>>16);
1131 0 : }
1132 :
1133 :
1134 : /////////////////////////////////////////////////////////////////////////////////
1135 : // SGF.Ini lesen ////////////////////////////////////////////////////////////////
1136 : /////////////////////////////////////////////////////////////////////////////////
1137 0 : SgfFontOne::SgfFontOne()
1138 : {
1139 0 : Next=NULL;
1140 0 : IFID=0;
1141 0 : Bold=sal_False;
1142 0 : Ital=sal_False;
1143 0 : Sans=sal_False;
1144 0 : Serf=sal_False;
1145 0 : Fixd=sal_False;
1146 0 : SVFamil=FAMILY_DONTKNOW;
1147 0 : SVChSet=RTL_TEXTENCODING_DONTKNOW;
1148 0 : SVWidth=40;
1149 0 : }
1150 :
1151 0 : void SgfFontOne::ReadOne( const rtl::OString& rID, rtl::OString& Dsc )
1152 : {
1153 0 : if ( Dsc.getLength() < 4 || ( Dsc[0] != '(' ) )
1154 0 : return;
1155 0 : sal_Int32 i=1; // Erster Buchstabe des IF-Fontnamen. Davor ist eine '('
1156 0 : while ( i < Dsc.getLength() && ( Dsc[i] !=')' ) )
1157 0 : i++;
1158 0 : Dsc = Dsc.copy(i+1); // IF-Fontname loeschen inkl. ()
1159 :
1160 0 : if ( Dsc.getLength() < 2 || ( Dsc[Dsc.getLength() - 1] !=')' ) )
1161 0 : return;
1162 0 : i=Dsc.getLength()-2; // hier ist die ')' des SV-Fontnames
1163 0 : sal_Int32 j=0;
1164 0 : while ( i > 0 && ( Dsc[i] != '(' ) )
1165 : {
1166 0 : i--;
1167 0 : j++;
1168 : }
1169 0 : SVFName = rtl::OStringToOUString(Dsc.copy(i+1,j), RTL_TEXTENCODING_IBM_437); // SV-Fontname rausholen
1170 0 : Dsc = rtl::OStringBuffer(Dsc).remove(i,j).makeStringAndClear();
1171 :
1172 0 : IFID = (sal_uInt32)rID.toInt32();
1173 0 : sal_Int32 nTokenCount = comphelper::string::getTokenCount(Dsc, ' ');
1174 0 : for (sal_Int32 nIdx = 0; nIdx < nTokenCount; ++nIdx)
1175 : {
1176 0 : rtl::OString s(Dsc.getToken(nIdx, ' '));
1177 0 : if (!s.isEmpty())
1178 : {
1179 0 : s = s.toAsciiUpperCase();
1180 0 : if (s.matchL(RTL_CONSTASCII_STRINGPARAM("BOLD"))) Bold=sal_True;
1181 0 : else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("ITAL"))) Ital=sal_True;
1182 0 : else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("SERF"))) Serf=sal_True;
1183 0 : else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("SANS"))) Sans=sal_True;
1184 0 : else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("FIXD"))) Fixd=sal_True;
1185 0 : else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("ROMAN"))) SVFamil=FAMILY_ROMAN;
1186 0 : else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("SWISS"))) SVFamil=FAMILY_SWISS;
1187 0 : else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("MODERN"))) SVFamil=FAMILY_MODERN;
1188 0 : else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("SCRIPT"))) SVFamil=FAMILY_SCRIPT;
1189 0 : else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("DECORA"))) SVFamil=FAMILY_DECORATIVE;
1190 0 : else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("ANSI"))) SVChSet=RTL_TEXTENCODING_MS_1252;
1191 0 : else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("IBMPC"))) SVChSet=RTL_TEXTENCODING_IBM_850;
1192 0 : else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("MAC"))) SVChSet=RTL_TEXTENCODING_APPLE_ROMAN;
1193 0 : else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("SYMBOL"))) SVChSet=RTL_TEXTENCODING_SYMBOL;
1194 0 : else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("SYSTEM"))) SVChSet = osl_getThreadTextEncoding();
1195 0 : else if (comphelper::string::isdigitAsciiString(s) ) SVWidth=sal::static_int_cast< sal_uInt16 >(s.toInt32());
1196 : }
1197 0 : }
1198 : }
1199 :
1200 : /////////////////////////////////////////////////////////////////////////////////
1201 :
1202 2 : SgfFontLst::SgfFontLst()
1203 : {
1204 2 : pList=NULL;
1205 2 : Last=NULL;
1206 2 : LastID=0;
1207 2 : LastLn=NULL;
1208 2 : Tried=sal_False;
1209 2 : }
1210 :
1211 4 : SgfFontLst::~SgfFontLst()
1212 : {
1213 2 : RausList();
1214 2 : }
1215 :
1216 2 : void SgfFontLst::RausList()
1217 : {
1218 : SgfFontOne* P;
1219 : SgfFontOne* P1;
1220 2 : P=pList;
1221 4 : while (P!=NULL) {
1222 0 : P1=P->Next;
1223 0 : delete P;
1224 0 : P=P1;
1225 : }
1226 2 : pList=NULL;
1227 2 : Last=NULL;
1228 2 : Tried=sal_False;
1229 2 : LastID=0;
1230 2 : LastLn=NULL;
1231 2 : }
1232 :
1233 2 : void SgfFontLst::AssignFN(const String& rFName)
1234 2 : { FNam=rFName; }
1235 :
1236 0 : void SgfFontLst::ReadList()
1237 : {
1238 0 : if (!Tried)
1239 : {
1240 0 : Tried=sal_True;
1241 0 : LastID=0;
1242 0 : LastLn=NULL;
1243 0 : SgfFontOne* P,P1;
1244 0 : Config aCfg(FNam);
1245 0 : aCfg.SetGroup("SGV Fonts fuer StarView");
1246 0 : sal_uInt16 Anz=aCfg.GetKeyCount();
1247 : sal_uInt16 i;
1248 0 : rtl::OString FID;
1249 0 : rtl::OString Dsc;
1250 :
1251 0 : for (i=0;i<Anz;i++)
1252 : {
1253 0 : FID = comphelper::string::remove(aCfg.GetKeyName(i), ' ');
1254 0 : Dsc = aCfg.ReadKey( i );
1255 0 : if (comphelper::string::isdigitAsciiString(FID))
1256 : {
1257 0 : P=new SgfFontOne; // neuer Eintrag
1258 0 : if (Last!=NULL) Last->Next=P; else pList=P; Last=P; // einklinken
1259 0 : P->ReadOne(FID,Dsc); // und Zeile interpretieren
1260 : }
1261 0 : }
1262 : }
1263 0 : }
1264 :
1265 0 : SgfFontOne* SgfFontLst::GetFontDesc(sal_uInt32 ID)
1266 : {
1267 0 : if (ID!=LastID) {
1268 : SgfFontOne* P;
1269 0 : P=pList;
1270 0 : while (P!=NULL && P->IFID!=ID) P=P->Next;
1271 0 : LastID=ID;
1272 0 : LastLn=P;
1273 : }
1274 0 : return LastLn;
1275 : }
1276 :
1277 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|