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