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