fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / vcl / source / filter / sgvtext.cxx
blobe4a5f4429c59d07f3a26e0b4cc55c62986543c64
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "sal/config.h"
22 #include <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"
31 extern SgfFontLst* pSgfFonts;
33 #ifndef abs
34 #define abs(x) ((x)<0 ? -(x) : (x))
35 #endif
38 ////////////////////////////////////////////////////////////////////////////////////////////////////
40 // Einschraenkungen: Schatten nur grau, 2D und mit fixem Abstand.
45 ////////////////////////////////////////////////////////////////////////////////////////////////////
47 /////////////////////////////////////////////////////////////////////////////////
48 /////////////////////////////////////////////////////////////////////////////////
49 /////////////////////////////////////////////////////////////////////////////////
50 // AbsBase.Pas
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)
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:
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)*/
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 */
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 */
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% */
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 */
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 */
129 #define MaxLineChars 1024
131 #define ChrXPosArrSize (MaxLineChars+1+1) /* 2k - Beginnt mit 0 im gegensatz zu StarDraw */
132 #define CharLineSize (MaxLineChars+1+1)
134 #define MinChar 32
135 #define MaxChar 255
138 //==============================================================================
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%
144 // end of AbsBase.Pas
145 /////////////////////////////////////////////////////////////////////////////////
146 /////////////////////////////////////////////////////////////////////////////////
147 /////////////////////////////////////////////////////////////////////////////////
151 /////////////////////////////////////////////////////////////////////////////////
152 /////////////////////////////////////////////////////////////////////////////////
153 /////////////////////////////////////////////////////////////////////////////////
154 // DefBase.Pas
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 */
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 */
178 #define MaxCharSlant 4200 /* Maximal 42deg kursiv ! */
180 // end of DefBase.Pas
181 /////////////////////////////////////////////////////////////////////////////////
182 /////////////////////////////////////////////////////////////////////////////////
183 /////////////////////////////////////////////////////////////////////////////////
186 sal_Bool CheckTextOutl(ObjAreaType& F, ObjLineType& L);
188 sal_Bool CheckTextOutl(ObjAreaType& F, ObjLineType& L)
190 return (F.FIntens!=L.LIntens) ||
191 ((F.FFarbe!=L.LFarbe) && (F.FIntens>0)) ||
192 ((F.FBFarbe!=L.LBFarbe) && (F.FIntens<100));
196 /////////////////////////////////////////////////////////////////////////////////
197 /////////////////////////////////////////////////////////////////////////////////
198 /////////////////////////////////////////////////////////////////////////////////
199 // Misc.Pas
201 short hPoint2Sgf(short a)
203 long b;
204 b=long(a)*127*SgfDpmm/(144*5);
205 return short(b);
208 // End of Misc.Pas
209 // AbsRead.Pas
211 // ======================================================================
212 // Function GetTopToBaseLine() Function GetBaseLineToBtm()
214 // Abstand von Zeilenoberkante bis BaseLine bzw. von BaseLine bis
215 // Unterkante berechnen. Alles in SGF-Units.
216 // ======================================================================
218 sal_uInt16 GetTopToBaseLine(sal_uInt16 MaxGrad)
220 long ret;
221 ret=long(MaxGrad)*long(CharTopToBase) /long(100);
222 return sal_uInt16(ret);
225 // ======================================================================
226 // Function GetTextChar() Function GetTextCharConv()
228 // Liest ein Zeichen aus dem Textbuffer, wertet dabei eventuell
229 // auftretende Escapesequenzen aus und setzt dementsprechend den
230 // Ein-/Ausgabeparameter AktAtr. Index wird entsprechend erhoeht.
231 // Der Parameter Rest muss immer die Anzahl der Zeichen beinhalten,
232 // den angeforderten Zeichen in der aktuellen Zeile noch folgen.
233 // Ansonsten funktioniert die Silbentrennung nicht richtig. Gibt man
234 // stattdessen die Konstante NoTrenn an, wird in keinem Fall
235 // getrennt, die Konstante DoTrenn bewirkt dagegen, dass ueberall dort
236 // getrennt wird, wo ein SoftTrenner vorkommt.
238 // SoftTrenner werden immer in ein Minuszeichen konvertiert.
239 // GetTextCharConv() konvertiert zusaetzlich HardSpace und AbsatzEnde
240 // in Spaces sowie HardTrenner in Minuszeichen. TextEnde wird immer
241 // als Char(0) geliefert.
242 // ======================================================================
246 UCHAR ConvertTextChar(UCHAR c)
248 if (c<32) {
249 switch (c) {
250 case HardSpace : c=' '; break;
251 case AbsatzEnd : c=' '; break;
252 case SoftTrenn : c='-'; break;
253 case HardTrenn : c='-'; break;
254 case SoftTrennK : c='-'; break;
255 case SoftTrennAdd: c='-';
258 return c;
261 long ChgValue(long Def, long Min, long Max, UCHAR FlgVal, long NumVal)
263 long r=0;
265 if (FlgVal==EscDeflt) {
266 r=Def; // zurueck auf Default
267 } else {
268 if (NumVal!=EscNoVal) r=NumVal; // Hart setzen
271 if (Min!=0 || Max!=0) {
272 if (r>Max) r=Max;
273 if (r<Min) r=Min;
275 return r;
280 void ChgSchnittBit(sal_uInt16 Bit, sal_uInt16 Radio1, sal_uInt16 Radio2, sal_uInt16 Radio3,
281 UCHAR FlgVal, sal_uInt16 Schnitt0, sal_uInt16& Schnitt)
283 sal_uInt16 All,Rad;
285 Rad=Radio1 | Radio2 | Radio3;
286 All=Bit | Rad;
288 switch (FlgVal) {
289 case EscSet : Schnitt=(Schnitt & ~All) | Bit; break;
290 case EscReset: Schnitt=(Schnitt & ~All); break;
291 case EscDeflt: Schnitt=(Schnitt & ~All) | (Schnitt0 & All); break;
292 case EscToggl: Schnitt=(Schnitt & ~Rad) ^ Bit;
298 UCHAR GetNextChar(UCHAR* TBuf, sal_uInt16 Index)
300 sal_uInt16 Cnt;
301 while (TBuf[Index]==Escape) {
302 Index++;
303 Cnt=0;
304 while (TBuf[Index]!=Escape && Cnt<=MaxEscLen) {
305 Index++; Cnt++; }
306 Index++;
308 return TBuf[Index];
313 UCHAR ProcessOne(UCHAR* TBuf, sal_uInt16& Index,
314 ObjTextType& Atr0, ObjTextType& AktAtr,
315 sal_Bool ScanEsc)
317 UCHAR c;
318 UCHAR Ident;
319 sal_Bool Ende;
320 sal_Bool q;
321 UCHAR FlgVal;
322 long NumVal;
323 long Sgn;
324 short i;
325 sal_Bool EoVal;
327 do {
328 c=TBuf[Index]; Index++;
329 Ende=(c!=Escape);
330 if (Ende==sal_False) {
331 c=TBuf[Index]; Index++;
332 Ident=c; // Identifer merken
333 FlgVal=EscNoFlg;
334 NumVal=EscNoVal;
335 c=TBuf[Index]; Index++; // Hier faengt der Wert an
336 if (c==EscSet || c==EscReset || c==EscDeflt || c==EscToggl) FlgVal=c; else {
337 if (c=='-') Sgn=-1; else Sgn=1;
338 if (c=='+' || c=='-') { c=TBuf[Index]; Index++; }
339 i=MaxEscValLen;
340 NumVal=0;
341 do {
342 NumVal=10*NumVal+c-'0';
343 EoVal=(TBuf[Index]<'0' || TBuf[Index]>'9');
344 if (EoVal==sal_False) { c=TBuf[Index]; Index++; }
345 i--;
346 } while (i>0 && EoVal==sal_False);
347 NumVal=Sgn*NumVal;
349 q=!CheckTextOutl(AktAtr.F,AktAtr.L);
351 switch (Ident) {
352 case EscFont : AktAtr.SetFont(sal_uLong (ChgValue(Atr0.GetFont(),0,0 ,FlgVal,NumVal)));break;
353 case EscGrad : AktAtr.Grad =sal_uInt16(ChgValue(Atr0.Grad, 2,2000 ,FlgVal,NumVal)); break;
354 case EscBreit: AktAtr.Breite =sal_uInt16(ChgValue(Atr0.Breite, 1,1000 ,FlgVal,NumVal)); break;
355 case EscKaptS: AktAtr.Kapit =(sal_uInt8)(ChgValue(Atr0.Kapit, 1,255 ,FlgVal,NumVal)); break;
356 case EscLFeed: AktAtr.LnFeed =sal_uInt16(ChgValue(Atr0.LnFeed, 1,65535 ,FlgVal,NumVal)); break;
357 case EscSlant: AktAtr.Slant =sal_uInt16(ChgValue(Atr0.Slant, 1,MaxCharSlant ,FlgVal,NumVal)); break;
358 case EscVPos : AktAtr.ChrVPos=char (ChgValue(Atr0.ChrVPos,-128,127 ,FlgVal,NumVal)); break;
359 case EscZAbst: AktAtr.ZAbst =(sal_uInt8)(ChgValue(Atr0.ZAbst, 1,255 ,FlgVal,NumVal)); break;
360 case EscHJust: AktAtr.Justify=(sal_uInt8)(ChgValue(Atr0.Justify & 0x0F,0,5 ,FlgVal,NumVal)); break;
361 case EscFarbe: { AktAtr.L.LFarbe =(sal_uInt8)(ChgValue(Atr0.L.LFarbe,0,7 ,FlgVal,NumVal)); if (q) AktAtr.F.FFarbe =AktAtr.L.LFarbe; } break;
362 case EscBFarb: { AktAtr.L.LBFarbe=(sal_uInt8)(ChgValue(Atr0.L.LBFarbe,0,255,FlgVal,NumVal)); if (q) AktAtr.F.FBFarbe=AktAtr.L.LBFarbe; } break;
363 case EscInts : { AktAtr.L.LIntens=(sal_uInt8)(ChgValue(Atr0.L.LIntens,0,100,FlgVal,NumVal)); if (q) AktAtr.F.FIntens=AktAtr.L.LIntens; } break;
365 case EscMustr: { AktAtr.F.FMuster=sal_uInt16(ChgValue(Atr0.F.FMuster,0,65535,FlgVal,NumVal)); } break;
366 case EscMFarb: { AktAtr.F.FFarbe =(sal_uInt8)(ChgValue(Atr0.F.FFarbe,0,7 ,FlgVal,NumVal)); } break;
367 case EscMBFrb: { AktAtr.F.FBFarbe=(sal_uInt8)(ChgValue(Atr0.F.FBFarbe,0,255,FlgVal,NumVal)); } break;
368 case EscMInts: { AktAtr.F.FIntens=(sal_uInt8)(ChgValue(Atr0.F.FIntens,0,100,FlgVal,NumVal)); } break;
370 case EscSMstr: { AktAtr.ShdF.FMuster=sal_uInt16(ChgValue(Atr0.ShdF.FMuster,0,65535,FlgVal,NumVal)); } break;
371 case EscSFarb: { AktAtr.ShdL.LFarbe =(sal_uInt8)(ChgValue(Atr0.ShdL.LFarbe,0,7 ,FlgVal,NumVal)); AktAtr.ShdF.FFarbe =AktAtr.ShdL.LFarbe; } break;
372 case EscSBFrb: { AktAtr.ShdL.LBFarbe=(sal_uInt8)(ChgValue(Atr0.ShdL.LBFarbe,0,255,FlgVal,NumVal)); AktAtr.ShdF.FBFarbe=AktAtr.ShdL.LBFarbe; } break;
373 case EscSInts: { AktAtr.ShdL.LIntens=(sal_uInt8)(ChgValue(Atr0.ShdL.LIntens,0,100,FlgVal,NumVal)); AktAtr.ShdF.FIntens=AktAtr.ShdL.LIntens; } break;
374 case EscSDist: { AktAtr.ShdVers.x=(short)ChgValue(Atr0.ShdVers.x,0,30000,FlgVal,NumVal); AktAtr.ShdVers.y=AktAtr.ShdVers.x; } break;
375 case EscSXDst: { AktAtr.ShdVers.x=(short)ChgValue(Atr0.ShdVers.x,0,30000,FlgVal,NumVal); } break;
376 case EscSYDst: { AktAtr.ShdVers.y=(short)ChgValue(Atr0.ShdVers.y,0,30000,FlgVal,NumVal); } break;
378 case EscBold : ChgSchnittBit(TextBoldBit,0,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
379 case EscRSlnt: ChgSchnittBit(TextRSlnBit,TextLSlnBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
380 case EscUndln: ChgSchnittBit(TextUndlBit,TextDbUnBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
381 case EscStrik: ChgSchnittBit(TextStrkBit,TextDbStBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
382 case EscDbUnd: ChgSchnittBit(TextDbUnBit,TextUndlBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
383 case EscDbStk: ChgSchnittBit(TextDbStBit,TextStrkBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
384 case EscSupSc: ChgSchnittBit(TextSupSBit,TextSubSBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
385 case EscSubSc: ChgSchnittBit(TextSubSBit,TextSupSBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
386 case EscKaptF: ChgSchnittBit(TextKaptBit,0,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
387 case EscLSlnt: ChgSchnittBit(TextLSlnBit,TextRSlnBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
388 case Esc2DShd: ChgSchnittBit(TextSh2DBit,TextSh3DBit,TextSh4DBit,TextShEbBit,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
389 case Esc3DShd: ChgSchnittBit(TextSh3DBit,TextSh2DBit,TextSh4DBit,TextShEbBit,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
390 case Esc4DShd: ChgSchnittBit(TextSh4DBit,TextSh2DBit,TextSh3DBit,TextShEbBit,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
391 case EscEbShd: ChgSchnittBit(TextShEbBit,TextSh2DBit,TextSh3DBit,TextSh4DBit,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
392 } //endcase
393 if (TBuf[Index]==Escape) Index++; // zweites Esc weglesen }
394 } // if Ende==sal_False
395 } while (Ende==sal_False && ScanEsc==sal_False);
396 if (Ende==sal_False) c=Escape;
397 return c;
398 } // end of ProcessOne
401 UCHAR GetTextChar(UCHAR* TBuf, sal_uInt16& Index,
402 ObjTextType& Atr0, ObjTextType& AktAtr,
403 sal_uInt16 Rest, sal_Bool ScanEsc)
405 UCHAR c,c0,nc;
407 c=ProcessOne(TBuf,Index,Atr0,AktAtr,ScanEsc);
408 if (ScanEsc==sal_False) {
409 if (c==SoftTrennAdd || c==SoftTrennK || c==SoftTrenn) {
410 nc=GetNextChar(TBuf,Index);
411 c0=c;
412 if (Rest==0 || Rest==DoTrenn ||
413 nc==' ' || nc==AbsatzEnd || nc==TextEnd) c='-';
414 else {
415 c=ProcessOne(TBuf,Index,Atr0,AktAtr,ScanEsc); // den Trenner ueberspringen
416 if (c0==SoftTrennAdd) {
417 if (c>=32) c=ProcessOne(TBuf,Index,Atr0,AktAtr,ScanEsc); // und hier noch 'nen Buchstaben ueberspringen
421 if ((Rest==1 || Rest==DoTrenn) && GetNextChar(TBuf,Index)==SoftTrennK) {
422 if (c=='c') c='k';
423 else if (c=='C') c='K';
426 return c;
429 // HardSpace und HardTrenn muessen explizit konvertiert werden ! }
430 // if AktAtr.Schnitt and TextKaptBit =TextKaptBit then c:=UpCase(c);(explizit) }
432 // Bei der Trennmethode SoftTrennAdd wird davon ausgegangen, dass der zu }
433 // trennende Konsonant bereits 3x mal im TextBuf vorhanden ist, z.b.: }
434 // "Schiff-fahrt". Wenn nicht getrennt, dann wird "-f" entfernt. }
438 UCHAR GetTextCharConv(UCHAR* TBuf, sal_uInt16& Index,
439 ObjTextType& Atr0, ObjTextType& AktAtr,
440 sal_uInt16 Rest, sal_Bool ScanEsc)
442 UCHAR c;
444 c=GetTextChar(TBuf,Index,Atr0,AktAtr,Rest,ScanEsc);
445 if (c<32) {
446 switch (c) {
447 case HardSpace : c=' '; break;
448 case AbsatzEnd : c=' '; break;
449 case HardTrenn : c='-';
452 return c;
456 // ======================================================================
457 // Function GetLineFeed()
459 // Benoetigter Zeilenabstand in SGF-Units. ChrVPos wird beruecksichtigt.
460 // ======================================================================
461 sal_uInt16 GetLineFeed(UCHAR* TBuf, sal_uInt16 Index, ObjTextType Atr0, ObjTextType AktAtr,
462 sal_uInt16 nChar, sal_uInt16& LF, sal_uInt16& MaxGrad)
464 UCHAR c=0;
465 sal_Bool AbsEnd=sal_False;
466 sal_uLong LF100=0;
467 sal_uLong MaxLF100=0;
468 sal_Bool LFauto=0;
469 sal_Bool First=sal_True;
470 sal_uInt16 Grad;
471 sal_uInt16 i=0;
472 sal_uInt16 r=1;
474 MaxGrad=0;
475 while (!AbsEnd && nChar>0) {
476 nChar--;
477 c=GetTextChar(TBuf,Index,Atr0,AktAtr,nChar,sal_False);
478 i++;
479 AbsEnd=(c==TextEnd || c==AbsatzEnd);
480 if (First || (!AbsEnd && c!=' ' && c!=HardTrenn)) {
481 LFauto=(AktAtr.LnFeed & 0x8000)==0;
482 LF100=AktAtr.LnFeed & 0x7FFF;
483 if (LFauto) LF100=LF100*AktAtr.Grad; else LF100*=LF100;
484 if (AktAtr.ChrVPos>0) LF100-=AktAtr.ChrVPos*100;
485 if (LF100>MaxLF100) MaxLF100=LF100;
486 Grad=AktAtr.Grad;
487 if (AktAtr.ChrVPos>0) Grad=Grad-AktAtr.ChrVPos;
488 if (Grad>MaxGrad) MaxGrad=Grad;
489 First=sal_False;
491 if (!AbsEnd && c!=' ') r=i;
493 MaxGrad=hPoint2Sgf(MaxGrad);
494 if (MaxLF100<=4000) { // sonst Overflowgefahr
495 LF=sal_uInt16(hPoint2Sgf(short(MaxLF100)) /100);
496 } else {
497 LF=sal_uInt16(hPoint2Sgf(short(MaxLF100) /100));
500 return r;
503 // End of AbsRead.Pas
504 /////////////////////////////////////////////////////////////////////////////////
505 /////////////////////////////////////////////////////////////////////////////////
506 /////////////////////////////////////////////////////////////////////////////////
510 /////////////////////////////////////////////////////////////////////////////////
511 /////////////////////////////////////////////////////////////////////////////////
512 /////////////////////////////////////////////////////////////////////////////////
513 // iFont.Pas
515 #define SuperSubFact 60 /* SuperScript/SubScript: 60% vom Schriftgrad */
516 #define DefaultSpace 40 /* Default: Space ist 40% vom SchriftGrad */
518 sal_uInt16 SetTextContext(OutputDevice& rOut, ObjTextType& Atr, sal_Bool Kapt, sal_uInt16 Dreh,
519 sal_uInt16 FitXMul, sal_uInt16 FitXDiv, sal_uInt16 FitYMul, sal_uInt16 FitYDiv)
521 SgfFontOne* pSgfFont; // Font aus dem IniFile
522 Font aFont;
523 Color aColor;
524 sal_uLong Grad;
525 sal_uLong Brei;
526 String FNam;
527 sal_uInt16 StdBrei=50; // Durchschnittliche Zeichenbreite in % von Schriftgrad
528 sal_Bool bFit=(FitXMul!=1 || FitXDiv!=1 || FitYMul!=1 || FitYDiv!=1);
530 pSgfFont = pSgfFonts->GetFontDesc(Atr.GetFont());
532 if ( pSgfFont!=NULL )
534 FNam =pSgfFont->SVFName;
535 StdBrei=pSgfFont->SVWidth;
536 if (pSgfFont->Fixd) aFont.SetPitch(PITCH_FIXED); else aFont.SetPitch(PITCH_VARIABLE);
537 aFont.SetFamily(pSgfFont->SVFamil);
538 aFont.SetCharSet(pSgfFont->SVChSet);
539 aFont.SetName(FNam);
541 else
542 { // Falls nich im Inifile, sind hier einige Fonts hart kodiert
543 aFont.SetPitch(PITCH_VARIABLE);
544 switch (Atr.GetFont()) {
545 case 92500: case 92501: case 92504: case 92505:
547 #if defined(WNT)
548 FNam=OUString("Times New Roman"); // CG Times ist unter Windows Times New Roman
549 #else
550 FNam=OUString("Times"); // ansonsten ist das einfach Times
551 #endif
552 StdBrei=40;
553 aFont.SetFamily(FAMILY_ROMAN);
554 } break;
555 case 94021: case 94022: case 94023: case 94024: {
556 #if defined(WNT)
557 FNam=OUString("Arial"); // Univers ist unter Windows Arial
558 #else
559 FNam=OUString("Helvetica"); // und ansonsten Helvetica
560 #endif
561 aFont.SetFamily(FAMILY_SWISS);
562 StdBrei=47;
563 } break;
564 case 93950: case 93951: case 93952: case 93953: {
565 #if defined(WNT)
566 FNam=OUString("Courier New"); // Der Vector-Courierfont unter Windows heisst Courier New
567 #else
568 FNam=OUString("Courier"); // ansonsten ist und bleibt Courier immer Courier
569 #endif
570 aFont.SetFamily(FAMILY_ROMAN);
571 aFont.SetPitch(PITCH_FIXED);
572 } break;
573 default: FNam = OUString("Helvetica");
575 aFont.SetName(FNam);
576 //aFont.SetCharSet(CHARSET_SYSTEM);
579 Grad=sal_uLong(Atr.Grad);
580 if ((Atr.Schnitt & TextKaptBit) !=0 && Kapt) Grad=Grad*sal_uLong(Atr.Kapit)/100;
581 if ((Atr.Schnitt & TextSupSBit) !=0 || (Atr.Schnitt & TextSubSBit) !=0) Grad=Grad*SuperSubFact/100;
582 Brei=Grad;
583 if (Atr.Breite!=100 || bFit) {
584 if (bFit) {
585 Grad=Grad*sal_uLong(FitYMul)/sal_uLong(FitYDiv);
586 Brei=Brei*sal_uLong(FitXMul)/sal_uLong(FitXDiv);
588 Brei=Brei*sal_uLong(Atr.Breite)/100;
589 Brei=Brei*sal_uLong(StdBrei)/100;
590 aFont.SetSize(Size(hPoint2Sgf(sal_uInt16(Brei)),hPoint2Sgf(sal_uInt16(Grad))));
591 } else {
592 aFont.SetSize(Size(0,hPoint2Sgf(sal_uInt16(Grad))));
595 aColor=Sgv2SvFarbe(Atr.L.LFarbe,Atr.L.LBFarbe,Atr.L.LIntens); aFont.SetColor(aColor);
596 aColor=Sgv2SvFarbe(Atr.F.FFarbe,Atr.F.FBFarbe,Atr.F.FIntens); aFont.SetFillColor(aColor);
597 aFont.SetTransparent(sal_True);
598 aFont.SetAlign(ALIGN_BASELINE);
600 Dreh/=10; Dreh=3600-Dreh; if (Dreh==3600) Dreh=0;
601 aFont.SetOrientation(Dreh);
603 if ((Atr.Schnitt & TextBoldBit) !=0) aFont.SetWeight(WEIGHT_BOLD);
604 if ((Atr.Schnitt & TextRSlnBit) !=0) aFont.SetItalic(ITALIC_NORMAL);
605 if ((Atr.Schnitt & TextUndlBit) !=0) aFont.SetUnderline(UNDERLINE_SINGLE);
606 if ((Atr.Schnitt & TextDbUnBit) !=0) aFont.SetUnderline(UNDERLINE_DOUBLE);
607 if ((Atr.Schnitt & TextStrkBit) !=0) aFont.SetStrikeout(STRIKEOUT_SINGLE);
608 if ((Atr.Schnitt & TextDbStBit) !=0) aFont.SetStrikeout(STRIKEOUT_DOUBLE);
609 if ((Atr.Schnitt & TextSh2DBit) !=0) aFont.SetShadow(sal_True);
610 if ((Atr.Schnitt & TextSh3DBit) !=0) aFont.SetShadow(sal_True);
611 if ((Atr.Schnitt & TextSh4DBit) !=0) aFont.SetShadow(sal_True);
612 if ((Atr.Schnitt & TextShEbBit) !=0) aFont.SetShadow(sal_True);
613 if (CheckTextOutl(Atr.F,Atr.L)) aFont.SetOutline(sal_True);
615 if (aFont!=rOut.GetFont()) rOut.SetFont(aFont);
617 return 0;
620 // iFont.Pas
621 /////////////////////////////////////////////////////////////////////////////////
622 /////////////////////////////////////////////////////////////////////////////////
623 /////////////////////////////////////////////////////////////////////////////////
626 /////////////////////////////////////////////////////////////////////////////////
627 /////////////////////////////////////////////////////////////////////////////////
628 /////////////////////////////////////////////////////////////////////////////////
629 // Absatz.Pas
631 struct ProcChrSta {
632 sal_uInt16 Index;
633 sal_uInt16 ChrXP;
634 UCHAR OutCh;
635 sal_Bool Kapt;
636 ObjTextType Attrib;
639 void InitProcessCharState(ProcChrSta& State, ObjTextType& AktAtr, sal_uInt16 IndexA)
641 State.Attrib=AktAtr;
642 State.OutCh=0;
643 State.Index=IndexA;
644 State.ChrXP=0;
645 State.Kapt=sal_False;
648 sal_Bool UpcasePossible(UCHAR c)
650 if ((c>='a' && c<='z') || c == 0xe4 || c == 0xf6 || c == 0xfc ) return sal_True;
651 else return sal_False;
654 UCHAR Upcase(UCHAR c)
656 if ((c>=(UCHAR)'a' && c<=(UCHAR)'z')) c=(c-(UCHAR)'a')+(UCHAR)'A';
657 else if ( c == 0xe4 ) c = 0xc4;
658 else if ( c == 0xf6 ) c = 0xd6;
659 else if ( c == 0xfc ) c = 0xdc;
660 return c;
663 sal_uInt16 GetCharWidth(OutputDevice& rOut, UCHAR c)
665 sal_uInt16 ChrWidth;
667 if (c==' ')
669 ChrWidth=(sal_uInt16)rOut.GetTextWidth( OUString('A') );
670 if (rOut.GetFont().GetPitch()!=PITCH_FIXED) {
671 ChrWidth=MulDiv(ChrWidth,DefaultSpace,100);
674 else
676 // with MaxChar == 255 c cannot be greater than MaxChar
677 // assert if MaxChar is ever changed
678 BOOST_STATIC_ASSERT( MaxChar == 255 );
679 BOOST_STATIC_ASSERT(sizeof(UCHAR) == 1);
680 if (c>=MinChar /*&& c<=MaxChar*/)
682 ChrWidth=(sal_uInt16)rOut.GetTextWidth(OUString(reinterpret_cast<sal_Char*>(&c), 1, RTL_TEXTENCODING_IBM_437));
684 else
686 ChrWidth=(sal_uInt16)rOut.GetTextWidth(OUString(static_cast<sal_Unicode>('A')));
689 return ChrWidth;
692 UCHAR ProcessChar(OutputDevice& rOut, UCHAR* TBuf, ProcChrSta& R, ObjTextType& Atr0,
693 sal_uInt16& nChars, sal_uInt16 Rest,
694 short* Line, UCHAR* cLine)
696 sal_uInt16 KernDist=0; // Wert fuer Kerning
697 sal_uInt16 ChrWidth;
698 UCHAR c;
699 UCHAR c1;
700 sal_Bool AbsEnd;
702 c=GetTextChar(TBuf,R.Index,Atr0,R.Attrib,Rest,sal_False); // versucht evtl. zu trennen, wenn Rest entsprechenden Wert besitzt
704 AbsEnd=(c==AbsatzEnd || c==TextEnd);
705 if (AbsEnd==sal_False) {
706 R.OutCh=ConvertTextChar(c); // von HardTrenn nach '-', ...
707 R.Kapt=(R.Attrib.Schnitt & TextKaptBit) !=0 && UpcasePossible(R.OutCh);
708 if (R.Kapt) R.OutCh=Upcase(R.OutCh);
709 SetTextContext(rOut,R.Attrib,R.Kapt,0,1,1,1,1);
711 if (R.Kapt) c1=Upcase(c); else c1=c;
712 ChrWidth=GetCharWidth(rOut,c1);
714 if (R.Attrib.ZAbst!=100) { // Spezial-Zeichenabstand ?
715 sal_uLong Temp;
716 Temp=sal_uLong(ChrWidth)*sal_uLong(R.Attrib.ZAbst)/100;
717 ChrWidth=sal_uInt16(Temp);
719 nChars++;
720 if (R.ChrXP>32000) R.ChrXP=32000;
721 Line[nChars]=R.ChrXP-KernDist;
722 cLine[nChars]=c;
723 R.ChrXP+=ChrWidth-KernDist; // Position fuer den naechsten Character
725 return c;
728 void FormatLine(UCHAR* TBuf, sal_uInt16& Index, ObjTextType& Atr0, ObjTextType& AktAtr,
729 sal_uInt16 UmbWdt, sal_uInt16 AdjWdt,
730 short* Line, sal_uInt16& nChars,
731 double, double,
732 UCHAR* cLine, sal_Bool TextFit)
734 VirtualDevice vOut;
735 UCHAR c,c0;
736 UCHAR ct;
737 sal_Bool First; // erster Char ?
738 sal_uInt8 Just = 0; // Absatzformatierung
739 sal_Bool Border; // Rand der Box erreicht ?
740 sal_Bool Border0;
741 sal_Bool AbsEnd; // Ende des Absatzes erreicht ?
742 ProcChrSta* R=new ProcChrSta;
743 ProcChrSta* R0=new ProcChrSta;
744 ProcChrSta* WErec=new ProcChrSta;
745 sal_uInt16 WEnChar;
746 ProcChrSta* WErec0=new ProcChrSta;
747 sal_uInt16 WEnChar0;
748 ProcChrSta* TRrec=new ProcChrSta;
749 sal_uInt16 TRnChar;
751 sal_uInt16 WordEndCnt; // Justieren und Trennen
752 sal_Bool WordEnd;
753 sal_Bool Trenn;
755 short BoxRest; // zum Quetschen und formatieren
756 sal_uInt16 i,j,k,h;
757 sal_uInt16 re,li;
759 vOut.SetMapMode(MapMode(MAP_10TH_MM,Point(),Fraction(1,4),Fraction(1,4)));
761 nChars=0;
762 SetTextContext(vOut,AktAtr,sal_False,0,1,1,1,1);
763 InitProcessCharState(*R,AktAtr,Index);
764 (*R0)=(*R); (*WErec)=(*R); WEnChar=0; c0=0; Border0=sal_False;
765 Border=sal_False; First=sal_True;
766 WordEndCnt=0;
768 do { // mal schauen, wieviele Worte so in die Zeile passen
769 if (Border) c=ProcessChar(vOut,TBuf,*R,Atr0,nChars,DoTrenn,Line,cLine);
770 else c=ProcessChar(vOut,TBuf,*R,Atr0,nChars,NoTrenn,Line,cLine);
771 AbsEnd=(c==AbsatzEnd || c==TextEnd);
772 //if not AbsEnd then
774 if (First) {
775 Just=R->Attrib.Justify & 0x0F; // Absatzformat steht wenn, dann am Anfang
777 Border=R->ChrXP>UmbWdt;
778 WordEnd=(AbsEnd || (c==' ')) && (c0!=' ') && (c0!=0);
779 Trenn=c=='-';
780 if (WordEnd && !Border0) {
781 WordEndCnt++;
782 (*WErec)=(*R0);
783 WEnChar=nChars-1;
785 if (Trenn && !Border) {
786 WordEndCnt++;
787 (*WErec)=(*R);
788 WEnChar=nChars;
791 (*R0)=(*R); c0=c;
792 Border0=Border;
793 First=sal_False;
794 AbsEnd=AbsEnd || (nChars>=MaxLineChars);
795 } while (!(AbsEnd || (Border && ((WordEndCnt>0) || WordEnd || Trenn))));
797 if (Border) { // Trennen und Quetschen
798 (*WErec0)=(*WErec); WEnChar0=WEnChar;
799 AbsEnd=sal_False; c0=0;
800 (*R)=(*WErec); nChars=WEnChar;
801 (*TRrec)=(*R); TRnChar=nChars;
802 Border0=sal_False; Border=sal_False;
803 do { // erst mal gucken wieviele Silben noch reinpassen
804 ct=ProcessChar(vOut,TBuf,*TRrec,Atr0,TRnChar,DoTrenn,Line,cLine);
805 c=ProcessChar(vOut,TBuf,*R,Atr0,nChars,NoTrenn,Line,cLine);
806 AbsEnd=(ct==AbsatzEnd) || (ct==TextEnd) || (nChars>=MaxLineChars);
808 Border=TRrec->ChrXP>UmbWdt;
809 WordEnd=AbsEnd || ((AbsEnd || (c==' ')) && (c0!=' ') && (c0!=0));
810 Trenn=ct=='-';
811 if (WordEnd && (!Border0 || (WordEndCnt==0))) {
812 WordEndCnt++;
813 (*WErec)=(*R0);
814 if (AbsEnd) WEnChar=nChars; else WEnChar=nChars-1;
815 (*TRrec)=(*R); TRnChar=nChars; // zum weitersuchen
817 if (Trenn && (!Border || (WordEndCnt==0))) {
818 WordEndCnt++; // merken, dass man hier trennen kann
819 (*WErec)=(*TRrec);
820 WEnChar=TRnChar;
821 (*TRrec)=(*R); TRnChar=nChars; // zum weitersuchen
823 (*R0)=(*R); c0=c;
824 Border0=Border;
825 Border=R->ChrXP>UmbWdt;
826 } while (!(AbsEnd || (Border && ((WordEndCnt>0) || WordEnd || Trenn))));
828 while (WErec0->Index<WErec->Index) { // damit Line[] auch garantiert stimmt }
829 c=ProcessChar(vOut,TBuf,*WErec0,Atr0,WEnChar0,WEnChar-WEnChar0-1,Line,cLine);
832 (*R)=(*WErec); nChars=WEnChar;
834 if (UmbWdt>=R->ChrXP) {
835 BoxRest=UmbWdt-R->ChrXP;
836 } else { // Zusammenquetschen
837 BoxRest=R->ChrXP-UmbWdt; // um soviel muss gequetscht werden
838 for (i=2;i<=nChars;i++) { // 1. CharPosition bleibt !
839 Line[i]-=(i-1)*(BoxRest) /(nChars-1);
841 R->ChrXP=UmbWdt;
842 Line[nChars+1]=UmbWdt;
846 if (!AbsEnd) {
847 do { // Leerzeichen weglesen
848 (*WErec)=(*R);
849 c=GetTextChar(TBuf,R->Index,Atr0,R->Attrib,NoTrenn,sal_False);
850 nChars++;
851 Line[nChars]=R->ChrXP;
852 cLine[nChars]=c;
853 } while (c==' ');
854 if (c!=' ' && c!=AbsatzEnd && c!=TextEnd) {
855 nChars--;
856 (*R)=(*WErec);
860 if (AbsEnd && nChars<MaxLineChars) { // Ausrichten, statt Blocksatz aber linksbuendig
861 if (Just==3) Just=0;
862 nChars++; Line[nChars]=R->ChrXP; // Damit AbsatzEnde auch weggelesen wird
863 Line[nChars+1]=R->ChrXP; // denn die Breite von CR oder #0 ist nun mal sehr klein
864 if (TBuf[R->Index-1]!=AbsatzEnd && TBuf[R->Index-1]!=TextEnd) {
865 c=GetTextChar(TBuf,R->Index,Atr0,R->Attrib,NoTrenn,sal_False); // Kleine Korrektur. Notig, wenn nur 1 Wort in
869 BoxRest=AdjWdt-R->ChrXP;
870 if (TextFit) Just=THJustLeft;
872 switch (Just) {
873 case THJustLeft: break; // Links
874 case THJustCenter: {
875 BoxRest=BoxRest /2; // Mitte
876 for (i=1;i<=nChars;i++) Line[i]=Line[i]+BoxRest;
877 } break;
878 case THJustRight: { // Rechts
879 for (i=1;i<=nChars;i++) Line[i]=Line[i]+BoxRest;
880 } break;
881 case THJustDrvOut:
882 case THJustBlock: { // Block und Austreibend
883 re=nChars;
884 if (Just==THJustDrvOut) re--;
885 while (re>=1 && (cLine[re]==' ' || cLine[re]==TextEnd || cLine[re]==AbsatzEnd)) re--;
886 li=1;
887 while (li<=re && (cLine[li]==' ' || cLine[li]==TextEnd || cLine[li]==AbsatzEnd)) li++;
888 if (Just==THJustDrvOut) BoxRest=AdjWdt-Line[re+1];
890 j=0; // Anzahl der Spaces ermitteln
891 for (i=li;i<=re;i++) {
892 if (cLine[i]==' ') {
893 j++;
897 if (j==0) { // nur 1 Wort ? -> Strecken !
898 for (i=li+1;i<=re;i++) { // von links nach rechts
899 Line[i]=Line[i]+MulDiv(i-li,BoxRest,re-li+1-1);
901 } else {
902 k=0; h=0;
903 for (i=li;i<=re;i++) { // j Spaces aufbohren !
904 if (cLine[i]==' ') { // Space gefunden !
905 k++;
906 h=MulDiv(k,BoxRest,j);
908 Line[i]=Line[i]+h;
911 for (i=re+1;i<=nChars;i++) Line[i]=Line[i]+BoxRest; // und den Rest anpassen
912 Line[nChars+1]=AdjWdt;
913 } break;
914 case THJustLocked: { //Gesperrt
915 re=nChars-1;
916 while (re>=1 && (cLine[re]==' ' || cLine[re]==TextEnd || cLine[re]==AbsatzEnd)) re--;
917 li=1;
918 while (li<=re && (cLine[li]==' ' || cLine[li]==TextEnd || cLine[li]==AbsatzEnd)) li++;
919 BoxRest=AdjWdt-Line[re+1];
920 for (i=li+1;i<=re;i++) { // Strecken von links nach rechts
921 Line[i]=Line[i]+MulDiv(i-li,BoxRest,re-li+1-1);
923 for (i=re+1;i<=nChars;i++) Line[i]=Line[i]+BoxRest; // und den Rest anpassen
924 Line[nChars+1]=AdjWdt;
925 } break;
927 Index=R->Index;
928 AktAtr=R->Attrib;
929 delete R;
930 delete R0;
931 delete WErec;
932 delete WErec0;
933 delete TRrec;
938 // End of Absatz.Pas
939 /////////////////////////////////////////////////////////////////////////////////
940 /////////////////////////////////////////////////////////////////////////////////
941 /////////////////////////////////////////////////////////////////////////////////
944 /////////////////////////////////////////////////////////////////////////////////
945 /////////////////////////////////////////////////////////////////////////////////
946 /////////////////////////////////////////////////////////////////////////////////
947 // DrawText.Pas
949 void DrawChar(OutputDevice& rOut, UCHAR c, ObjTextType T, PointType Pos, sal_uInt16 DrehWink,
950 sal_uInt16 FitXMul, sal_uInt16 FitXDiv, sal_uInt16 FitYMul, sal_uInt16 FitYDiv)
952 SetTextContext(rOut,T,UpcasePossible(c),DrehWink,FitXMul,FitXDiv,FitYMul,FitYDiv);
953 if ((T.Schnitt & TextKaptBit)!=0 && UpcasePossible(c)) c=Upcase(c);
954 OUString s(reinterpret_cast<const sal_Char*>(&c), 1,
955 RTL_TEXTENCODING_IBM_437);
956 rOut.DrawText( Point( Pos.x, Pos.y ), s );
959 /*************************************************************************
961 |* TextType::Draw()
963 *************************************************************************/
964 void TextType::Draw(OutputDevice& rOut)
966 if ((Flags & TextOutlBit)!=0) return; // Sourcetext fuer Outliner !!
968 ObjTextType T1,T2;
969 sal_uInt16 Index1;
970 sal_uInt16 Index2;
971 UCHAR c = TextEnd;
972 sal_uInt16 l; // Anzahl der Zeichen in der Zeile
973 sal_uInt16 i;
974 short yPos0;
975 short xPos;
976 short yPos;
977 sal_uInt16 LF;
978 sal_uInt16 MaxGrad;
979 short xSize;
980 short xSAdj;
981 short ySize;
982 double sn,cs;
983 sal_uInt16 TopToBase;
984 sal_Bool Ende = 0;
985 sal_uInt16 lc;
986 sal_Bool LineFit; // FitSize.x=0? oder Flags -> jede Zeile stretchen
987 sal_Bool TextFit;
988 short* xLine;
989 UCHAR* cLine; // Buffer fuer FormatLine
990 sal_uInt16 FitXMul;
991 sal_uInt16 FitXDiv;
992 sal_uInt16 FitYMul;
993 sal_uInt16 FitYDiv;
994 sal_Bool Fehler;
995 UCHAR* Buf=Buffer; // Zeiger auf die Buchstaben
997 pSgfFonts->ReadList();
998 xLine=new short[ChrXPosArrSize];
999 cLine=new UCHAR[CharLineSize];
1001 TextFit=(Flags & TextFitBits)!=0;
1002 LineFit=sal_False;
1003 LineFit=((Flags & TextFitZBit)!=0);
1004 if (TextFit && FitSize.x==0) LineFit=sal_True;
1006 if (DrehWink==0) {
1007 sn=0.0;
1008 cs=1.0;
1009 } else {
1010 sn=sin(double(DrehWink)*3.14159265359/18000);
1011 cs=cos(double(DrehWink)*3.14159265359/18000);
1014 T1=T; Index1=0; yPos=0; xPos=0;
1015 if (TextFit) {
1016 ySize=Pos2.y-Pos1.y;
1017 xSize=32000 /2; // Umbruch
1018 xSAdj=Pos2.x-Pos1.x; // zum Ausrichten bei Zentriert/Blocksatz
1019 //if (xSize<=0) { xSize=32000 /2; LineFit=sal_True; }
1020 FitXMul=sal::static_int_cast< sal_uInt16 >(abs(Pos2.x-Pos1.x)); FitXDiv=FitSize.x; if (FitXDiv==0) FitXDiv=1;
1021 FitYMul=sal::static_int_cast< sal_uInt16 >(abs(Pos2.y-Pos1.y)); FitYDiv=FitSize.y; if (FitYDiv==0) FitYDiv=1;
1022 } else {
1023 xSize=Pos2.x-Pos1.x;
1024 xSAdj=xSize;
1025 ySize=Pos2.y-Pos1.y;
1026 FitXMul=1; FitXDiv=1;
1027 FitYMul=1; FitYDiv=1;
1029 if (xSize<0) xSize=0;
1030 if (xSAdj<0) xSAdj=0;
1032 do {
1033 T2=T1; Index2=Index1;
1034 FormatLine(Buf,Index2,T,T2,xSize,xSAdj,xLine,l,sn,cs,cLine,LineFit);
1035 Fehler=(Index2==Index1);
1036 if (!Fehler) {
1037 lc=GetLineFeed(Buf,Index1,T,T1,l,LF,MaxGrad);
1038 if (TextFit) {
1039 if (LineFit) FitXDiv=xLine[lc+1];
1040 if (FitXDiv>0) {
1041 long Temp;
1042 for (i=1;i<=l+1;i++) {
1043 Temp=long(xLine[i])*long(FitXMul) /long(FitXDiv);
1044 xLine[i]=short(Temp);
1046 LF=MulDiv(LF,FitYMul,FitYDiv);
1047 MaxGrad=MulDiv(MaxGrad,FitYMul,FitYDiv);
1048 } else {
1049 FitXDiv=1; // 0 gibts nicht
1052 yPos0=yPos;
1053 TopToBase=GetTopToBaseLine(MaxGrad);
1054 yPos=yPos+TopToBase;
1055 Ende=(yPos0+short(MulDiv(MaxGrad,CharTopToBtm,100))>ySize) && !TextFit;
1056 if (!Ende) {
1057 T2=T1; Index2=Index1;
1058 i=1;
1059 while (i<=l) {
1060 c=GetTextCharConv(Buf,Index2,T,T2,l-i,sal_False);
1061 long xp1,yp1; // wegen Overflowgefahr
1062 PointType Pos;
1063 xp1=long(Pos1.x)+xPos+long(xLine[i]);
1064 yp1=long(Pos1.y)+yPos;
1065 if (xp1>32000) xp1=32000; if (xp1<-12000) xp1=-12000;
1066 if (yp1>32000) yp1=32000; if (yp1<-12000) yp1=-12000;
1067 Pos.x=short(xp1);
1068 Pos.y=short(yp1);
1070 if (DrehWink!=0) RotatePoint(Pos,Pos1.x,Pos1.y,sn,cs);
1071 DrawChar(rOut,c,T2,Pos,DrehWink,FitXMul,FitXDiv,FitYMul,FitYDiv);
1072 i++;
1073 } // while i<=l
1074 yPos=yPos0+LF;
1075 T1=T2; Index1=Index2; // Fuer die naechste Zeile
1076 } // if ObjMin.y+yPos<=Obj_Max.y
1077 } // if !Fehler
1078 } while (c!=TextEnd && !Ende && !Fehler);
1079 delete[] cLine;
1080 delete[] xLine;
1083 // End of DrawText.Pas
1084 /////////////////////////////////////////////////////////////////////////////////
1085 /////////////////////////////////////////////////////////////////////////////////
1086 /////////////////////////////////////////////////////////////////////////////////
1088 // nicht mehr benoetigt, da der Pointer nun extra gefuehrt wird
1089 // (DEC Alpha hat naemlich 64Bit-Pointer!)
1090 //UCHAR* TextType::GetBufPtr()
1092 // sal_uLong Temp;
1093 // Temp=sal_uLong(BufLo)+0x00010000*sal_uLong(BufHi);
1094 // return (UCHAR*)Temp;
1097 //void TextType::SetBufPtr(UCHAR* Ptr)
1099 // sal_uLong Temp=(sal_uLong)Ptr;
1100 // BufLo=sal_uInt16(Temp & 0x0000FFFF);
1101 // BufHi=sal_uInt16((Temp & 0xFFFF0000)>>16);
1104 sal_uInt32 ObjTextType::GetFont()
1106 return sal_uLong(FontLo)+0x00010000*sal_uLong(FontHi);
1109 void ObjTextType::SetFont(sal_uInt32 FontID)
1111 FontLo=sal_uInt16(FontID & 0x0000FFFF);
1112 FontHi=sal_uInt16((FontID & 0xFFFF0000)>>16);
1116 /////////////////////////////////////////////////////////////////////////////////
1117 // SGF.Ini lesen ////////////////////////////////////////////////////////////////
1118 /////////////////////////////////////////////////////////////////////////////////
1119 SgfFontOne::SgfFontOne()
1121 Next=NULL;
1122 IFID=0;
1123 Bold=sal_False;
1124 Ital=sal_False;
1125 Sans=sal_False;
1126 Serf=sal_False;
1127 Fixd=sal_False;
1128 SVFamil=FAMILY_DONTKNOW;
1129 SVChSet=RTL_TEXTENCODING_DONTKNOW;
1130 SVWidth=40;
1133 void SgfFontOne::ReadOne( const OString& rID, OString& Dsc )
1135 if ( Dsc.getLength() < 4 || ( Dsc[0] != '(' ) )
1136 return;
1137 sal_Int32 i=1; // Erster Buchstabe des IF-Fontnamen. Davor ist eine '('
1138 while ( i < Dsc.getLength() && ( Dsc[i] !=')' ) )
1139 i++;
1140 Dsc = Dsc.copy(i+1); // IF-Fontname loeschen inkl. ()
1142 if ( Dsc.getLength() < 2 || ( Dsc[Dsc.getLength() - 1] !=')' ) )
1143 return;
1144 i=Dsc.getLength()-2; // hier ist die ')' des SV-Fontnames
1145 sal_Int32 j=0;
1146 while ( i > 0 && ( Dsc[i] != '(' ) )
1148 i--;
1149 j++;
1151 SVFName = OStringToOUString(Dsc.copy(i+1,j), RTL_TEXTENCODING_IBM_437); // SV-Fontname rausholen
1152 Dsc = OStringBuffer(Dsc).remove(i,j).makeStringAndClear();
1154 IFID = (sal_uInt32)rID.toInt32();
1155 sal_Int32 nTokenCount = comphelper::string::getTokenCount(Dsc, ' ');
1156 for (sal_Int32 nIdx = 0; nIdx < nTokenCount; ++nIdx)
1158 OString s(Dsc.getToken(nIdx, ' '));
1159 if (!s.isEmpty())
1161 s = s.toAsciiUpperCase();
1162 if (s.match("BOLD")) Bold=sal_True;
1163 else if (s.match("ITAL")) Ital=sal_True;
1164 else if (s.match("SERF")) Serf=sal_True;
1165 else if (s.match("SANS")) Sans=sal_True;
1166 else if (s.match("FIXD")) Fixd=sal_True;
1167 else if (s.match("ROMAN")) SVFamil=FAMILY_ROMAN;
1168 else if (s.match("SWISS")) SVFamil=FAMILY_SWISS;
1169 else if (s.match("MODERN")) SVFamil=FAMILY_MODERN;
1170 else if (s.match("SCRIPT")) SVFamil=FAMILY_SCRIPT;
1171 else if (s.match("DECORA")) SVFamil=FAMILY_DECORATIVE;
1172 else if (s.match("ANSI")) SVChSet=RTL_TEXTENCODING_MS_1252;
1173 else if (s.match("IBMPC")) SVChSet=RTL_TEXTENCODING_IBM_850;
1174 else if (s.match("MAC")) SVChSet=RTL_TEXTENCODING_APPLE_ROMAN;
1175 else if (s.match("SYMBOL")) SVChSet=RTL_TEXTENCODING_SYMBOL;
1176 else if (s.match("SYSTEM")) SVChSet = osl_getThreadTextEncoding();
1177 else if (comphelper::string::isdigitAsciiString(s) ) SVWidth=sal::static_int_cast< sal_uInt16 >(s.toInt32());
1182 /////////////////////////////////////////////////////////////////////////////////
1184 SgfFontLst::SgfFontLst()
1186 pList=NULL;
1187 Last=NULL;
1188 LastID=0;
1189 LastLn=NULL;
1190 Tried=sal_False;
1193 SgfFontLst::~SgfFontLst()
1195 RausList();
1198 void SgfFontLst::RausList()
1200 SgfFontOne* P;
1201 SgfFontOne* P1;
1202 P=pList;
1203 while (P!=NULL) {
1204 P1=P->Next;
1205 delete P;
1206 P=P1;
1208 pList=NULL;
1209 Last=NULL;
1210 Tried=sal_False;
1211 LastID=0;
1212 LastLn=NULL;
1215 void SgfFontLst::AssignFN(const String& rFName)
1216 { FNam=rFName; }
1218 void SgfFontLst::ReadList()
1220 if (!Tried)
1222 Tried=sal_True;
1223 LastID=0;
1224 LastLn=NULL;
1225 SgfFontOne* P,P1;
1226 Config aCfg(FNam);
1227 aCfg.SetGroup("SGV Fonts fuer StarView");
1228 sal_uInt16 Anz=aCfg.GetKeyCount();
1229 sal_uInt16 i;
1230 OString FID;
1231 OString Dsc;
1233 for (i=0;i<Anz;i++)
1235 FID = comphelper::string::remove(aCfg.GetKeyName(i), ' ');
1236 Dsc = aCfg.ReadKey( i );
1237 if (comphelper::string::isdigitAsciiString(FID))
1239 P=new SgfFontOne; // neuer Eintrag
1240 if (Last!=NULL) Last->Next=P; else pList=P; Last=P; // einklinken
1241 P->ReadOne(FID,Dsc); // und Zeile interpretieren
1247 SgfFontOne* SgfFontLst::GetFontDesc(sal_uInt32 ID)
1249 if (ID!=LastID) {
1250 SgfFontOne* P;
1251 P=pList;
1252 while (P!=NULL && P->IFID!=ID) P=P->Next;
1253 LastID=ID;
1254 LastLn=P;
1256 return LastLn;
1259 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */