1 // Copyright 2014 PDFium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #include "../../include/reflow/reflowengine.h" 8 #include "reflowedpage.h" 9 #include "layoutprovider_taggedpdf.h" 10 IPDF_LayoutProcessor* IPDF_LayoutProcessor::Create_LayoutProcessor_Reflow(FX_FLOAT TopIndent, FX_FLOAT fWidth, FX_FLOAT fHeight, void* pReflowedPage, int flags, FX_FLOAT lineSpace ) 11 { 12 if(pReflowedPage == NULL || fWidth <= 20) { 13 return NULL; 14 } 15 CPDF_LayoutProcessor_Reflow* pReflowEngine = FX_NEW CPDF_LayoutProcessor_Reflow(); 16 if (NULL == pReflowEngine) { 17 return NULL; 18 } 19 pReflowEngine->Init(TopIndent, fWidth, fHeight, (CPDF_ReflowedPage*)pReflowedPage, flags, lineSpace); 20 return pReflowEngine; 21 } 22 CPDF_LayoutProcessor_Reflow::CPDF_LayoutProcessor_Reflow() 23 { 24 m_pPause = NULL; 25 m_pLayoutElement = NULL; 26 m_fRefWidth = 0; 27 m_fRefWidth = 0; 28 m_fCurrLineWidth = 0; 29 m_fCurrLineHeight = 0; 30 m_bIllustration = FALSE; 31 m_pPreObj = NULL; 32 m_pCurrLine = FX_NEW CRF_DataPtrArray(50); 33 m_pTempLine = FX_NEW CRF_DataPtrArray(50); 34 m_StartIndent = 0; 35 m_PausePosition = 0; 36 } 37 CPDF_LayoutProcessor_Reflow::~CPDF_LayoutProcessor_Reflow() 38 { 39 if (m_pCurrLine) { 40 m_pCurrLine->RemoveAll(); 41 delete m_pCurrLine; 42 } 43 m_pCurrLine = NULL; 44 if (m_pTempLine) { 45 m_pTempLine->RemoveAll(); 46 delete m_pTempLine; 47 } 48 m_pTempLine = NULL; 49 } 50 void CPDF_LayoutProcessor_Reflow::Init(FX_FLOAT TopIndent, FX_FLOAT fWidth, FX_FLOAT fHeight, CPDF_ReflowedPage* pReflowedPage, int flags, FX_FLOAT lineSpace) 51 { 52 m_pLayoutElement = NULL; 53 m_TopIndent = TopIndent; 54 m_Status = LayoutReady; 55 m_flags = flags; 56 m_pReflowedPage = pReflowedPage; 57 m_fScreenHeight = fHeight; 58 m_fRefWidth = fWidth; 59 m_fCurrLineHeight = 0; 60 m_fCurrLineWidth = 0; 61 m_fLineSpace = lineSpace; 62 pReflowedPage->m_PageWidth = fWidth; 63 pReflowedPage->m_PageHeight = TopIndent; 64 } 65 void CPDF_LayoutProcessor_Reflow::FitPageMode() 66 { 67 if(m_flags & RF_PARSER_PAGEMODE && m_fScreenHeight > 20) { 68 float fitPageHeight = m_fScreenHeight; 69 CPDF_ReflowedPage* pRFPage = m_pReflowedPage; 70 int count = pRFPage->m_pReflowed->GetSize(); 71 CFX_WordArray dy; 72 dy.Add(0); 73 int pos = 0; 74 int screenCount = 1; 75 FX_FLOAT h = pRFPage->GetPageHeight(); 76 while (h > screenCount * fitPageHeight) { 77 FX_FLOAT tempPageHeight = screenCount * fitPageHeight; 78 int j = 0; 79 FX_FLOAT tempDy = 0; 80 for(int i = 0; i < count; i++) { 81 CRF_Data* pData = (*pRFPage->m_pReflowed)[i]; 82 FX_FLOAT posY; 83 posY = pData->m_PosY; 84 if(FXSYS_fabs(posY) > tempPageHeight && 85 FXSYS_fabs(posY + pData->m_Height) < tempPageHeight) { 86 if(j == 0) { 87 j = i; 88 } 89 if(pData->m_Height > fitPageHeight) { 90 FX_FLOAT zoom; 91 FX_FLOAT spaceh = screenCount * fitPageHeight + posY + pData->m_Height; 92 if(spaceh < fitPageHeight / 3 * 2) { 93 spaceh = fitPageHeight; 94 } 95 zoom = spaceh / pData->m_Height; 96 tempDy = spaceh - pData->m_Height; 97 pData->m_Height = spaceh; 98 pData->m_Width *= zoom; 99 break; 100 } 101 FX_FLOAT dy = pData->m_PosY + pData->m_Height + tempPageHeight; 102 if(dy > tempDy) { 103 tempDy = dy; 104 } 105 } else if(FXSYS_fabs(posY + pData->m_Height) > tempPageHeight) { 106 break; 107 } 108 } 109 for(; j < count; j++) { 110 CRF_Data* pData = (*pRFPage->m_pReflowed)[j]; 111 FX_FLOAT posY; 112 posY = pData->m_PosY; 113 if(FXSYS_fabs(posY) > tempPageHeight ) { 114 pData->m_PosY -= tempDy; 115 } 116 if(pData->m_Height >= fitPageHeight) { 117 pData->m_Height = fitPageHeight - 1; 118 if(pData->GetType() == CRF_Data::Text) { 119 CRF_CharData* pCharData = (CRF_CharData*)pData; 120 pCharData->m_pCharState->m_fFontSize = pData->m_Height; 121 } 122 } 123 } 124 pRFPage->m_PageHeight += tempDy; 125 h += tempDy; 126 screenCount++; 127 } 128 } 129 } 130 LayoutStatus CPDF_LayoutProcessor_Reflow::StartProcess(IPDF_LayoutElement* pElement, IFX_Pause* pPause, const CFX_AffineMatrix* pPDFMatrix) 131 { 132 if(!pElement) { 133 return LayoutError; 134 } 135 m_pPause = pPause; 136 m_PDFMatrix = *pPDFMatrix; 137 m_pRootElement = pElement; 138 ProcessElement(m_pRootElement, m_fRefWidth); 139 if(m_Status == LayoutToBeContinued) { 140 return LayoutToBeContinued; 141 } 142 m_Status = LayoutFinished; 143 FitPageMode(); 144 return LayoutFinished; 145 } 146 LayoutStatus CPDF_LayoutProcessor_Reflow::Continue() 147 { 148 int size = m_pReflowedPage->m_pReflowed->GetSize(); 149 ProcessElement(m_pRootElement, m_CurrRefWidth); 150 size = m_pReflowedPage->m_pReflowed->GetSize(); 151 if(m_Status == LayoutReady) { 152 m_Status = LayoutFinished; 153 FitPageMode(); 154 } 155 return m_Status; 156 } 157 int CPDF_LayoutProcessor_Reflow::GetPosition() 158 { 159 return m_PausePosition; 160 } 161 FX_BOOL CPDF_LayoutProcessor_Reflow::IsCanBreakAfter(FX_DWORD unicode) 162 { 163 if(unicode == -1) { 164 return FALSE; 165 } 166 switch(unicode) { 167 case 40: 168 case 91: 169 case 123: 170 return FALSE; 171 } 172 if(unicode >= 256) { 173 return TRUE; 174 } else if(unicode >= 48 && unicode <= 57) { 175 return FALSE; 176 } else if(unicode >= 64 && unicode <= 90) { 177 return FALSE; 178 } else if(unicode >= 97 && unicode <= 122) { 179 return FALSE; 180 } 181 return TRUE; 182 } 183 FX_BOOL CPDF_LayoutProcessor_Reflow::IsCanBreakBefore(FX_DWORD unicode) 184 { 185 if(unicode == -1) { 186 return FALSE; 187 } 188 switch(unicode) { 189 case 33: 190 case 41: 191 case 44: 192 case 46: 193 case 59: 194 case 63: 195 case 93: 196 case 125: 197 return FALSE; 198 } 199 if(unicode >= 256) { 200 return TRUE; 201 } else if(unicode >= 48 && unicode <= 57) { 202 return FALSE; 203 } else if(unicode >= 64 && unicode <= 90) { 204 return FALSE; 205 } else if(unicode >= 97 && unicode <= 122) { 206 return FALSE; 207 } 208 return TRUE; 209 } 210 void CPDF_LayoutProcessor_Reflow::ProcessTable(FX_FLOAT dx) 211 { 212 if(m_pReflowedPage->m_pReflowed->GetSize() == 0) { 213 return; 214 } 215 CRF_Table* pTable = m_TableArray.GetAt(m_TableArray.GetSize() - 1); 216 int rowCount = pTable->m_nCell.GetSize(); 217 int n = 0; 218 FX_FLOAT* dyRow = FX_Alloc(FX_FLOAT, rowCount + 1); 219 FXSYS_memset32(dyRow, 0, sizeof(FX_FLOAT) * (rowCount + 1)); 220 dyRow[0] = 0 ; 221 dyRow[0] = - pTable->m_ReflowPageHeight; 222 int tableColCount = 0; 223 int i; 224 for(i = 0; i < rowCount; i++) { 225 int colCount = pTable->m_nCell.GetAt(i); 226 if(colCount > tableColCount) { 227 tableColCount = colCount; 228 } 229 } 230 int cellCount = tableColCount * rowCount; 231 RF_TableCell** pVirtualTable = FX_Alloc(RF_TableCell*, cellCount); 232 FXSYS_memset32(pVirtualTable, 0, sizeof(RF_TableCell*) * cellCount); 233 for(i = 0; i < rowCount; i++) { 234 int colCount = pTable->m_nCell.GetAt(i); 235 FX_FLOAT rowWidth = 0; 236 int j = 0; 237 int s = pTable->m_pCellArray.GetSize(); 238 for(j = 0; j < colCount; j++) { 239 RF_TableCell* pCell = (RF_TableCell*)pTable->m_pCellArray.GetAt(n++); 240 if(pCell->m_EndPos < pCell->m_BeginPos) { 241 continue; 242 } 243 int pos = i * tableColCount; 244 while(pos < cellCount && pVirtualTable[pos] != NULL) { 245 pos++; 246 } 247 if(pos >= (i + 1) * tableColCount) { 248 pos = i * tableColCount + j; 249 } 250 int RowSpan = pCell->m_RowSpan; 251 int ColSpan = pCell->m_ColSpan; 252 if(RowSpan + i > rowCount) { 253 RowSpan = rowCount - i; 254 } 255 if(ColSpan + j > colCount) { 256 ColSpan = colCount - j; 257 } 258 for(int m = 0; m < RowSpan; m++) { 259 for(int nn = 0; nn < ColSpan; nn++) { 260 if(pos + nn >= cellCount) { 261 break; 262 } 263 pVirtualTable[pos + nn] = pCell; 264 } 265 pos += tableColCount; 266 } 267 FX_FLOAT dxCell = dx; 268 for(pos = i * tableColCount; pVirtualTable[pos] != pCell && pos < cellCount; pos++) { 269 dxCell += (pVirtualTable[pos])->m_MaxWidth; 270 } 271 CRF_Data* pData = (*m_pReflowedPage->m_pReflowed)[pCell->m_BeginPos]; 272 FX_FLOAT dy = dyRow[i] - pData->m_Height - pData->m_PosY; 273 CFX_AffineMatrix matrix(1, 0, 0, 1, dxCell, dy); 274 Transform(&matrix, m_pReflowedPage->m_pReflowed, pCell->m_BeginPos, pCell->m_EndPos - pCell->m_BeginPos + 1); 275 if(pCell->m_RowSpan + i <= rowCount) { 276 if(FXSYS_fabs(dyRow[pCell->m_RowSpan + i]) < FXSYS_fabs(dyRow[i] - pCell->m_CellHeight)) { 277 dyRow[pCell->m_RowSpan + i] = dyRow[i] - pCell->m_CellHeight; 278 } 279 } 280 } 281 } 282 n = 0; 283 for(i = 0; i < rowCount; i++) { 284 int colCount = pTable->m_nCell.GetAt(i); 285 for(int j = 0; j < colCount; j++) { 286 RF_TableCell* pCell = (RF_TableCell*)pTable->m_pCellArray.GetAt(n++); 287 switch(pCell->m_BlockAlign) { 288 case LayoutAfter: { 289 FX_FLOAT dy = dyRow[i + pCell->m_RowSpan] - pCell->m_CellHeight - dyRow[i]; 290 CFX_AffineMatrix matrix(1, 0, 0, 1, 0, dy); 291 Transform(&matrix, m_pReflowedPage->m_pReflowed, pCell->m_BeginPos, pCell->m_EndPos - pCell->m_BeginPos + 1); 292 } 293 break; 294 case LayoutMiddle: 295 case LayoutJustify: { 296 FX_FLOAT dy = (dyRow[i + pCell->m_RowSpan] + pCell->m_CellHeight - dyRow[i]) / 2; 297 CFX_AffineMatrix matrix(1, 0, 0, 1, 0, dy); 298 Transform(&matrix, m_pReflowedPage->m_pReflowed, pCell->m_BeginPos, pCell->m_EndPos - pCell->m_BeginPos + 1); 299 break; 300 } 301 default: 302 break; 303 } 304 } 305 } 306 CRF_Data* pData = (*m_pReflowedPage->m_pReflowed)[m_pReflowedPage->m_pReflowed->GetSize() - 1]; 307 m_pReflowedPage->m_PageHeight = - dyRow[rowCount] + pData->m_Height; 308 FX_Free(pVirtualTable); 309 FX_Free(dyRow); 310 int size = pTable->m_pCellArray.GetSize(); 311 for(i = 0; i < size; i++) { 312 RF_TableCell* pCell = pTable->m_pCellArray.GetAt(i); 313 FX_Free(pCell); 314 } 315 pTable->m_pCellArray.RemoveAll(); 316 pTable->m_nCell.RemoveAll(); 317 int s = sizeof(CRF_Table); 318 delete pTable; 319 m_TableArray.RemoveAt(m_TableArray.GetSize() - 1); 320 } 321 CFX_FloatRect CPDF_LayoutProcessor_Reflow::GetElmBBox(IPDF_LayoutElement* pElement) 322 { 323 CFX_FloatRect rect; 324 int objCount = pElement->CountObjects(); 325 int count = pElement->CountChildren(); 326 if(objCount == 0 && count == 0) { 327 return rect; 328 } 329 CFX_AffineMatrix matrix; 330 int i; 331 for(i = 0; i < objCount; i++) { 332 CPDF_PageObject* pObj = pElement->GetObject(0); 333 if(!pObj) { 334 continue; 335 } 336 if( rect.Height() == 0 ) { 337 rect = pObj->GetBBox(&matrix); 338 } else { 339 rect.Union(pObj->GetBBox(&matrix)); 340 } 341 } 342 for(i = 0; i < count; i++) { 343 IPDF_LayoutElement* pChildElement = pElement->GetChild(i); 344 if( rect.Height() == 0 ) { 345 rect = GetElmBBox(pChildElement); 346 } else { 347 rect.Union(GetElmBBox(pChildElement)); 348 } 349 } 350 return rect; 351 } 352 FX_FLOAT CPDF_LayoutProcessor_Reflow::GetElmWidth(IPDF_LayoutElement* pElement) 353 { 354 if(!pElement) { 355 return 0; 356 } 357 LayoutType layoutType = pElement->GetType(); 358 FX_FLOAT width = 0; 359 if(layoutType == LayoutTable || layoutType == LayoutTableDataCell || layoutType == LayoutTableHeaderCell) { 360 width = pElement->GetNumberAttr(LayoutWidth); 361 if(width > 0) { 362 return width; 363 } 364 } else if( layoutType == LayoutTableRow) { 365 int count = pElement->CountChildren(); 366 for(int i = 0; i < count; i++) { 367 IPDF_LayoutElement* pElm = pElement->GetChild(i); 368 width += pElm->GetNumberAttr(LayoutWidth); 369 } 370 if(width > 0) { 371 return width; 372 } 373 } 374 CFX_FloatRect rect = GetElmBBox(pElement); 375 return rect.Width(); 376 } 377 FX_BOOL GetIntersection(FX_FLOAT low1, FX_FLOAT high1, FX_FLOAT low2, FX_FLOAT high2, 378 FX_FLOAT& interlow, FX_FLOAT& interhigh); 379 FX_BOOL IsSameLine(FX_BOOL bHorizontal, CFX_FloatRect Rect1, CFX_FloatRect Rect2) 380 { 381 if(bHorizontal) { 382 FX_FLOAT inter_top, inter_bottom; 383 if (!GetIntersection(Rect1.bottom, Rect1.top, Rect2.bottom, Rect2.top, 384 inter_bottom, inter_top)) { 385 return FALSE; 386 } 387 FX_FLOAT lineHeight = Rect1.top - Rect1.bottom; 388 if(lineHeight > 20 && lineHeight > Rect2.Height() * 2) { 389 return FALSE; 390 } 391 if(lineHeight > 5 && Rect2.Height() / 2 > lineHeight) { 392 return FALSE; 393 } 394 FX_FLOAT inter_h = inter_top - inter_bottom; 395 if (inter_h < (lineHeight) / 2 && inter_h < Rect2.Height() / 2) { 396 return FALSE; 397 } 398 } else { 399 FX_FLOAT inter_left, inter_right; 400 if(!GetIntersection(Rect1.left, Rect1.right, Rect2.left, Rect2.right, inter_left, inter_right)) { 401 return FALSE; 402 } 403 FX_FLOAT inter_w = inter_right - inter_left; 404 if (inter_w < (Rect1.right - Rect1.left) / 2 && inter_w < (Rect2.right - Rect2.left) / 2) { 405 return FALSE; 406 } 407 } 408 return TRUE; 409 } 410 FX_INT32 IsCanMergeParagraph(IPDF_LayoutElement* pPrevElement, IPDF_LayoutElement* pNextElement) 411 { 412 FX_INT32 analogial = 100; 413 FX_INT32 nPrevObj = pPrevElement->CountObjects(), i; 414 CPDF_PageObject* pPrevObj = NULL; 415 CFX_FloatRect prevRect, rect; 416 CFX_PtrArray prevLine, line; 417 FX_BOOL bParagraphStart = FALSE; 418 for(i = 0; i < nPrevObj; i++) { 419 CPDF_PageObject* pObj = pPrevElement->GetObject(i); 420 if(!pPrevObj) { 421 pPrevObj = pObj; 422 rect = CFX_FloatRect(pObj->m_Left, pObj->m_Bottom, pObj->m_Right, pObj->m_Top); 423 line.Add(pObj); 424 continue; 425 } 426 CFX_FloatRect objRect = CFX_FloatRect(pObj->m_Left, pObj->m_Bottom, pObj->m_Right, pObj->m_Top); 427 if(IsSameLine(TRUE, rect, objRect)) { 428 line.Add(pObj); 429 rect.Union(objRect); 430 } else { 431 prevLine.RemoveAll(); 432 prevLine.Append(line); 433 prevRect = rect; 434 line.RemoveAll(); 435 line.Add(pObj); 436 rect = objRect; 437 if(!bParagraphStart) { 438 if (prevRect.left > rect.left + rect.Height() * 1.5) { 439 bParagraphStart = TRUE; 440 } 441 } 442 } 443 } 444 if(prevLine.GetSize()) { 445 if(FXSYS_fabs(rect.right - prevRect.right) > rect.Height()) { 446 analogial -= 50; 447 } 448 } 449 CPDF_PageObject* pObj = pPrevElement->GetObject(nPrevObj - 1); 450 if(pObj->m_Type == PDFPAGE_TEXT) { 451 CPDF_TextObject* pText = (CPDF_TextObject*)pObj; 452 FX_INT32 nItem = pText->CountItems(); 453 CPDF_TextObjectItem item; 454 pText->GetItemInfo(nItem - 1, &item); 455 CFX_WideString wStr = pText->GetFont()->UnicodeFromCharCode(item.m_CharCode); 456 if(wStr.IsEmpty()) { 457 wStr = (FX_WCHAR)item.m_CharCode; 458 } 459 FX_WCHAR wch = wStr.GetAt(wStr.GetLength() - 1); 460 switch(wch) { 461 case '.': 462 case 12290: 463 case 65311: 464 case 63: 465 case 33: 466 case 65281: 467 analogial -= 50; 468 break; 469 } 470 } 471 prevLine.RemoveAll(); 472 prevLine.Append(line); 473 line.RemoveAll(); 474 FX_INT32 nNextObj = pNextElement->CountObjects(); 475 pPrevObj = NULL; 476 FX_BOOL bFirst = TRUE; 477 for(i = 0; i < nNextObj; i++) { 478 CPDF_PageObject* pObj = pNextElement->GetObject(i); 479 if(!pPrevObj) { 480 pPrevObj = pObj; 481 rect = CFX_FloatRect(pObj->m_Left, pObj->m_Bottom, pObj->m_Right, pObj->m_Top); 482 line.Add(pObj); 483 continue; 484 } 485 CFX_FloatRect objRect = CFX_FloatRect(pObj->m_Left, pObj->m_Bottom, pObj->m_Right, pObj->m_Top); 486 if(IsSameLine(TRUE, rect, objRect)) { 487 line.Add(pObj); 488 rect.Union(objRect); 489 } else { 490 if(FXSYS_fabs(rect.right - prevRect.right) < rect.Height() && FXSYS_fabs(rect.left - prevRect.left) < rect.Height()) { 491 analogial += 50; 492 } 493 prevLine.RemoveAll(); 494 prevLine.Append(line); 495 prevRect = rect; 496 line.RemoveAll(); 497 line.Add(pObj); 498 rect = objRect; 499 if(!bFirst) { 500 break; 501 } 502 bFirst = FALSE; 503 } 504 } 505 if(prevLine.GetSize()) { 506 if(bParagraphStart) { 507 if(prevRect.left - rect.left > rect.Height() && prevRect.left - rect.left < rect.Height() * 3) { 508 analogial -= 50; 509 } 510 } else { 511 if(FXSYS_fabs(prevRect.left - rect.left) < rect.Height()) { 512 analogial -= 50; 513 } 514 } 515 } 516 return analogial; 517 } 518 void CPDF_LayoutProcessor_Reflow::ProcessElement(IPDF_LayoutElement* pElement, FX_FLOAT reflowWidth) 519 { 520 if(pElement == NULL) { 521 return; 522 } 523 if(m_Status == LayoutReady) { 524 LayoutType layoutType = pElement->GetType(); 525 FX_INT32 ElementType = GetElementTypes(layoutType); 526 switch(ElementType) { 527 case SST_IE: 528 m_bIllustration = TRUE; 529 break; 530 case SST_BLSE: 531 FinishedCurrLine(); 532 FX_FLOAT StartIndent = 0; 533 if(IPDF_LayoutElement* pParent = pElement->GetParent()) { 534 StartIndent = pParent->GetNumberAttr(LayoutStartIndent); 535 } 536 FX_FLOAT currStartIndent = pElement->GetNumberAttr(LayoutStartIndent); 537 m_StartIndent = ConverWidth(currStartIndent); 538 FX_FLOAT width = reflowWidth; 539 if(StartIndent != currStartIndent) { 540 reflowWidth -= m_StartIndent; 541 } 542 FX_FLOAT spaceBefore = pElement->GetNumberAttr(LayoutSpaceBefore); 543 m_pReflowedPage->m_PageHeight += spaceBefore; 544 m_TextAlign = pElement->GetEnumAttr(LayoutTextAlign); 545 if(IPDF_LayoutElement* pParent = pElement->GetParent()) { 546 StartIndent = pParent->GetNumberAttr(LayoutEndIndent); 547 FX_FLOAT currEndIndent = pElement->GetNumberAttr(LayoutEndIndent); 548 if(StartIndent != currStartIndent) { 549 reflowWidth -= ConverWidth(currEndIndent); 550 } 551 } 552 if(reflowWidth * 2 < width) { 553 reflowWidth = width; 554 m_StartIndent = 0; 555 } 556 break; 557 } 558 switch(layoutType) { 559 case LayoutTable: { 560 CRF_Table* pTable = FX_NEW CRF_Table; 561 if (NULL == pTable) { 562 break; 563 } 564 m_TableArray.Add(pTable); 565 pTable->m_ReflowPageHeight = m_pReflowedPage->m_PageHeight; 566 pTable->m_TableWidth = GetElmWidth(pElement); 567 break; 568 } 569 case LayoutTableRow: { 570 if(!m_TableArray.GetSize()) { 571 break; 572 } 573 int count = pElement->CountChildren(); 574 CRF_Table* pTable = m_TableArray.GetAt(m_TableArray.GetSize() - 1); 575 int f = 0; 576 for(int i = 0; i < count; i++) { 577 IPDF_LayoutElement* pChildElement = pElement->GetChild(i); 578 LayoutType type = pChildElement->GetType(); 579 if(type == LayoutTableDataCell || type == LayoutTableHeaderCell) { 580 f++; 581 } 582 } 583 pTable->m_nCell.Add(f); 584 break; 585 } 586 case LayoutTableDataCell: 587 case LayoutTableHeaderCell: { 588 if(!m_TableArray.GetSize()) { 589 break; 590 } 591 RF_TableCell* pCell = FX_Alloc(RF_TableCell, 1); 592 FXSYS_memset32(pCell, 0 , sizeof(RF_TableCell)); 593 CRF_Table* pTable = m_TableArray.GetAt(m_TableArray.GetSize() - 1); 594 int pos = pTable->m_nCell.GetSize() - 1; 595 pCell->m_BeginPos = m_pReflowedPage->m_pReflowed->GetSize(); 596 FX_FLOAT cellWidth = pElement->GetNumberAttr(LayoutWidth); 597 if(cellWidth == 0 || pCell->m_MaxWidth > pTable->m_TableWidth) { 598 CRF_Table* pTable = m_TableArray.GetAt(m_TableArray.GetSize() - 1); 599 pCell->m_MaxWidth = reflowWidth / pTable->m_nCell.GetAt(pTable->m_nCell.GetSize() - 1); 600 } else { 601 pCell->m_MaxWidth = pElement->GetNumberAttr(LayoutWidth) * reflowWidth / pTable->m_TableWidth; 602 } 603 pCell->m_ColSpan = (int)(pElement->GetNumberAttr(LayoutColSpan)); 604 pCell->m_RowSpan = (int)(pElement->GetNumberAttr(LayoutRowSpan)); 605 if(!pCell->m_ColSpan) { 606 pCell->m_ColSpan = 1; 607 } 608 if(!pCell->m_RowSpan ) { 609 pCell->m_RowSpan = 1; 610 } 611 pCell->m_BlockAlign = pElement->GetEnumAttr(LayoutBlockAlign); 612 m_TextAlign = pElement->GetEnumAttr(LayoutInlineAlign); 613 pCell->m_PosX = 0; 614 pCell->m_PosY = 0; 615 reflowWidth = pCell->m_MaxWidth; 616 pTable->m_pCellArray.Add(pCell); 617 break; 618 } 619 default: 620 break; 621 } 622 m_fLineHeight = pElement->GetNumberAttr(LayoutLineHeight); 623 int ReflowedSize = m_pReflowedPage->m_pReflowed->GetSize(); 624 if(pElement->CountObjects()) { 625 ProcessObjs(pElement, reflowWidth); 626 } 627 } 628 int count = pElement->CountChildren(); 629 for(int i = 0; i < count; i++) { 630 IPDF_LayoutElement* pChildElement = pElement->GetChild(i); 631 ProcessElement(pChildElement, reflowWidth); 632 if(m_pPause && m_pRootElement == pElement && m_Status != LayoutToBeContinued ) { 633 if(m_pPause->NeedToPauseNow()) { 634 m_pLayoutElement = pChildElement; 635 m_Status = LayoutToBeContinued; 636 m_CurrRefWidth = reflowWidth; 637 m_PausePosition = (i + 1) * 100 / (count + 1); 638 return ; 639 } 640 } 641 if(m_Status == LayoutToBeContinued && m_pLayoutElement == pChildElement) { 642 m_Status = LayoutReady; 643 } 644 } 645 if(m_Status == LayoutReady) { 646 FX_FLOAT dx = 0; 647 LayoutType layoutType = pElement->GetType(); 648 FX_INT32 ElementType = GetElementTypes(layoutType); 649 switch(ElementType) { 650 case SST_IE: 651 m_bIllustration = FALSE; 652 FinishedCurrLine(); 653 break; 654 case SST_BLSE: 655 FinishedCurrLine(); 656 FX_FLOAT StartIndent = 0; 657 if(IPDF_LayoutElement* pParent = pElement->GetParent()) { 658 StartIndent = pParent->GetNumberAttr(LayoutStartIndent); 659 } 660 FX_FLOAT currStartIndent = pElement->GetNumberAttr(LayoutStartIndent); 661 if(StartIndent != currStartIndent) { 662 reflowWidth += ConverWidth(currStartIndent); 663 dx += ConverWidth(currStartIndent); 664 } 665 FX_FLOAT spaceAfter = pElement->GetNumberAttr(LayoutSpaceAfter); 666 m_pReflowedPage->m_PageHeight += spaceAfter; 667 break; 668 } 669 switch(layoutType) { 670 case LayoutTableDataCell: 671 case LayoutTableHeaderCell: { 672 if(!m_TableArray.GetSize()) { 673 break; 674 } 675 CRF_Table* pTable = m_TableArray.GetAt(m_TableArray.GetSize() - 1); 676 RF_TableCell* pCell = pTable->m_pCellArray.GetAt(pTable->m_pCellArray.GetSize() - 1); 677 pCell->m_EndPos = m_pReflowedPage->m_pReflowed->GetSize() - 1; 678 if(pCell->m_EndPos < pCell->m_BeginPos) { 679 pCell->m_CellHeight = 0; 680 } else { 681 CRF_Data* pBeginData = (*m_pReflowedPage->m_pReflowed)[pCell->m_BeginPos]; 682 CRF_Data* pEndData = (*m_pReflowedPage->m_pReflowed)[pCell->m_EndPos]; 683 pCell->m_CellHeight = pBeginData->m_Height > pEndData->m_Height ? pBeginData->m_Height : pEndData->m_Height; 684 pCell->m_CellHeight -= pEndData->m_PosY - pBeginData->m_PosY; 685 } 686 break; 687 } 688 case LayoutTableRow: { 689 if(!m_TableArray.GetSize()) { 690 break; 691 } 692 CRF_Table* pTable = m_TableArray.GetAt(m_TableArray.GetSize() - 1); 693 if(pTable->m_nCol == 0) { 694 pTable->m_nCol = pTable->m_pCellArray.GetSize(); 695 } 696 break; 697 } 698 case LayoutTable: { 699 ProcessTable(dx); 700 break; 701 } 702 default: 703 if(dx) { 704 CFX_AffineMatrix matrix(1, 0, 0, 1, dx, 0); 705 int ReflowedSize = m_pReflowedPage->m_pReflowed->GetSize(); 706 Transform(&matrix, m_pReflowedPage->m_pReflowed, ReflowedSize, m_pReflowedPage->m_pReflowed->GetSize() - ReflowedSize); 707 } 708 } 709 } 710 if(m_pRootElement == pElement) { 711 m_PausePosition = 100; 712 } 713 } 714 FX_INT32 CPDF_LayoutProcessor_Reflow::GetElementTypes(LayoutType layoutType) 715 { 716 switch(layoutType) { 717 case LayoutParagraph: 718 case LayoutHeading: 719 case LayoutHeading1: 720 case LayoutHeading2: 721 case LayoutHeading3: 722 case LayoutHeading4: 723 case LayoutHeading5: 724 case LayoutHeading6: 725 case LayoutList: 726 case LayoutListItem: 727 case LayoutListLabel: 728 case LayoutListBody: 729 case LayoutTable: 730 case LayoutTableHeaderCell: 731 case LayoutTableDataCell: 732 case LayoutTableRow: 733 case LayoutTableHeaderGroup: 734 case LayoutTableBodyGroup: 735 case LayoutTableFootGroup: 736 case LayoutTOCI: 737 case LayoutCaption: 738 return SST_BLSE; 739 case LayoutFigure: 740 case LayoutFormula: 741 case LayoutForm: 742 return SST_IE; 743 case LayoutSpan: 744 case LayoutQuote: 745 case LayoutNote: 746 case LayoutReference: 747 case LayoutBibEntry: 748 case LayoutCode: 749 case LayoutLink: 750 case LayoutAnnot: 751 case LayoutRuby: 752 case LayoutWarichu: 753 return SST_ILSE; 754 default: 755 return SST_GE; 756 } 757 return FALSE; 758 } 759 FX_FLOAT CPDF_LayoutProcessor_Reflow::ConverWidth(FX_FLOAT width) 760 { 761 return width; 762 } 763 void CPDF_LayoutProcessor_Reflow::ProcessObject(CPDF_PageObject* pObj, FX_FLOAT reflowWidth, CFX_AffineMatrix objMatrix) 764 { 765 if(!pObj) { 766 return; 767 } 768 if(pObj->m_Type == PDFPAGE_TEXT) { 769 ProcessTextObject( (CPDF_TextObject *)pObj, reflowWidth, objMatrix); 770 } else if(pObj->m_Type == PDFPAGE_IMAGE) { 771 if(!(m_flags & RF_PARSER_IMAGE)) { 772 return; 773 } 774 CPDF_PageObjects* pObjs = FX_NEW CPDF_PageObjects(FALSE); 775 if (NULL == pObjs) { 776 return; 777 } 778 FX_POSITION pos = pObjs->GetLastObjectPosition(); 779 pos = pObjs->InsertObject(pos, pObj); 780 CFX_AffineMatrix matrix; 781 FX_RECT rect = pObj->GetBBox(&matrix); 782 CPDF_ImageObject* ImageObj = (CPDF_ImageObject*)pObj; 783 ProcessUnitaryObjs(pObjs, reflowWidth, objMatrix); 784 delete pObjs; 785 } else if(pObj->m_Type == PDFPAGE_PATH) { 786 } else if(pObj->m_Type == PDFPAGE_FORM) { 787 CPDF_FormObject* pForm = (CPDF_FormObject*)pObj; 788 FX_POSITION pos = pForm->m_pForm->GetFirstObjectPosition(); 789 objMatrix.Concat(pForm->m_FormMatrix); 790 while (pos) { 791 CPDF_PageObject* pObj1 = pForm->m_pForm->GetNextObject(pos); 792 ProcessObject(pObj1, reflowWidth, objMatrix); 793 } 794 } 795 } 796 void CPDF_LayoutProcessor_Reflow::ProcessObjs(IPDF_LayoutElement* pElement, FX_FLOAT reflowWidth) 797 { 798 m_fCurrMaxWidth = reflowWidth; 799 int ObjCount = pElement->CountObjects(); 800 for(int i = 0; i < ObjCount; i++) { 801 CPDF_PageObject* pObj = pElement->GetObject(i); 802 ProcessObject(pObj, reflowWidth, m_PDFMatrix); 803 continue; 804 } 805 } 806 void CPDF_LayoutProcessor_Reflow::AddTemp2CurrLine(int begin, int count) 807 { 808 if(begin < 0 || count <= 0 || !m_pReflowedPage || !m_pReflowedPage->m_pReflowed || !m_pTempLine) { 809 return; 810 } else { 811 count += begin; 812 } 813 int size = m_pReflowedPage->m_pReflowed->GetSize(); 814 int temps = m_pTempLine->GetSize(); 815 for(int i = begin; i < count; i++) { 816 CRF_Data* pData = (*m_pTempLine)[i]; 817 AddData2CurrLine(pData); 818 } 819 } 820 void CPDF_LayoutProcessor_Reflow::AddData2CurrLine(CRF_Data* pData) 821 { 822 if(pData == NULL || m_pCurrLine == NULL) { 823 return; 824 } 825 m_pCurrLine->Add(pData); 826 m_fCurrLineWidth = pData->m_PosX + pData->m_Width; 827 if(pData->m_Height > m_fCurrLineHeight) { 828 m_fCurrLineHeight = pData->m_Height; 829 } 830 } 831 void CPDF_LayoutProcessor_Reflow::UpdateCurrLine() 832 { 833 } 834 void CPDF_LayoutProcessor_Reflow::Transform(const CFX_AffineMatrix* pMatrix, CRF_DataPtrArray* pDataArray, int beginPos, int count) 835 { 836 if (!pDataArray) { 837 return; 838 } 839 if(count == 0) { 840 count = pDataArray->GetSize(); 841 } else { 842 count += beginPos; 843 } 844 for(int i = beginPos; i < count; i++) { 845 CRF_Data* pData = (*pDataArray)[i]; 846 Transform(pMatrix, pData); 847 } 848 } 849 void CPDF_LayoutProcessor_Reflow::Transform(const CFX_AffineMatrix* pMatrix, CRF_Data* pData) 850 { 851 if(pData->GetType() == CRF_Data::Path) { 852 CRF_PathData* pPathData = (CRF_PathData*)pData; 853 pPathData->m_pPath2Device.Concat(*pMatrix); 854 } 855 pMatrix->Transform(pData->m_PosX, pData->m_PosY, pData->m_PosX, pData->m_PosY); 856 } 857 FX_BOOL CPDF_LayoutProcessor_Reflow::FinishedCurrLine() 858 { 859 if (NULL == m_pCurrLine) { 860 return FALSE; 861 } 862 int count = m_pCurrLine->GetSize(); 863 if(count == 0) { 864 return FALSE; 865 } 866 if(m_fLineHeight > m_fCurrLineHeight) { 867 m_fCurrLineHeight = m_fLineHeight; 868 } else { 869 m_fCurrLineHeight += 2; 870 } 871 if(m_pReflowedPage->m_pReflowed->GetSize() > 0) { 872 m_fCurrLineHeight += m_fLineSpace; 873 } 874 FX_FLOAT height = m_pReflowedPage->m_PageHeight + m_fCurrLineHeight; 875 FX_FLOAT lineHeight = m_fLineHeight; 876 if(lineHeight == 0) { 877 lineHeight = m_fCurrLineHeight; 878 } 879 FX_FLOAT dx = 0; 880 switch(m_TextAlign) { 881 case LayoutCenter: 882 dx = (m_fCurrMaxWidth - m_fCurrLineWidth) / 2; 883 break; 884 case LayoutEnd: 885 dx = m_fCurrMaxWidth - m_fCurrLineWidth; 886 break; 887 case LayoutJustify: 888 break; 889 default: 890 break; 891 } 892 FX_FLOAT dy = - height; 893 int refedSize = m_pReflowedPage->m_pReflowed->GetSize(); 894 if(count == 13) { 895 int a = 0; 896 } 897 for(int i = 0; i < count; i++) { 898 CRF_Data* pData = (*m_pCurrLine)[i]; 899 m_pReflowedPage->m_pReflowed->Add(pData); 900 FX_FLOAT x = m_StartIndent + dx * (m_TextAlign == LayoutJustify ? i + 1 : 1); 901 CFX_AffineMatrix matrix(1, 0, 0, 1, x, dy); 902 Transform(&matrix, pData); 903 } 904 m_pCurrLine->RemoveAll(); 905 m_fCurrLineWidth = 0; 906 m_pReflowedPage->m_PageHeight += m_fCurrLineHeight; 907 m_fCurrLineHeight = 0; 908 return TRUE; 909 } 910 CRF_CharState* CPDF_LayoutProcessor_Reflow::GetCharState(CPDF_TextObject* pObj, CPDF_Font* pFont, FX_FLOAT fHeight, FX_ARGB color) 911 { 912 if (NULL == m_pReflowedPage->m_pCharState) { 913 return NULL; 914 } 915 int count = m_pReflowedPage->m_pCharState->GetSize(); 916 for(int i = count - 1; i >= 0; i--) { 917 CRF_CharState* pState = (CRF_CharState*)m_pReflowedPage->m_pCharState->GetAt(i); 918 if(pState->m_Color == color && pState->m_fFontSize == fHeight && pState->m_pFont == pFont && pState->m_pTextObj == pObj) { 919 return pState; 920 } 921 } 922 CRF_CharState pState; 923 pState.m_pTextObj = pObj; 924 pState.m_Color = color; 925 pState.m_pFont = pFont; 926 pState.m_fFontSize = fHeight; 927 int ascent = pFont->GetTypeAscent(); 928 int descent = pFont->GetTypeDescent(); 929 pState.m_fAscent = ascent * fHeight / (ascent - descent); 930 if(descent == 0) { 931 pState.m_fDescent = 0; 932 } else { 933 pState.m_fDescent = descent * fHeight / (ascent - descent); 934 } 935 pState.m_bVert = FALSE; 936 CPDF_CIDFont *pCIDFont = pFont->GetCIDFont(); 937 if(pCIDFont) { 938 pState.m_bVert = pCIDFont->IsVertWriting(); 939 } 940 m_pReflowedPage->m_pCharState->Add(pState); 941 return (CRF_CharState*)m_pReflowedPage->m_pCharState->GetAt(count); 942 } 943 int CPDF_LayoutProcessor_Reflow::GetCharWidth(FX_DWORD charCode, CPDF_Font* pFont) const 944 { 945 if(charCode == -1) { 946 return 0; 947 } 948 int w = pFont->GetCharWidthF(charCode); 949 if(w == 0) { 950 CFX_ByteString str; 951 pFont->AppendChar(str, charCode); 952 w = pFont->GetStringWidth(str, 1); 953 if(w == 0) { 954 FX_RECT BBox; 955 pFont->GetCharBBox(charCode, BBox); 956 w = BBox.right - BBox.left; 957 } 958 } 959 return w; 960 } 961 void CPDF_LayoutProcessor_Reflow::CreateRFData(CPDF_PageObject* pObj, CFX_AffineMatrix* pObjMatrix) 962 { 963 if (NULL == m_pReflowedPage->m_pMemoryPool) { 964 return; 965 } 966 if(pObj->m_Type == PDFPAGE_TEXT) { 967 CPDF_TextObject* pTextObj = (CPDF_TextObject* )pObj; 968 int count = pTextObj->CountItems(); 969 if(!count) { 970 return; 971 } 972 if(count == 1) { 973 CPDF_TextObjectItem Item; 974 pTextObj->GetItemInfo(0, &Item); 975 if(Item.m_CharCode == 49) { 976 int a = 0; 977 } 978 } 979 CPDF_Font * pFont = pTextObj->GetFont(); 980 FX_FLOAT fs = pTextObj->GetFontSize(); 981 FX_FLOAT* pmatrix = pTextObj->m_TextState.GetMatrix(); 982 FX_FLOAT matrix1 = pmatrix[1]; 983 if(pmatrix[2] == 0) { 984 matrix1 = 0; 985 } 986 CFX_AffineMatrix textMatrix(pmatrix[0], matrix1, pmatrix[2], pmatrix[3], 0, 0); 987 FX_FLOAT height = FXSYS_fabs(textMatrix.TransformDistance(fs)); 988 if(pObjMatrix) { 989 height = FXSYS_fabs(pObjMatrix->TransformDistance(height)); 990 } 991 int r = 0, g = 0, b = 0; 992 pTextObj->m_ColorState.GetFillColor()->GetRGB(r, g, b); 993 FX_ARGB col = r * 0x10000; 994 col += g * 0x100; 995 col += b; 996 CRF_CharState* pState = GetCharState(pTextObj, pFont, height, col); 997 FX_FLOAT dx = 0, dy = 0; 998 FX_RECT ObjBBox; 999 if(pObjMatrix) { 1000 ObjBBox = pTextObj->GetBBox(pObjMatrix); 1001 dx = (float)ObjBBox.left; 1002 dy = (float)ObjBBox.bottom; 1003 } else { 1004 CFX_AffineMatrix matrix; 1005 ObjBBox = pTextObj->GetBBox(&matrix); 1006 } 1007 FX_FLOAT objWidth = 0; 1008 CFX_ByteString str; 1009 FX_BOOL bOrder = TRUE; 1010 CFX_PtrArray tempArray; 1011 int i = 0; 1012 CPDF_TextObjectItem Item; 1013 pTextObj->GetItemInfo(i, &Item); 1014 dx = Item.m_OriginX; 1015 dy = Item.m_OriginY; 1016 textMatrix.Transform(Item.m_OriginX, Item.m_OriginY, dx, dy); 1017 CRF_CharData* pLastData = NULL; 1018 FX_FLOAT horzScale = pTextObj->m_TextState.GetFontSizeV() / pTextObj->m_TextState.GetFontSizeH(); 1019 while(i < count) { 1020 pTextObj->GetItemInfo(i, &Item); 1021 if(Item.m_CharCode == -1) { 1022 i++; 1023 continue; 1024 } 1025 FX_FLOAT OriginX, OriginY; 1026 textMatrix.Transform(Item.m_OriginX, Item.m_OriginY, OriginX, OriginY); 1027 CRF_CharData* pData = (CRF_CharData*)m_pReflowedPage->m_pMemoryPool->Alloc(sizeof(CRF_CharData)); 1028 if (NULL == pData) { 1029 continue; 1030 } 1031 pData->m_Type = CRF_Data::Text; 1032 if(FXSYS_fabs(OriginY - dy) > FXSYS_fabs(OriginX - dx)) { 1033 pData->m_PosY = dy; 1034 pData->m_PosX = pLastData->m_PosX + pLastData->m_Width + textMatrix.TransformDistance(pTextObj->m_TextState.GetObject()->m_CharSpace); 1035 } else { 1036 pData->m_PosY = OriginY; 1037 pData->m_PosX = OriginX; 1038 } 1039 int size = tempArray.GetSize(); 1040 if(size && pData->m_PosX < pLastData->m_PosX ) { 1041 for (int j = 0; j < size; j++) { 1042 CRF_CharData* pData1 = (CRF_CharData*)tempArray.GetAt(j); 1043 if(pData1->m_PosX > pData->m_PosX) { 1044 tempArray.InsertAt(j, pData); 1045 break; 1046 } 1047 } 1048 } else { 1049 tempArray.Add(pData); 1050 } 1051 pLastData = pData; 1052 pData->m_CharCode = Item.m_CharCode; 1053 pData->m_Height = FXSYS_fabs(height); 1054 int w = GetCharWidth(Item.m_CharCode, pFont); 1055 pData->m_Width = FXSYS_fabs(fs * textMatrix.TransformDistance((FX_FLOAT)w) / 1000); 1056 if(horzScale) { 1057 pData->m_Width /= horzScale; 1058 } 1059 pData->m_pCharState = pState; 1060 i++; 1061 } 1062 count = tempArray.GetSize(); 1063 for (int j = 0; j < count; j++) { 1064 CRF_CharData* pData = (CRF_CharData*)tempArray.GetAt(j); 1065 if (m_pTempLine) { 1066 m_pTempLine->Add(pData); 1067 } 1068 } 1069 tempArray.RemoveAll(); 1070 } else if(pObj->m_Type == PDFPAGE_IMAGE) { 1071 CPDF_ImageObject* pImageObj = (CPDF_ImageObject* )pObj; 1072 CRF_ImageData* pRFImage = (CRF_ImageData*)m_pReflowedPage->m_pMemoryPool->Alloc(sizeof(CRF_ImageData)); 1073 if (NULL == pRFImage) { 1074 return; 1075 } 1076 pRFImage->m_pBitmap = NULL; 1077 pRFImage->m_Type = CRF_Data::Image; 1078 if (m_pTempLine) { 1079 m_pTempLine->Add(pRFImage); 1080 } 1081 CPDF_Image *pImage = pImageObj->m_pImage; 1082 if (!pImage->m_pDIBSource || !pImage->m_pMask) { 1083 if(pImage->StartLoadDIBSource(m_pReflowedPage->GetFormResDict(pImageObj), m_pReflowedPage->m_pPDFPage->m_pResources, 0, 0, TRUE)) { 1084 pImage->Continue(NULL); 1085 } 1086 } 1087 CFX_DIBSource* pDibSource = pImage->DetachBitmap(); 1088 if (pDibSource) { 1089 pRFImage->m_pBitmap = pDibSource->Clone(); 1090 delete pDibSource; 1091 } 1092 CFX_DIBSource* pMask = pImage->DetachMask(); 1093 if (pMask) { 1094 if (!pMask->IsAlphaMask()) { 1095 CFX_DIBitmap* pMaskBmp = pMask->Clone(); 1096 pMaskBmp->ConvertFormat(FXDIB_8bppMask); 1097 pRFImage->m_pBitmap->MultiplyAlpha(pMaskBmp); 1098 delete pMaskBmp; 1099 } else { 1100 pRFImage->m_pBitmap->MultiplyAlpha(pMask); 1101 } 1102 delete pMask; 1103 } 1104 CFX_FloatRect ObjBBox; 1105 if(pObjMatrix) { 1106 ObjBBox = pImageObj->GetBBox(pObjMatrix); 1107 } else { 1108 CFX_AffineMatrix matrix; 1109 ObjBBox = pImageObj->GetBBox(&matrix); 1110 } 1111 pRFImage->m_Width = ObjBBox.Width(); 1112 pRFImage->m_Height = ObjBBox.Height(); 1113 pRFImage->m_PosX = 0; 1114 pRFImage->m_PosY = 0; 1115 CFX_AffineMatrix matrix(1, 0, 0, -1, 0, 0); 1116 matrix.Concat(pImageObj->m_Matrix); 1117 matrix.Concat(*pObjMatrix); 1118 pRFImage->m_Matrix.Set(matrix.a == 0 ? 0 : matrix.a / FXSYS_fabs(matrix.a), 1119 matrix.b == 0 ? 0 : matrix.b / FXSYS_fabs(matrix.b), 1120 matrix.c == 0 ? 0 : matrix.c / FXSYS_fabs(matrix.c), 1121 matrix.d == 0 ? 0 : matrix.d / FXSYS_fabs(matrix.d), 0, 0); 1122 } else if(pObj->m_Type == PDFPAGE_PATH) { 1123 } 1124 } 1125 FX_FLOAT CPDF_LayoutProcessor_Reflow:: GetDatasWidth(int beginPos, int endpos) 1126 { 1127 if(endpos < beginPos || !m_pTempLine) { 1128 return 0; 1129 } 1130 if(endpos > m_pTempLine->GetSize() - 1) { 1131 endpos = m_pTempLine->GetSize() - 1; 1132 } 1133 CRF_Data* pBeginData = (*m_pTempLine)[beginPos]; 1134 CRF_Data* pEndData = (*m_pTempLine)[endpos]; 1135 return pEndData->m_PosX - pBeginData->m_PosX + pEndData->m_Width; 1136 } 1137 FX_WCHAR CPDF_LayoutProcessor_Reflow::GetPreChar() 1138 { 1139 if (NULL == m_pCurrLine) { 1140 return -1; 1141 } 1142 int index = m_pCurrLine->GetSize() - 1; 1143 CRF_CharData* pCharData = NULL; 1144 while (index >= 0 && !pCharData) { 1145 CRF_Data* pData = (*m_pCurrLine)[index]; 1146 if(pData->GetType() == CRF_Data::Text) { 1147 pCharData = (CRF_CharData*)pData; 1148 } else { 1149 return -1; 1150 } 1151 index --; 1152 } 1153 if(m_pReflowedPage) { 1154 index = m_pReflowedPage->m_pReflowed->GetSize() - 1; 1155 } 1156 while(!pCharData && index >= 0) { 1157 CRF_Data* pData = (*m_pReflowedPage->m_pReflowed)[index]; 1158 if(pData->GetType() == CRF_Data::Text) { 1159 pCharData = (CRF_CharData*)pData; 1160 } else { 1161 return -1; 1162 } 1163 index --; 1164 } 1165 if(pCharData) { 1166 CFX_WideString str = pCharData->m_pCharState->m_pFont->UnicodeFromCharCode(pCharData->m_CharCode); 1167 return str.GetAt(0); 1168 } 1169 return -1; 1170 } 1171 int CPDF_LayoutProcessor_Reflow::ProcessInsertObject(CPDF_TextObject* pObj, CFX_AffineMatrix formMatrix) 1172 { 1173 if(!pObj || !m_pPreObj || !m_pCurrLine) { 1174 return 0; 1175 } 1176 if(m_pCurrLine->GetSize() == 0) { 1177 return 0; 1178 } 1179 CPDF_TextObjectItem item; 1180 int nItem = m_pPreObj->CountItems(); 1181 m_pPreObj->GetItemInfo(nItem - 1, &item); 1182 FX_FLOAT last_pos = item.m_OriginX; 1183 FX_FLOAT last_width = GetCharWidth(item.m_CharCode, m_pPreObj->GetFont()) * m_pPreObj->GetFontSize() / 1000; 1184 last_width = FXSYS_fabs(last_width); 1185 pObj->GetItemInfo(0, &item); 1186 FX_FLOAT this_width = GetCharWidth(item.m_CharCode, pObj->GetFont()) * pObj->GetFontSize() / 1000; 1187 this_width = FXSYS_fabs(this_width); 1188 FX_FLOAT threshold = last_width > this_width ? last_width / 4 : this_width / 4; 1189 CFX_AffineMatrix prev_matrix, prev_reverse; 1190 m_pPreObj->GetTextMatrix(&prev_matrix); 1191 prev_matrix.Concat(m_perMatrix); 1192 prev_reverse.SetReverse(prev_matrix); 1193 FX_FLOAT x = pObj->GetPosX(), y = pObj->GetPosY(); 1194 formMatrix.Transform(x, y); 1195 prev_reverse.Transform(x, y); 1196 FX_WCHAR preChar = GetPreChar(); 1197 CFX_WideString wstrItem = pObj->GetFont()->UnicodeFromCharCode(item.m_CharCode); 1198 FX_WCHAR curChar = wstrItem.GetAt(0); 1199 if (FXSYS_fabs(y) > threshold * 2) { 1200 if (preChar == L'-') { 1201 return 3; 1202 } 1203 if (preChar != L' ') { 1204 return 1; 1205 } 1206 return 2; 1207 } 1208 if ((x - last_pos - last_width) > threshold && curChar != L' ' && preChar != L' ') { 1209 return 1; 1210 } 1211 return 0; 1212 } 1213 FX_INT32 CPDF_LayoutProcessor_Reflow::LogicPreObj(CPDF_TextObject* pObj) 1214 { 1215 CPDF_TextObject* pPreObj = m_pPreObj; 1216 m_pPreObj = pObj; 1217 if(!pObj || !pPreObj) { 1218 return 0; 1219 } 1220 CPDF_TextObjectItem item; 1221 pPreObj->GetItemInfo(pPreObj->CountItems() - 1, &item); 1222 FX_FLOAT last_pos = item.m_OriginX; 1223 FX_FLOAT last_width = pPreObj->GetFont()->GetCharWidthF(item.m_CharCode) * pPreObj->GetFontSize() / 1000; 1224 last_width = FXSYS_fabs(last_width); 1225 pObj->GetItemInfo(0, &item); 1226 FX_FLOAT this_width = pObj->GetFont()->GetCharWidthF(item.m_CharCode) * pObj->GetFontSize() / 1000; 1227 this_width = FXSYS_fabs(this_width); 1228 FX_FLOAT threshold = last_width > this_width ? last_width / 4 : this_width / 4; 1229 CFX_AffineMatrix prev_matrix, prev_reverse; 1230 pPreObj->GetTextMatrix(&prev_matrix); 1231 prev_reverse.SetReverse(prev_matrix); 1232 FX_FLOAT x = pObj->GetPosX(), y = pObj->GetPosY(); 1233 prev_reverse.Transform(x, y); 1234 CFX_WideString wstrItem = pObj->GetFont()->UnicodeFromCharCode(item.m_CharCode); 1235 FX_WCHAR curChar = wstrItem.GetAt(0); 1236 if (FXSYS_fabs(y) > threshold * 2) { 1237 return 2; 1238 } 1239 FX_WCHAR preChar = 0; 1240 if (FXSYS_fabs(last_pos + last_width - x) > threshold && curChar != L' ') { 1241 return 1; 1242 } 1243 return 0; 1244 m_pPreObj = pObj; 1245 if(!pPreObj) { 1246 return 0; 1247 } 1248 if(pPreObj->m_Type != pObj->m_Type) { 1249 return 0; 1250 } 1251 CFX_FloatRect rcCurObj(pObj->m_Left, pObj->m_Bottom, pObj->m_Right, pObj->m_Top); 1252 CFX_FloatRect rcPreObj(pPreObj->m_Left, pPreObj->m_Bottom, pPreObj->m_Right, pPreObj->m_Top); 1253 if(pObj->m_Type == PDFPAGE_IMAGE) { 1254 if(rcPreObj.Contains(rcCurObj)) { 1255 return 2; 1256 } 1257 if(rcCurObj.Contains(rcPreObj)) { 1258 return 2; 1259 } 1260 return 0; 1261 } 1262 if(pObj->m_Type == PDFPAGE_TEXT) { 1263 if(!((rcPreObj.bottom > rcCurObj.top) || (rcPreObj.top < rcCurObj.bottom))) { 1264 FX_FLOAT height = FX_MIN(rcPreObj.Height(), rcCurObj.Height()); 1265 if((rcCurObj.left - rcPreObj.right) > height / 3) { 1266 return 3; 1267 } 1268 } 1269 if(FXSYS_fabs(rcPreObj.Width() - rcCurObj.Width()) >= 2 || FXSYS_fabs(rcPreObj.Height() - rcCurObj.Height()) >= 2 ) { 1270 return 0; 1271 } 1272 CPDF_TextObject* pPreTextObj = (CPDF_TextObject*)pPreObj; 1273 CPDF_TextObject* pCurTextObj = (CPDF_TextObject*)pObj; 1274 int nPreCount = pPreTextObj->CountItems(); 1275 int nCurCount = pCurTextObj->CountItems(); 1276 if (nPreCount != nCurCount) { 1277 return 0; 1278 } 1279 FX_BOOL bSame = TRUE; 1280 for (int i = 0; i < nPreCount; i++) { 1281 CPDF_TextObjectItem itemPer, itemCur; 1282 pPreTextObj->GetItemInfo(i, &itemPer); 1283 pCurTextObj->GetItemInfo(i, &itemCur); 1284 if (itemCur.m_CharCode != itemPer.m_CharCode) { 1285 return 0; 1286 } 1287 if (itemCur.m_OriginX != itemPer.m_OriginX) { 1288 bSame = FALSE; 1289 } 1290 if (itemCur.m_OriginY != itemPer.m_OriginY) { 1291 bSame = FALSE; 1292 } 1293 } 1294 if(rcPreObj.left == rcCurObj.left && rcPreObj.top == rcCurObj.top) { 1295 return 1; 1296 } 1297 if(FXSYS_fabs(rcPreObj.left - rcCurObj.left) < rcPreObj.Width() / 3 1298 && FXSYS_fabs(rcPreObj.top - rcCurObj.top) < rcPreObj.Height() / 3) { 1299 return 2; 1300 } 1301 } 1302 return 0; 1303 } 1304 FX_BOOL CPDF_LayoutProcessor_Reflow::IsSameTextObject(CPDF_TextObject* pTextObj1, CPDF_TextObject* pTextObj2) 1305 { 1306 if (!pTextObj1 || !pTextObj2) { 1307 return FALSE; 1308 } 1309 CFX_FloatRect rcPreObj(pTextObj2->m_Left, pTextObj2->m_Bottom, pTextObj2->m_Right, pTextObj2->m_Top); 1310 CFX_FloatRect rcCurObj(pTextObj1->m_Left, pTextObj1->m_Bottom, pTextObj1->m_Right, pTextObj1->m_Top); 1311 if (rcPreObj.IsEmpty() && rcCurObj.IsEmpty()) { 1312 return FALSE; 1313 } 1314 if (!rcPreObj.IsEmpty() || !rcCurObj.IsEmpty()) { 1315 rcPreObj.Intersect(rcCurObj); 1316 if (rcPreObj.IsEmpty()) { 1317 return FALSE; 1318 } 1319 if (FXSYS_fabs(rcPreObj.Width() - rcCurObj.Width()) > rcCurObj.Width() / 2) { 1320 return FALSE; 1321 } 1322 if (pTextObj2->GetFontSize() != pTextObj1->GetFontSize()) { 1323 return FALSE; 1324 } 1325 } 1326 int nPreCount = pTextObj2->CountItems(); 1327 int nCurCount = pTextObj1->CountItems(); 1328 if (nPreCount != nCurCount) { 1329 return FALSE; 1330 } 1331 for (int i = 0; i < nPreCount; i++) { 1332 CPDF_TextObjectItem itemPer, itemCur; 1333 pTextObj2->GetItemInfo(i, &itemPer); 1334 pTextObj1->GetItemInfo(i, &itemCur); 1335 if (itemCur.m_CharCode != itemPer.m_CharCode) { 1336 return FALSE; 1337 } 1338 } 1339 return TRUE; 1340 } 1341 void CPDF_LayoutProcessor_Reflow::ProcessTextObject(CPDF_TextObject *pTextObj, FX_FLOAT reflowWidth, CFX_AffineMatrix objMatrix) 1342 { 1343 if(reflowWidth < 0 || !m_pCurrLine || !m_pTempLine) { 1344 return; 1345 } 1346 if(IsSameTextObject(pTextObj, m_pPreObj)) { 1347 return; 1348 } 1349 CPDF_PageObject* pPreObj = m_pPreObj; 1350 FX_INT32 logic = ProcessInsertObject(pTextObj, objMatrix); 1351 m_pPreObj = pTextObj; 1352 m_perMatrix.Copy(objMatrix); 1353 int size = m_pTempLine->GetSize(); 1354 int curs = m_pCurrLine->GetSize(); 1355 CreateRFData(pTextObj); 1356 size = m_pTempLine->GetSize(); 1357 int reds = m_pReflowedPage->m_pReflowed->GetSize(); 1358 if(size == 0) { 1359 return; 1360 } 1361 if(logic == 1) { 1362 m_fCurrLineWidth += pTextObj->GetBBox(&objMatrix).Height() / 3; 1363 } else if(logic == 3 && curs) { 1364 m_fCurrLineWidth -= (*m_pCurrLine)[curs - 1]->m_Width; 1365 m_pCurrLine->Delete(curs - 1); 1366 } 1367 int beginPos = 0, endPos = m_pTempLine->GetSize() - 1; 1368 while(beginPos <= endPos) { 1369 int tempBeginPos = beginPos; 1370 int tempEndPos = endPos; 1371 FX_FLOAT all_width = GetDatasWidth( beginPos, endPos); 1372 if(all_width < reflowWidth - m_fCurrLineWidth) { 1373 CRF_CharData* pBeginData = (CRF_CharData*)(*m_pTempLine)[beginPos]; 1374 CFX_AffineMatrix matrix(1, 0, 0, 1, -pBeginData->m_PosX + m_fCurrLineWidth, -pBeginData->m_PosY); 1375 Transform(&matrix, m_pTempLine, beginPos, endPos - beginPos + 1); 1376 AddTemp2CurrLine(beginPos, endPos - beginPos + 1); 1377 m_pTempLine->RemoveAll(); 1378 return; 1379 } 1380 int midPos ; 1381 if(tempBeginPos >= tempEndPos && tempEndPos != 0) { 1382 midPos = tempEndPos; 1383 } else { 1384 while (tempBeginPos < tempEndPos ) { 1385 midPos = (tempEndPos - tempBeginPos) / 2 + tempBeginPos; 1386 if(midPos == tempBeginPos || midPos == tempEndPos) { 1387 break; 1388 } 1389 FX_FLOAT w = GetDatasWidth( beginPos, midPos); 1390 if(w < reflowWidth - m_fCurrLineWidth) { 1391 tempBeginPos = midPos; 1392 } else { 1393 tempEndPos = midPos; 1394 } 1395 } 1396 midPos = tempBeginPos; 1397 if(midPos == 0) { 1398 FX_FLOAT w = GetDatasWidth( beginPos, 1); 1399 if(w > reflowWidth - m_fCurrLineWidth) { 1400 midPos = -1; 1401 } 1402 } 1403 } 1404 if(midPos == -1) { 1405 int count = m_pCurrLine->GetSize(); 1406 if(count == 0) { 1407 midPos = 0; 1408 } 1409 } 1410 int f = -1; 1411 int i = 0; 1412 for(i = midPos; i >= beginPos; i--) { 1413 CRF_CharData* pData = (CRF_CharData*)(*m_pTempLine)[i]; 1414 CFX_WideString Wstr = pData->m_pCharState->m_pFont->UnicodeFromCharCode(pData->m_CharCode); 1415 FX_WCHAR cha = Wstr.GetAt(0); 1416 if(i < m_pTempLine->GetSize() - 1) { 1417 CRF_CharData* pNextData = (CRF_CharData*)(*m_pTempLine)[i + 1]; 1418 if(pNextData->m_PosX - (pData->m_PosX + pData->m_Width) >= pData->m_Height / 4) { 1419 f = i; 1420 i++; 1421 } 1422 } 1423 if(f == -1) { 1424 if(IsCanBreakAfter((FX_DWORD)cha)) { 1425 f = i; 1426 i++; 1427 } else if(IsCanBreakBefore((FX_DWORD)cha)) { 1428 f = i - 1; 1429 if(f < beginPos) { 1430 f = -1; 1431 } 1432 } 1433 } 1434 if(f != -1) { 1435 CRF_CharData* pBeginData = (CRF_CharData*)(*m_pTempLine)[beginPos]; 1436 CFX_AffineMatrix matrix(1, 0, 0, 1, -pBeginData->m_PosX + m_fCurrLineWidth, -pBeginData->m_PosY); 1437 Transform(&matrix, m_pTempLine, beginPos, f - beginPos + 1); 1438 CRF_Data* pData = (*m_pTempLine)[0]; 1439 AddTemp2CurrLine(beginPos, f - beginPos + 1); 1440 beginPos = i; 1441 FinishedCurrLine(); 1442 f = 1; 1443 break; 1444 } 1445 } 1446 if(f == -1 && i < beginPos) { 1447 if( m_pCurrLine->GetSize()) { 1448 int count = m_pCurrLine->GetSize(); 1449 f = -1; 1450 for(int i = count - 1; i >= 0; i--) { 1451 CRF_Data* pData = (*m_pCurrLine)[i]; 1452 if(pData->GetType() != CRF_Data::Text) { 1453 f = i + 1; 1454 } else { 1455 CRF_CharData* pCharData = (CRF_CharData*)pData; 1456 CFX_WideString Wstr = pCharData->m_pCharState->m_pFont->UnicodeFromCharCode(pCharData->m_CharCode); 1457 FX_WCHAR cha = Wstr.GetAt(0); 1458 if(IsCanBreakAfter(cha)) { 1459 f = i + 1; 1460 i++; 1461 } else if(IsCanBreakBefore(cha)) { 1462 f = i; 1463 } 1464 if(f == 0) { 1465 f = -1; 1466 } 1467 } 1468 if(f != -1) { 1469 FinishedCurrLine(); 1470 if(f < count) { 1471 int reflowdCount = m_pReflowedPage->m_pReflowed->GetSize(); 1472 int pos = reflowdCount + f - count; 1473 CRF_CharData* pData = (CRF_CharData*)(*m_pReflowedPage->m_pReflowed)[pos]; 1474 CFX_AffineMatrix matrix(1, 0, 0, 1, -pData->m_PosX + m_fCurrLineWidth, -pData->m_PosY); 1475 Transform(&matrix, m_pReflowedPage->m_pReflowed, pos, reflowdCount - pos); 1476 for(int j = pos; j < reflowdCount; j++) { 1477 AddData2CurrLine((*m_pReflowedPage->m_pReflowed)[j]); 1478 } 1479 m_pReflowedPage->m_pReflowed->Delete(pos, count - f); 1480 if(logic == 3) { 1481 m_fCurrLineWidth += pTextObj->GetBBox(&objMatrix).Height() / 3; 1482 } 1483 } 1484 break; 1485 } 1486 } 1487 } 1488 if(f == -1) { 1489 CRF_CharData* pData = (CRF_CharData*)(*m_pTempLine)[beginPos]; 1490 CFX_AffineMatrix matrix(1, 0, 0, 1, -pData->m_PosX + m_fCurrLineWidth, -pData->m_PosY); 1491 if(beginPos == midPos) { 1492 Transform(&matrix, pData); 1493 FX_RECT rect; 1494 pData->m_pCharState->m_pFont->GetFontBBox(rect); 1495 FX_FLOAT* pmatrix = pTextObj->m_TextState.GetMatrix(); 1496 CFX_AffineMatrix textMatrix(pmatrix[0], pmatrix[1], pmatrix[2], pmatrix[3], 0, 0); 1497 FX_FLOAT width = pData->m_Height * (rect.right - rect.left) / 1000; 1498 FX_FLOAT f = (reflowWidth - m_fCurrLineWidth) / width; 1499 pData->m_PosY *= f; 1500 pData->m_Width *= f; 1501 pData->m_Height *= f; 1502 pData->m_pCharState = GetCharState(pData->m_pCharState->m_pTextObj, pData->m_pCharState->m_pFont, pData->m_Height, pData->m_pCharState->m_Color); 1503 AddData2CurrLine(pData); 1504 } else { 1505 for(int m = beginPos; m <= midPos; m++) { 1506 CRF_CharData* pData = (CRF_CharData*)(*m_pTempLine)[m]; 1507 Transform(&matrix, pData); 1508 AddData2CurrLine(pData); 1509 } 1510 } 1511 FinishedCurrLine(); 1512 beginPos = midPos + 1; 1513 } 1514 } 1515 } 1516 m_pTempLine->RemoveAll(); 1517 return; 1518 } 1519 void CPDF_LayoutProcessor_Reflow::ProcessUnitaryObjs(CPDF_PageObjects *pObjs, FX_FLOAT reflowWidth, CFX_AffineMatrix objMatrix) 1520 { 1521 if(!pObjs) { 1522 return; 1523 } 1524 CFX_FloatRect ObjBBox = pObjs->CalcBoundingBox(); 1525 objMatrix.TransformRect(ObjBBox); 1526 FX_FLOAT ObjWidth = ObjBBox.Width(); 1527 FX_FLOAT ObjHeight = ObjBBox.Height(); 1528 CFX_AffineMatrix matrix; 1529 if(ObjWidth <= reflowWidth - m_fCurrLineWidth) { 1530 matrix.Set(1, 0, 0, 1, m_fCurrLineWidth , 0); 1531 } else if(ObjWidth <= reflowWidth) { 1532 FinishedCurrLine(); 1533 matrix.Set(1, 0, 0, 1, 0, 0); 1534 } else { 1535 FinishedCurrLine(); 1536 FX_FLOAT f = reflowWidth / ObjWidth ; 1537 matrix.Set(f, 0, 0, f, 0, 0); 1538 } 1539 CFX_AffineMatrix tempMatrix = matrix; 1540 matrix.Concat(objMatrix); 1541 FX_POSITION pos = pObjs->GetFirstObjectPosition(); 1542 while(pos) { 1543 CPDF_PageObject* pObj = pObjs->GetNextObject(pos); 1544 if(pObj->m_Type == PDFPAGE_TEXT) { 1545 FX_INT32 ret = LogicPreObj((CPDF_TextObject*)pObj); 1546 if(ret == 1 || ret == 2) { 1547 continue; 1548 } 1549 } 1550 CreateRFData(pObj, &matrix); 1551 } 1552 if (m_pTempLine) { 1553 Transform(&tempMatrix, m_pTempLine, 0, m_pTempLine->GetSize()); 1554 AddTemp2CurrLine(0, m_pTempLine->GetSize()); 1555 m_pTempLine->RemoveAll(); 1556 } 1557 } 1558 void CPDF_LayoutProcessor_Reflow::ProcessPathObject(CPDF_PathObject *pObj, FX_FLOAT reflowWidth) 1559 { 1560 } 1561