1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_editeng.hxx" 26 27 #include <editeng/txtrange.hxx> 28 #include <math.h> 29 #include <tools/poly.hxx> 30 #include <tools/debug.hxx> 31 #include <basegfx/polygon/b2dpolygon.hxx> 32 #include <basegfx/polygon/b2dpolygontools.hxx> 33 34 /************************************************************************* 35 |* 36 |* TextRanger::TextRanger() 37 |* 38 |* Beschreibung 39 |* Ersterstellung 20.01.97 40 |* Letzte Aenderung 20.01.97 AMA 41 |* 42 *************************************************************************/ 43 44 TextRanger::TextRanger( const basegfx::B2DPolyPolygon& rPolyPolygon, const basegfx::B2DPolyPolygon* pLinePolyPolygon, 45 sal_uInt16 nCacheSz, sal_uInt16 nLft, sal_uInt16 nRght, sal_Bool bSimpl, sal_Bool bInnr, 46 sal_Bool bVert ) : 47 pBound( NULL ), 48 nCacheSize( nCacheSz ), 49 nCacheIdx( 0 ), 50 nRight( nRght ), 51 nLeft( nLft ), 52 nUpper( 0 ), 53 nLower( 0 ), 54 nPointCount( 0 ), 55 bSimple( bSimpl ), 56 bInner( bInnr ), 57 bVertical( bVert ) 58 { 59 #ifdef DBG_UTIL 60 bFlag3 = bFlag4 = bFlag5 = bFlag6 = bFlag7 = sal_False; 61 #endif 62 pRangeArr = new Range[ nCacheSize ]; 63 pCache = new SvLongsPtr[ nCacheSize ]; 64 memset( pRangeArr, 0, nCacheSize * sizeof( Range ) ); 65 memset( pCache, 0, nCacheSize * sizeof( SvLongsPtr ) ); 66 sal_uInt32 nCount(rPolyPolygon.count()); 67 mpPolyPolygon = new PolyPolygon( (sal_uInt16)nCount ); 68 69 for(sal_uInt32 i(0L); i < nCount; i++) 70 { 71 const basegfx::B2DPolygon aCandidate(rPolyPolygon.getB2DPolygon(i).getDefaultAdaptiveSubdivision()); 72 nPointCount += aCandidate.count(); 73 mpPolyPolygon->Insert( Polygon(aCandidate), (sal_uInt16)i ); 74 } 75 76 if( pLinePolyPolygon ) 77 { 78 nCount = pLinePolyPolygon->count(); 79 mpLinePolyPolygon = new PolyPolygon(); 80 81 for(sal_uInt32 i(0L); i < nCount; i++) 82 { 83 const basegfx::B2DPolygon aCandidate(pLinePolyPolygon->getB2DPolygon(i).getDefaultAdaptiveSubdivision()); 84 nPointCount += aCandidate.count(); 85 mpLinePolyPolygon->Insert( Polygon(aCandidate), (sal_uInt16)i ); 86 } 87 } 88 else 89 mpLinePolyPolygon = NULL; 90 } 91 92 /************************************************************************* 93 |* 94 |* TextRanger::~TextRanger() 95 |* 96 |* Beschreibung 97 |* Ersterstellung 20.01.97 98 |* Letzte Aenderung 20.01.97 AMA 99 |* 100 *************************************************************************/ 101 102 TextRanger::~TextRanger() 103 { 104 for( sal_uInt16 i = 0; i < nCacheSize; ++i ) 105 delete pCache[i]; 106 delete[] pCache; 107 delete[] pRangeArr; 108 delete mpPolyPolygon; 109 delete mpLinePolyPolygon; 110 delete pBound; 111 } 112 113 /*-----------------17.11.00 09:49------------------- 114 * TextRanger::SetVertical(..) 115 * If there's is a change in the writing direction, 116 * the cache has to be cleared. 117 * --------------------------------------------------*/ 118 119 void TextRanger::SetVertical( sal_Bool bNew ) 120 { 121 if( IsVertical() != bNew ) 122 { 123 bVertical = bNew; 124 for( sal_uInt16 i = 0; i < nCacheSize; ++i ) 125 delete pCache[i]; 126 memset( pRangeArr, 0, nCacheSize * sizeof( Range ) ); 127 memset( pCache, 0, nCacheSize * sizeof( SvLongsPtr ) ); 128 } 129 } 130 131 /************************************************************************* 132 |* 133 |* SvxBoundArgs 134 |* 135 |* Beschreibung 136 |* Ersterstellung 20.01.97 137 |* Letzte Aenderung 20.01.97 AMA 138 |* 139 *************************************************************************/ 140 141 class SvxBoundArgs 142 { 143 SvBools aBoolArr; 144 SvLongs *pLongArr; 145 TextRanger *pTextRanger; 146 long nMin; 147 long nMax; 148 long nTop; 149 long nBottom; 150 long nUpDiff; 151 long nLowDiff; 152 long nUpper; 153 long nLower; 154 long nStart; 155 long nEnd; 156 sal_uInt16 nCut; 157 sal_uInt16 nLast; 158 sal_uInt16 nNext; 159 sal_uInt8 nAct; 160 sal_uInt8 nFirst; 161 sal_Bool bClosed : 1; 162 sal_Bool bInner : 1; 163 sal_Bool bMultiple : 1; 164 sal_Bool bConcat : 1; 165 sal_Bool bRotate : 1; 166 void NoteRange( sal_Bool bToggle ); 167 long Cut( long nY, const Point& rPt1, const Point& rPt2 ); 168 void Add(); 169 void _NoteFarPoint( long nPx, long nPyDiff, long nDiff ); 170 void NoteFarPoint( long nPx, long nPyDiff, long nDiff ) 171 { if( nDiff ) _NoteFarPoint( nPx, nPyDiff, nDiff ); } 172 long CalcMax( const Point& rPt1, const Point& rPt2, long nRange, long nFar ); 173 void CheckCut( const Point& rLst, const Point& rNxt ); 174 inline long A( const Point& rP ) const { return bRotate ? rP.Y() : rP.X(); } 175 inline long B( const Point& rP ) const { return bRotate ? rP.X() : rP.Y(); } 176 public: 177 SvxBoundArgs( TextRanger* pRanger, SvLongs *pLong, const Range& rRange ); 178 void NotePoint( const long nA ) { NoteMargin( nA - nStart, nA + nEnd ); } 179 void NoteMargin( const long nL, const long nR ) 180 { if( nMin > nL ) nMin = nL; if( nMax < nR ) nMax = nR; } 181 sal_uInt16 Area( const Point& rPt ); 182 void NoteUpLow( long nA, const sal_uInt8 nArea ); 183 void Calc( const PolyPolygon& rPoly ); 184 void Concat( const PolyPolygon* pPoly ); 185 // inlines 186 void NoteLast() { if( bMultiple ) NoteRange( nAct == nFirst ); } 187 void SetClosed( const sal_Bool bNew ){ bClosed = bNew; } 188 sal_Bool IsClosed() const { return bClosed; } 189 void SetConcat( const sal_Bool bNew ){ bConcat = bNew; } 190 sal_Bool IsConcat() const { return bConcat; } 191 sal_uInt8 GetAct() const { return nAct; } 192 }; 193 194 SvxBoundArgs::SvxBoundArgs( TextRanger* pRanger, SvLongs *pLong, 195 const Range& rRange ) 196 : pLongArr( pLong ), pTextRanger( pRanger ), 197 nTop( rRange.Min() ), nBottom( rRange.Max() ), 198 bInner( pRanger->IsInner() ), bMultiple( bInner || !pRanger->IsSimple() ), 199 bConcat( sal_False ), bRotate( pRanger->IsVertical() ) 200 { 201 if( bRotate ) 202 { 203 nStart = pRanger->GetUpper(); 204 nEnd = pRanger->GetLower(); 205 nLowDiff = pRanger->GetLeft(); 206 nUpDiff = pRanger->GetRight(); 207 } 208 else 209 { 210 nStart = pRanger->GetLeft(); 211 nEnd = pRanger->GetRight(); 212 nLowDiff = pRanger->GetUpper(); 213 nUpDiff = pRanger->GetLower(); 214 } 215 nUpper = nTop - nUpDiff; 216 nLower = nBottom + nLowDiff; 217 pLongArr->Remove( 0, pLongArr->Count() ); 218 } 219 220 long SvxBoundArgs::CalcMax( const Point& rPt1, const Point& rPt2, 221 long nRange, long nFarRange ) 222 { 223 double nDa = Cut( nRange, rPt1, rPt2 ) - Cut( nFarRange, rPt1, rPt2 ); 224 double nB; 225 if( nDa < 0 ) 226 { 227 nDa = -nDa; 228 nB = nEnd; 229 } 230 else 231 nB = nStart; 232 nB *= nB; 233 nB += nDa * nDa; 234 nB = nRange + nDa * ( nFarRange - nRange ) / sqrt( nB ); 235 236 sal_Bool bNote; 237 if( nB < B(rPt2) ) 238 bNote = nB > B(rPt1); 239 else 240 bNote = nB < B(rPt1); 241 if( bNote ) 242 return( long( nB ) ); 243 return 0; 244 } 245 246 void SvxBoundArgs::CheckCut( const Point& rLst, const Point& rNxt ) 247 { 248 if( nCut & 1 ) 249 NotePoint( Cut( nBottom, rLst, rNxt ) ); 250 if( nCut & 2 ) 251 NotePoint( Cut( nTop, rLst, rNxt ) ); 252 if( rLst.X() != rNxt.X() && rLst.Y() != rNxt.Y() ) 253 { 254 long nYps; 255 if( nLowDiff && ( ( nCut & 1 ) || nLast == 1 || nNext == 1 ) ) 256 { 257 nYps = CalcMax( rLst, rNxt, nBottom, nLower ); 258 if( nYps ) 259 _NoteFarPoint( Cut( nYps, rLst, rNxt ), nLower-nYps, nLowDiff ); 260 } 261 if( nUpDiff && ( ( nCut & 2 ) || nLast == 2 || nNext == 2 ) ) 262 { 263 nYps = CalcMax( rLst, rNxt, nTop, nUpper ); 264 if( nYps ) 265 _NoteFarPoint( Cut( nYps, rLst, rNxt ), nYps-nUpper, nUpDiff ); 266 } 267 } 268 } 269 270 void SvxBoundArgs::_NoteFarPoint( long nPa, long nPbDiff, long nDiff ) 271 { 272 long nTmpA; 273 double nQuot = 2 * nDiff - nPbDiff; 274 nQuot *= nPbDiff; 275 nQuot = sqrt( nQuot ); 276 nQuot /= nDiff; 277 nTmpA = nPa - long( nStart * nQuot ); 278 nPbDiff = nPa + long( nEnd * nQuot ); 279 NoteMargin( nTmpA, nPbDiff ); 280 } 281 282 void SvxBoundArgs::NoteRange( sal_Bool bToggle ) 283 { 284 DBG_ASSERT( nMax >= nMin || bInner, "NoteRange: Min > Max?"); 285 if( nMax < nMin ) 286 return; 287 if( !bClosed ) 288 bToggle = sal_False; 289 sal_uInt16 nIdx = 0; 290 sal_uInt16 nCount = pLongArr->Count(); 291 DBG_ASSERT( nCount == 2 * aBoolArr.size(), "NoteRange: Incompatible Sizes" ); 292 while( nIdx < nCount && (*pLongArr)[ nIdx ] < nMin ) 293 ++nIdx; 294 sal_Bool bOdd = nIdx % 2 ? sal_True : sal_False; 295 // Kein Ueberlappung mit vorhandenen Intervallen? 296 if( nIdx == nCount || ( !bOdd && nMax < (*pLongArr)[ nIdx ] ) ) 297 { // Dann wird ein neues eingefuegt ... 298 pLongArr->Insert( nMin, nIdx ); 299 pLongArr->Insert( nMax, nIdx + 1 ); 300 aBoolArr.insert( aBoolArr.begin() + nIdx / 2, bToggle ); 301 } 302 else 303 { // ein vorhandes Intervall erweitern ... 304 sal_uInt16 nMaxIdx = nIdx; 305 // Wenn wir auf einer linken Intervallgrenze gelandet sind, muss diese 306 // auf nMin gesenkt werden. 307 if( bOdd ) 308 --nIdx; 309 else 310 (*pLongArr)[ nIdx ] = nMin; 311 while( nMaxIdx < nCount && (*pLongArr)[ nMaxIdx ] < nMax ) 312 ++nMaxIdx; 313 DBG_ASSERT( nMaxIdx > nIdx || nMin == nMax, "NoteRange: Funny Situation." ); 314 if( nMaxIdx ) 315 --nMaxIdx; 316 if( nMaxIdx < nIdx ) 317 nMaxIdx = nIdx; 318 // Wenn wir auf einer rechten Intervallgrenze landen, muss diese 319 // auf nMax angehoben werden. 320 if( nMaxIdx % 2 ) 321 (*pLongArr)[ nMaxIdx-- ] = nMax; 322 // Jetzt werden eventuell noch Intervalle verschmolzen 323 sal_uInt16 nDiff = nMaxIdx - nIdx; 324 nMaxIdx = nIdx / 2; // Ab hier ist nMaxIdx der Index im BoolArray. 325 if( nDiff ) 326 { 327 (*pLongArr).Remove( nIdx + 1, nDiff ); 328 nDiff /= 2; 329 sal_uInt16 nStop = nMaxIdx + nDiff; 330 for( sal_uInt16 i = nMaxIdx; i < nStop; ++i ) 331 bToggle ^= aBoolArr[ i ]; 332 aBoolArr.erase( aBoolArr.begin() + nMaxIdx, aBoolArr.begin() + (nMaxIdx + nDiff) ); 333 } 334 DBG_ASSERT( nMaxIdx < aBoolArr.size(), "NoteRange: Too much deleted" ); 335 aBoolArr[ nMaxIdx ] ^= bToggle; 336 } 337 } 338 339 void SvxBoundArgs::Calc( const PolyPolygon& rPoly ) 340 { 341 sal_uInt16 nCount; 342 nAct = 0; 343 for( sal_uInt16 i = 0; i < rPoly.Count(); ++i ) 344 { 345 const Polygon& rPol = rPoly[ i ]; 346 nCount = rPol.GetSize(); 347 if( nCount ) 348 { 349 const Point& rNull = rPol[ 0 ]; 350 SetClosed( IsConcat() || ( rNull == rPol[ nCount - 1 ] ) ); 351 nLast = Area( rNull ); 352 if( nLast & 12 ) 353 { 354 nFirst = 3; 355 if( bMultiple ) 356 nAct = 0; 357 } 358 else 359 { 360 // Der erste Punkt des Polygons liegt innerhalb der Zeile. 361 if( nLast ) 362 { 363 if( bMultiple || !nAct ) 364 { 365 nMin = USHRT_MAX; 366 nMax = 0; 367 } 368 if( nLast & 1 ) 369 NoteFarPoint( A(rNull), nLower - B(rNull), nLowDiff ); 370 else 371 NoteFarPoint( A(rNull), B(rNull) - nUpper, nUpDiff ); 372 } 373 else 374 { 375 if( bMultiple || !nAct ) 376 { 377 nMin = A(rNull); 378 nMax = nMin + nEnd; 379 nMin -= nStart; 380 } 381 else 382 NotePoint( A(rNull) ); 383 } 384 nFirst = 0; // In welcher Richtung wird die Zeile verlassen? 385 nAct = 3; // Wir sind z.Z. innerhalb der Zeile. 386 } 387 if( nCount > 1 ) 388 { 389 sal_uInt16 nIdx = 1; 390 while( sal_True ) 391 { 392 const Point& rLast = rPol[ nIdx - 1 ]; 393 if( nIdx == nCount ) 394 nIdx = 0; 395 const Point& rNext = rPol[ nIdx ]; 396 nNext = Area( rNext ); 397 nCut = nNext ^ nLast; 398 sal_uInt16 nOldAct = nAct; 399 if( nAct ) 400 CheckCut( rLast, rNext ); 401 if( nCut & 4 ) 402 { 403 NoteUpLow( Cut( nLower, rLast, rNext ), 2 ); 404 if( nAct && nAct != nOldAct ) 405 { 406 nOldAct = nAct; 407 CheckCut( rLast, rNext ); 408 } 409 } 410 if( nCut & 8 ) 411 { 412 NoteUpLow( Cut( nUpper, rLast, rNext ), 1 ); 413 if( nAct && nAct != nOldAct ) 414 CheckCut( rLast, rNext ); 415 } 416 if( !nIdx ) 417 { 418 if( !( nNext & 12 ) ) 419 NoteLast(); 420 break; 421 } 422 if( !( nNext & 12 ) ) 423 { 424 if( !nNext ) 425 NotePoint( A(rNext) ); 426 else if( nNext & 1 ) 427 NoteFarPoint( A(rNext), nLower-B(rNext), nLowDiff ); 428 else 429 NoteFarPoint( A(rNext), B(rNext)-nUpper, nUpDiff ); 430 } 431 nLast = nNext; 432 if( ++nIdx == nCount && !IsClosed() ) 433 { 434 if( !( nNext & 12 ) ) 435 NoteLast(); 436 break; 437 } 438 } 439 } 440 if( bMultiple && IsConcat() ) 441 { 442 Add(); 443 nAct = 0; 444 } 445 } 446 } 447 if( !bMultiple ) 448 { 449 DBG_ASSERT( pLongArr->Count() == 0, "I said: Simple!" ); 450 if( nAct ) 451 { 452 if( bInner ) 453 { 454 long nTmpMin, nTmpMax; 455 { 456 nTmpMin = nMin + 2 * nStart; 457 nTmpMax = nMax - 2 * nEnd; 458 if( nTmpMin <= nTmpMax ) 459 { 460 pLongArr->Insert( nTmpMin, 0 ); 461 pLongArr->Insert( nTmpMax, 1 ); 462 } 463 } 464 } 465 else 466 { 467 pLongArr->Insert( nMin, 0 ); 468 pLongArr->Insert( nMax, 1 ); 469 } 470 } 471 } 472 else if( !IsConcat() ) 473 Add(); 474 } 475 476 void SvxBoundArgs::Add() 477 { 478 sal_uInt16 nLongIdx = 1; 479 size_t nCount = aBoolArr.size(); 480 if( nCount && ( !bInner || !pTextRanger->IsSimple() ) ) 481 { 482 sal_Bool bDelete = aBoolArr.front(); 483 if( bInner ) 484 bDelete = !bDelete; 485 for( size_t nBoolIdx = 1; nBoolIdx < nCount; ++nBoolIdx ) 486 { 487 if( bDelete ) 488 { 489 sal_uInt16 next = 2; 490 while( nBoolIdx < nCount && !aBoolArr[ nBoolIdx++ ] && 491 (!bInner || nBoolIdx < nCount ) ) 492 next += 2; 493 pLongArr->Remove( nLongIdx, next ); 494 next /= 2; 495 nBoolIdx = nBoolIdx - next; 496 nCount = nCount - next; 497 aBoolArr.erase( aBoolArr.begin() + nBoolIdx, aBoolArr.begin() + (nBoolIdx + next) ); 498 if( nBoolIdx ) 499 aBoolArr[ nBoolIdx - 1 ] = sal_False; 500 #if OSL_DEBUG_LEVEL > 1 501 else 502 ++next; 503 #endif 504 } 505 bDelete = nBoolIdx < nCount && aBoolArr[ nBoolIdx ]; 506 nLongIdx += 2; 507 DBG_ASSERT( nLongIdx == 2*nBoolIdx+1, "BoundArgs: Array-Idx Confusion" ); 508 DBG_ASSERT( aBoolArr.size()*2 == pLongArr->Count(), 509 "BoundArgs: Array-Count: Confusion" ); 510 } 511 } 512 if( 0 != ( nCount = pLongArr->Count() ) ) 513 { 514 if( bInner ) 515 { 516 pLongArr->Remove( 0, 1 ); 517 pLongArr->Remove( pLongArr->Count() - 1, 1 ); 518 519 // Hier wird die Zeile beim "einfachen" Konturumfluss im Innern 520 // in ein grosses Rechteck zusammengefasst. 521 // Zur Zeit (April 1999) wertet die EditEngine nur das erste Rechteck 522 // aus, falls sie eines Tages in der Lage ist, eine Zeile in mehreren 523 // Teilen auszugeben, kann es sinnvoll sein, die folgenden Zeilen 524 // zu loeschen. 525 if( pTextRanger->IsSimple() && pLongArr->Count() > 2 ) 526 pLongArr->Remove( 1, pLongArr->Count() - 2 ); 527 528 } 529 } 530 } 531 532 void SvxBoundArgs::Concat( const PolyPolygon* pPoly ) 533 { 534 SetConcat( sal_True ); 535 DBG_ASSERT( pPoly, "Nothing to do?" ); 536 SvLongs *pOld = pLongArr; 537 pLongArr = new SvLongs( 2, 8 ); 538 aBoolArr.clear(); 539 bInner = sal_False; 540 Calc( *pPoly ); 541 sal_uInt16 nCount = pLongArr->Count(); 542 sal_uInt16 nIdx = 0; 543 sal_uInt16 i = 0; 544 sal_Bool bSubtract = pTextRanger->IsInner(); 545 while( i < nCount ) 546 { 547 sal_uInt16 nOldCount = pOld->Count(); 548 if( nIdx == nOldCount ) 549 { // Am Ende des alten Arrays angelangt... 550 if( !bSubtract ) 551 pOld->Insert( pLongArr, nIdx, i, USHRT_MAX ); 552 break; 553 } 554 long nLeft = (*pLongArr)[ i++ ]; 555 long nRight = (*pLongArr)[ i++ ]; 556 sal_uInt16 nLeftPos = nIdx + 1; 557 while( nLeftPos < nOldCount && nLeft > (*pOld)[ nLeftPos ] ) 558 nLeftPos += 2; 559 if( nLeftPos >= nOldCount ) 560 { // Das aktuelle Intervall gehoert ans Ende des alten Arrays... 561 if( !bSubtract ) 562 pOld->Insert( pLongArr, nOldCount, i - 2, USHRT_MAX ); 563 break; 564 } 565 sal_uInt16 nRightPos = nLeftPos - 1; 566 while( nRightPos < nOldCount && nRight >= (*pOld)[ nRightPos ] ) 567 nRightPos += 2; 568 if( nRightPos < nLeftPos ) 569 { // Das aktuelle Intervall gehoert zwischen zwei alte Intervalle 570 if( !bSubtract ) 571 pOld->Insert( pLongArr, nRightPos, i - 2, i ); 572 nIdx = nRightPos + 2; 573 } 574 else if( bSubtract ) // Subtrahieren ggf. Trennen 575 { 576 long nOld; 577 if( nLeft > ( nOld = (*pOld)[ nLeftPos - 1 ] ) ) 578 { // Jetzt spalten wir den linken Teil ab... 579 if( nLeft - 1 > nOld ) 580 { 581 pOld->Insert( nOld, nLeftPos - 1 ); 582 pOld->Insert( nLeft - 1, nLeftPos ); 583 nLeftPos += 2; 584 nRightPos += 2; 585 } 586 } 587 if( nRightPos - nLeftPos > 1 ) 588 pOld->Remove( nLeftPos, nRightPos - nLeftPos - 1 ); 589 if( ++nRight >= ( nOld = (*pOld)[ nLeftPos ] ) ) 590 pOld->Remove( nLeftPos - 1, 2 ); 591 else 592 (*pOld)[ nLeftPos - 1 ] = nRight; 593 } 594 else // Verschmelzen 595 { 596 if( nLeft < (*pOld)[ nLeftPos - 1 ] ) 597 (*pOld)[ nLeftPos - 1 ] = nLeft; 598 if( nRight > (*pOld)[ nRightPos - 1 ] ) 599 (*pOld)[ nRightPos - 1 ] = nRight; 600 if( nRightPos - nLeftPos > 1 ) 601 pOld->Remove( nLeftPos, nRightPos - nLeftPos - 1 ); 602 603 } 604 nIdx = nLeftPos - 1; 605 } 606 delete pLongArr; 607 } 608 609 /************************************************************************* 610 * SvxBoundArgs::Area ermittelt den Bereich, in dem sich der Punkt befindet 611 * 0 = innerhalb der Zeile 612 * 1 = unterhalb, aber innerhalb der oberen Randes 613 * 2 = oberhalb, aber innerhalb der unteren Randes 614 * 5 = unterhalb des oberen Randes 615 *10 = oberhalb des unteren Randes 616 *************************************************************************/ 617 618 sal_uInt16 SvxBoundArgs::Area( const Point& rPt ) 619 { 620 long nB = B( rPt ); 621 if( nB >= nBottom ) 622 { 623 if( nB >= nLower ) 624 return 5; 625 return 1; 626 } 627 if( nB <= nTop ) 628 { 629 if( nB <= nUpper ) 630 return 10; 631 return 2; 632 } 633 return 0; 634 } 635 636 /************************************************************************* 637 * lcl_Cut berechnet die X-Koordinate der Strecke (Pt1-Pt2) auf der 638 * Y-Koordinate nY. 639 * Vorausgesetzt wird, dass einer der Punkte oberhalb und der andere 640 * unterhalb der Y-Koordinate liegt. 641 *************************************************************************/ 642 643 long SvxBoundArgs::Cut( long nB, const Point& rPt1, const Point& rPt2 ) 644 { 645 if( pTextRanger->IsVertical() ) 646 { 647 double nQuot = nB - rPt1.X(); 648 nQuot /= ( rPt2.X() - rPt1.X() ); 649 nQuot *= ( rPt2.Y() - rPt1.Y() ); 650 return long( rPt1.Y() + nQuot ); 651 } 652 double nQuot = nB - rPt1.Y(); 653 nQuot /= ( rPt2.Y() - rPt1.Y() ); 654 nQuot *= ( rPt2.X() - rPt1.X() ); 655 return long( rPt1.X() + nQuot ); 656 } 657 658 void SvxBoundArgs::NoteUpLow( long nA, const sal_uInt8 nArea ) 659 { 660 if( nAct ) 661 { 662 NoteMargin( nA, nA ); 663 if( bMultiple ) 664 { 665 NoteRange( nArea != nAct ); 666 nAct = 0; 667 } 668 if( !nFirst ) 669 nFirst = nArea; 670 } 671 else 672 { 673 nAct = nArea; 674 nMin = nA; 675 nMax = nA; 676 } 677 } 678 679 SvLongsPtr TextRanger::GetTextRanges( const Range& rRange ) 680 { 681 DBG_ASSERT( rRange.Min() || rRange.Max(), "Zero-Range not allowed, Bye Bye" ); 682 sal_uInt16 nIndex = 0; 683 while( nIndex < nCacheSize && rRange != pRangeArr[ nIndex ] ) 684 ++nIndex; 685 if( nIndex >= nCacheSize ) 686 { 687 ++nCacheIdx; 688 nCacheIdx %= nCacheSize; 689 pRangeArr[ nCacheIdx ] = rRange; 690 if( !pCache[ nCacheIdx ] ) 691 pCache[ nCacheIdx ] = new SvLongs( 2, 8 ); 692 nIndex = nCacheIdx; 693 SvxBoundArgs aArg( this, pCache[ nCacheIdx ], rRange ); 694 aArg.Calc( *mpPolyPolygon ); 695 if( mpLinePolyPolygon ) 696 aArg.Concat( mpLinePolyPolygon ); 697 } 698 return pCache[ nIndex ]; 699 } 700 701 const Rectangle& TextRanger::_GetBoundRect() 702 { 703 DBG_ASSERT( 0 == pBound, "Don't call twice." ); 704 pBound = new Rectangle( mpPolyPolygon->GetBoundRect() ); 705 return *pBound; 706 } 707 708 709