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 <algorithm> 8 9 #include "core/include/fxcrt/fx_ext.h" 10 #include "fpdfsdk/include/fsdk_baseannot.h" 11 #include "fpdfsdk/include/fsdk_define.h" 12 #include "fpdfsdk/include/fsdk_mgr.h" 13 14 #ifdef PDF_ENABLE_XFA 15 #include "fpdfsdk/include/fpdfxfa/fpdfxfa_doc.h" 16 #endif // PDF_ENABLE_XFA 17 18 int _gAfxGetTimeZoneInSeconds(FX_CHAR tzhour, uint8_t tzminute) { 19 return (int)tzhour * 3600 + (int)tzminute * (tzhour >= 0 ? 60 : -60); 20 } 21 22 FX_BOOL _gAfxIsLeapYear(int16_t year) { 23 return ((year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0))); 24 } 25 26 FX_WORD _gAfxGetYearDays(int16_t year) { 27 return (_gAfxIsLeapYear(year) == TRUE ? 366 : 365); 28 } 29 30 uint8_t _gAfxGetMonthDays(int16_t year, uint8_t month) { 31 uint8_t mDays; 32 switch (month) { 33 case 1: 34 case 3: 35 case 5: 36 case 7: 37 case 8: 38 case 10: 39 case 12: 40 mDays = 31; 41 break; 42 43 case 4: 44 case 6: 45 case 9: 46 case 11: 47 mDays = 30; 48 break; 49 50 case 2: 51 if (_gAfxIsLeapYear(year) == TRUE) 52 mDays = 29; 53 else 54 mDays = 28; 55 break; 56 57 default: 58 mDays = 0; 59 break; 60 } 61 62 return mDays; 63 } 64 65 CPDFSDK_DateTime::CPDFSDK_DateTime() { 66 ResetDateTime(); 67 } 68 69 CPDFSDK_DateTime::CPDFSDK_DateTime(const CFX_ByteString& dtStr) { 70 ResetDateTime(); 71 72 FromPDFDateTimeString(dtStr); 73 } 74 75 CPDFSDK_DateTime::CPDFSDK_DateTime(const CPDFSDK_DateTime& datetime) { 76 operator=(datetime); 77 } 78 79 CPDFSDK_DateTime::CPDFSDK_DateTime(const FX_SYSTEMTIME& st) { 80 operator=(st); 81 } 82 83 void CPDFSDK_DateTime::ResetDateTime() { 84 tzset(); 85 86 time_t curTime; 87 time(&curTime); 88 struct tm* newtime; 89 // newtime = gmtime(&curTime); 90 newtime = localtime(&curTime); 91 92 dt.year = newtime->tm_year + 1900; 93 dt.month = newtime->tm_mon + 1; 94 dt.day = newtime->tm_mday; 95 dt.hour = newtime->tm_hour; 96 dt.minute = newtime->tm_min; 97 dt.second = newtime->tm_sec; 98 // dt.tzHour = _timezone / 3600 * -1; 99 // dt.tzMinute = (abs(_timezone) % 3600) / 60; 100 } 101 102 CPDFSDK_DateTime& CPDFSDK_DateTime::operator=( 103 const CPDFSDK_DateTime& datetime) { 104 FXSYS_memcpy(&dt, &datetime.dt, sizeof(FX_DATETIME)); 105 return *this; 106 } 107 108 CPDFSDK_DateTime& CPDFSDK_DateTime::operator=(const FX_SYSTEMTIME& st) { 109 tzset(); 110 111 dt.year = (int16_t)st.wYear; 112 dt.month = (uint8_t)st.wMonth; 113 dt.day = (uint8_t)st.wDay; 114 dt.hour = (uint8_t)st.wHour; 115 dt.minute = (uint8_t)st.wMinute; 116 dt.second = (uint8_t)st.wSecond; 117 // dt.tzHour = _timezone / 3600 * -1; 118 // dt.tzMinute = (abs(_timezone) % 3600) / 60; 119 return *this; 120 } 121 122 FX_BOOL CPDFSDK_DateTime::operator==(CPDFSDK_DateTime& datetime) { 123 return (FXSYS_memcmp(&dt, &datetime.dt, sizeof(FX_DATETIME)) == 0); 124 } 125 126 FX_BOOL CPDFSDK_DateTime::operator!=(CPDFSDK_DateTime& datetime) { 127 return (FXSYS_memcmp(&dt, &datetime.dt, sizeof(FX_DATETIME)) != 0); 128 } 129 130 FX_BOOL CPDFSDK_DateTime::operator>(CPDFSDK_DateTime& datetime) { 131 CPDFSDK_DateTime dt1 = ToGMT(); 132 CPDFSDK_DateTime dt2 = datetime.ToGMT(); 133 int d1 = 134 (((int)dt1.dt.year) << 16) | (((int)dt1.dt.month) << 8) | (int)dt1.dt.day; 135 int d2 = (((int)dt1.dt.hour) << 16) | (((int)dt1.dt.minute) << 8) | 136 (int)dt1.dt.second; 137 int d3 = 138 (((int)dt2.dt.year) << 16) | (((int)dt2.dt.month) << 8) | (int)dt2.dt.day; 139 int d4 = (((int)dt2.dt.hour) << 16) | (((int)dt2.dt.minute) << 8) | 140 (int)dt2.dt.second; 141 142 if (d1 > d3) 143 return TRUE; 144 if (d2 > d4) 145 return TRUE; 146 return FALSE; 147 } 148 149 FX_BOOL CPDFSDK_DateTime::operator>=(CPDFSDK_DateTime& datetime) { 150 CPDFSDK_DateTime dt1 = ToGMT(); 151 CPDFSDK_DateTime dt2 = datetime.ToGMT(); 152 int d1 = 153 (((int)dt1.dt.year) << 16) | (((int)dt1.dt.month) << 8) | (int)dt1.dt.day; 154 int d2 = (((int)dt1.dt.hour) << 16) | (((int)dt1.dt.minute) << 8) | 155 (int)dt1.dt.second; 156 int d3 = 157 (((int)dt2.dt.year) << 16) | (((int)dt2.dt.month) << 8) | (int)dt2.dt.day; 158 int d4 = (((int)dt2.dt.hour) << 16) | (((int)dt2.dt.minute) << 8) | 159 (int)dt2.dt.second; 160 161 if (d1 >= d3) 162 return TRUE; 163 if (d2 >= d4) 164 return TRUE; 165 return FALSE; 166 } 167 168 FX_BOOL CPDFSDK_DateTime::operator<(CPDFSDK_DateTime& datetime) { 169 CPDFSDK_DateTime dt1 = ToGMT(); 170 CPDFSDK_DateTime dt2 = datetime.ToGMT(); 171 int d1 = 172 (((int)dt1.dt.year) << 16) | (((int)dt1.dt.month) << 8) | (int)dt1.dt.day; 173 int d2 = (((int)dt1.dt.hour) << 16) | (((int)dt1.dt.minute) << 8) | 174 (int)dt1.dt.second; 175 int d3 = 176 (((int)dt2.dt.year) << 16) | (((int)dt2.dt.month) << 8) | (int)dt2.dt.day; 177 int d4 = (((int)dt2.dt.hour) << 16) | (((int)dt2.dt.minute) << 8) | 178 (int)dt2.dt.second; 179 180 if (d1 < d3) 181 return TRUE; 182 if (d2 < d4) 183 return TRUE; 184 return FALSE; 185 } 186 187 FX_BOOL CPDFSDK_DateTime::operator<=(CPDFSDK_DateTime& datetime) { 188 CPDFSDK_DateTime dt1 = ToGMT(); 189 CPDFSDK_DateTime dt2 = datetime.ToGMT(); 190 int d1 = 191 (((int)dt1.dt.year) << 16) | (((int)dt1.dt.month) << 8) | (int)dt1.dt.day; 192 int d2 = (((int)dt1.dt.hour) << 16) | (((int)dt1.dt.minute) << 8) | 193 (int)dt1.dt.second; 194 int d3 = 195 (((int)dt2.dt.year) << 16) | (((int)dt2.dt.month) << 8) | (int)dt2.dt.day; 196 int d4 = (((int)dt2.dt.hour) << 16) | (((int)dt2.dt.minute) << 8) | 197 (int)dt2.dt.second; 198 199 if (d1 <= d3) 200 return TRUE; 201 if (d2 <= d4) 202 return TRUE; 203 return FALSE; 204 } 205 206 CPDFSDK_DateTime::operator time_t() { 207 struct tm newtime; 208 209 newtime.tm_year = dt.year - 1900; 210 newtime.tm_mon = dt.month - 1; 211 newtime.tm_mday = dt.day; 212 newtime.tm_hour = dt.hour; 213 newtime.tm_min = dt.minute; 214 newtime.tm_sec = dt.second; 215 216 return mktime(&newtime); 217 } 218 219 CPDFSDK_DateTime& CPDFSDK_DateTime::FromPDFDateTimeString( 220 const CFX_ByteString& dtStr) { 221 int strLength = dtStr.GetLength(); 222 if (strLength > 0) { 223 int i = 0; 224 int j, k; 225 FX_CHAR ch; 226 while (i < strLength && !std::isdigit(dtStr[i])) 227 ++i; 228 229 if (i >= strLength) 230 return *this; 231 232 j = 0; 233 k = 0; 234 while (i < strLength && j < 4) { 235 ch = dtStr[i]; 236 k = k * 10 + FXSYS_toDecimalDigit(ch); 237 j++; 238 if (!std::isdigit(ch)) 239 break; 240 i++; 241 } 242 dt.year = (int16_t)k; 243 if (i >= strLength || j < 4) 244 return *this; 245 246 j = 0; 247 k = 0; 248 while (i < strLength && j < 2) { 249 ch = dtStr[i]; 250 k = k * 10 + FXSYS_toDecimalDigit(ch); 251 j++; 252 if (!std::isdigit(ch)) 253 break; 254 i++; 255 } 256 dt.month = (uint8_t)k; 257 if (i >= strLength || j < 2) 258 return *this; 259 260 j = 0; 261 k = 0; 262 while (i < strLength && j < 2) { 263 ch = dtStr[i]; 264 k = k * 10 + FXSYS_toDecimalDigit(ch); 265 j++; 266 if (!std::isdigit(ch)) 267 break; 268 i++; 269 } 270 dt.day = (uint8_t)k; 271 if (i >= strLength || j < 2) 272 return *this; 273 274 j = 0; 275 k = 0; 276 while (i < strLength && j < 2) { 277 ch = dtStr[i]; 278 k = k * 10 + FXSYS_toDecimalDigit(ch); 279 j++; 280 if (!std::isdigit(ch)) 281 break; 282 i++; 283 } 284 dt.hour = (uint8_t)k; 285 if (i >= strLength || j < 2) 286 return *this; 287 288 j = 0; 289 k = 0; 290 while (i < strLength && j < 2) { 291 ch = dtStr[i]; 292 k = k * 10 + FXSYS_toDecimalDigit(ch); 293 j++; 294 if (!std::isdigit(ch)) 295 break; 296 i++; 297 } 298 dt.minute = (uint8_t)k; 299 if (i >= strLength || j < 2) 300 return *this; 301 302 j = 0; 303 k = 0; 304 while (i < strLength && j < 2) { 305 ch = dtStr[i]; 306 k = k * 10 + FXSYS_toDecimalDigit(ch); 307 j++; 308 if (!std::isdigit(ch)) 309 break; 310 i++; 311 } 312 dt.second = (uint8_t)k; 313 if (i >= strLength || j < 2) 314 return *this; 315 316 ch = dtStr[i++]; 317 if (ch != '-' && ch != '+') 318 return *this; 319 if (ch == '-') 320 dt.tzHour = -1; 321 else 322 dt.tzHour = 1; 323 j = 0; 324 k = 0; 325 while (i < strLength && j < 2) { 326 ch = dtStr[i]; 327 k = k * 10 + FXSYS_toDecimalDigit(ch); 328 j++; 329 if (!std::isdigit(ch)) 330 break; 331 i++; 332 } 333 dt.tzHour *= (FX_CHAR)k; 334 if (i >= strLength || j < 2) 335 return *this; 336 337 ch = dtStr[i++]; 338 if (ch != '\'') 339 return *this; 340 j = 0; 341 k = 0; 342 while (i < strLength && j < 2) { 343 ch = dtStr[i]; 344 k = k * 10 + FXSYS_toDecimalDigit(ch); 345 j++; 346 if (!std::isdigit(ch)) 347 break; 348 i++; 349 } 350 dt.tzMinute = (uint8_t)k; 351 if (i >= strLength || j < 2) 352 return *this; 353 } 354 355 return *this; 356 } 357 358 CFX_ByteString CPDFSDK_DateTime::ToCommonDateTimeString() { 359 CFX_ByteString str1; 360 str1.Format("%04d-%02d-%02d %02d:%02d:%02d ", dt.year, dt.month, dt.day, 361 dt.hour, dt.minute, dt.second); 362 if (dt.tzHour < 0) 363 str1 += "-"; 364 else 365 str1 += "+"; 366 CFX_ByteString str2; 367 str2.Format("%02d:%02d", abs(dt.tzHour), dt.tzMinute); 368 return str1 + str2; 369 } 370 371 CFX_ByteString CPDFSDK_DateTime::ToPDFDateTimeString() { 372 CFX_ByteString dtStr; 373 char tempStr[32]; 374 memset(tempStr, 0, sizeof(tempStr)); 375 FXSYS_snprintf(tempStr, sizeof(tempStr) - 1, "D:%04d%02d%02d%02d%02d%02d", 376 dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second); 377 dtStr = CFX_ByteString(tempStr); 378 if (dt.tzHour < 0) 379 dtStr += CFX_ByteString("-"); 380 else 381 dtStr += CFX_ByteString("+"); 382 memset(tempStr, 0, sizeof(tempStr)); 383 FXSYS_snprintf(tempStr, sizeof(tempStr) - 1, "%02d'%02d'", abs(dt.tzHour), 384 dt.tzMinute); 385 dtStr += CFX_ByteString(tempStr); 386 return dtStr; 387 } 388 389 void CPDFSDK_DateTime::ToSystemTime(FX_SYSTEMTIME& st) { 390 CPDFSDK_DateTime dt = *this; 391 time_t t = (time_t)dt; 392 struct tm* pTime = localtime(&t); 393 if (pTime) { 394 st.wYear = (FX_WORD)pTime->tm_year + 1900; 395 st.wMonth = (FX_WORD)pTime->tm_mon + 1; 396 st.wDay = (FX_WORD)pTime->tm_mday; 397 st.wDayOfWeek = (FX_WORD)pTime->tm_wday; 398 st.wHour = (FX_WORD)pTime->tm_hour; 399 st.wMinute = (FX_WORD)pTime->tm_min; 400 st.wSecond = (FX_WORD)pTime->tm_sec; 401 st.wMilliseconds = 0; 402 } 403 } 404 405 CPDFSDK_DateTime CPDFSDK_DateTime::ToGMT() { 406 CPDFSDK_DateTime dt = *this; 407 dt.AddSeconds(-_gAfxGetTimeZoneInSeconds(dt.dt.tzHour, dt.dt.tzMinute)); 408 dt.dt.tzHour = 0; 409 dt.dt.tzMinute = 0; 410 return dt; 411 } 412 413 CPDFSDK_DateTime& CPDFSDK_DateTime::AddDays(short days) { 414 if (days == 0) 415 return *this; 416 417 int16_t y = dt.year, yy; 418 uint8_t m = dt.month; 419 uint8_t d = dt.day; 420 int mdays, ydays, ldays; 421 422 ldays = days; 423 if (ldays > 0) { 424 yy = y; 425 if (((FX_WORD)m * 100 + d) > 300) 426 yy++; 427 ydays = _gAfxGetYearDays(yy); 428 while (ldays >= ydays) { 429 y++; 430 ldays -= ydays; 431 yy++; 432 mdays = _gAfxGetMonthDays(y, m); 433 if (d > mdays) { 434 m++; 435 d -= mdays; 436 } 437 ydays = _gAfxGetYearDays(yy); 438 } 439 mdays = _gAfxGetMonthDays(y, m) - d + 1; 440 while (ldays >= mdays) { 441 ldays -= mdays; 442 m++; 443 d = 1; 444 mdays = _gAfxGetMonthDays(y, m); 445 } 446 d += ldays; 447 } else { 448 ldays *= -1; 449 yy = y; 450 if (((FX_WORD)m * 100 + d) < 300) 451 yy--; 452 ydays = _gAfxGetYearDays(yy); 453 while (ldays >= ydays) { 454 y--; 455 ldays -= ydays; 456 yy--; 457 mdays = _gAfxGetMonthDays(y, m); 458 if (d > mdays) { 459 m++; 460 d -= mdays; 461 } 462 ydays = _gAfxGetYearDays(yy); 463 } 464 while (ldays >= d) { 465 ldays -= d; 466 m--; 467 mdays = _gAfxGetMonthDays(y, m); 468 d = mdays; 469 } 470 d -= ldays; 471 } 472 473 dt.year = y; 474 dt.month = m; 475 dt.day = d; 476 477 return *this; 478 } 479 480 CPDFSDK_DateTime& CPDFSDK_DateTime::AddSeconds(int seconds) { 481 if (seconds == 0) 482 return *this; 483 484 int n; 485 int days; 486 487 n = dt.hour * 3600 + dt.minute * 60 + dt.second + seconds; 488 if (n < 0) { 489 days = (n - 86399) / 86400; 490 n -= days * 86400; 491 } else { 492 days = n / 86400; 493 n %= 86400; 494 } 495 dt.hour = (uint8_t)(n / 3600); 496 dt.hour %= 24; 497 n %= 3600; 498 dt.minute = (uint8_t)(n / 60); 499 dt.second = (uint8_t)(n % 60); 500 if (days != 0) 501 AddDays(days); 502 503 return *this; 504 } 505 506 CPDFSDK_Annot::CPDFSDK_Annot(CPDFSDK_PageView* pPageView) 507 : m_pPageView(pPageView), m_bSelected(FALSE), m_nTabOrder(-1) { 508 } 509 510 CPDFSDK_BAAnnot::CPDFSDK_BAAnnot(CPDF_Annot* pAnnot, 511 CPDFSDK_PageView* pPageView) 512 : CPDFSDK_Annot(pPageView), m_pAnnot(pAnnot) { 513 } 514 515 CPDF_Annot* CPDFSDK_BAAnnot::GetPDFAnnot() const { 516 return m_pAnnot; 517 } 518 519 FX_BOOL CPDFSDK_Annot::IsSelected() { 520 return m_bSelected; 521 } 522 523 void CPDFSDK_Annot::SetSelected(FX_BOOL bSelected) { 524 m_bSelected = bSelected; 525 } 526 527 // Tab Order 528 int CPDFSDK_Annot::GetTabOrder() { 529 return m_nTabOrder; 530 } 531 532 void CPDFSDK_Annot::SetTabOrder(int iTabOrder) { 533 m_nTabOrder = iTabOrder; 534 } 535 536 CPDF_Dictionary* CPDFSDK_BAAnnot::GetAnnotDict() const { 537 return m_pAnnot->GetAnnotDict(); 538 } 539 540 void CPDFSDK_BAAnnot::SetRect(const CPDF_Rect& rect) { 541 ASSERT(rect.right - rect.left >= GetMinWidth()); 542 ASSERT(rect.top - rect.bottom >= GetMinHeight()); 543 544 m_pAnnot->GetAnnotDict()->SetAtRect("Rect", rect); 545 } 546 547 CPDF_Rect CPDFSDK_BAAnnot::GetRect() const { 548 CPDF_Rect rect; 549 m_pAnnot->GetRect(rect); 550 return rect; 551 } 552 553 CFX_ByteString CPDFSDK_BAAnnot::GetType() const { 554 return m_pAnnot->GetSubType(); 555 } 556 557 CFX_ByteString CPDFSDK_BAAnnot::GetSubType() const { 558 return ""; 559 } 560 561 void CPDFSDK_BAAnnot::DrawAppearance(CFX_RenderDevice* pDevice, 562 const CFX_Matrix* pUser2Device, 563 CPDF_Annot::AppearanceMode mode, 564 const CPDF_RenderOptions* pOptions) { 565 m_pAnnot->DrawAppearance(m_pPageView->GetPDFPage(), pDevice, pUser2Device, 566 mode, pOptions); 567 } 568 569 FX_BOOL CPDFSDK_BAAnnot::IsAppearanceValid() { 570 return m_pAnnot->GetAnnotDict()->GetDict("AP") != NULL; 571 } 572 573 FX_BOOL CPDFSDK_BAAnnot::IsAppearanceValid(CPDF_Annot::AppearanceMode mode) { 574 CPDF_Dictionary* pAP = m_pAnnot->GetAnnotDict()->GetDict("AP"); 575 if (!pAP) 576 return FALSE; 577 578 // Choose the right sub-ap 579 const FX_CHAR* ap_entry = "N"; 580 if (mode == CPDF_Annot::Down) 581 ap_entry = "D"; 582 else if (mode == CPDF_Annot::Rollover) 583 ap_entry = "R"; 584 if (!pAP->KeyExist(ap_entry)) 585 ap_entry = "N"; 586 587 // Get the AP stream or subdirectory 588 CPDF_Object* psub = pAP->GetElementValue(ap_entry); 589 return !!psub; 590 } 591 592 void CPDFSDK_BAAnnot::DrawBorder(CFX_RenderDevice* pDevice, 593 const CFX_Matrix* pUser2Device, 594 const CPDF_RenderOptions* pOptions) { 595 m_pAnnot->DrawBorder(pDevice, pUser2Device, pOptions); 596 } 597 598 void CPDFSDK_BAAnnot::ClearCachedAP() { 599 m_pAnnot->ClearCachedAP(); 600 } 601 602 void CPDFSDK_BAAnnot::SetContents(const CFX_WideString& sContents) { 603 if (sContents.IsEmpty()) 604 m_pAnnot->GetAnnotDict()->RemoveAt("Contents"); 605 else 606 m_pAnnot->GetAnnotDict()->SetAtString("Contents", 607 PDF_EncodeText(sContents)); 608 } 609 610 CFX_WideString CPDFSDK_BAAnnot::GetContents() const { 611 return m_pAnnot->GetAnnotDict()->GetUnicodeText("Contents"); 612 } 613 614 void CPDFSDK_BAAnnot::SetAnnotName(const CFX_WideString& sName) { 615 if (sName.IsEmpty()) 616 m_pAnnot->GetAnnotDict()->RemoveAt("NM"); 617 else 618 m_pAnnot->GetAnnotDict()->SetAtString("NM", PDF_EncodeText(sName)); 619 } 620 621 CFX_WideString CPDFSDK_BAAnnot::GetAnnotName() const { 622 return m_pAnnot->GetAnnotDict()->GetUnicodeText("NM"); 623 } 624 625 void CPDFSDK_BAAnnot::SetModifiedDate(const FX_SYSTEMTIME& st) { 626 CPDFSDK_DateTime dt(st); 627 CFX_ByteString str = dt.ToPDFDateTimeString(); 628 629 if (str.IsEmpty()) 630 m_pAnnot->GetAnnotDict()->RemoveAt("M"); 631 else 632 m_pAnnot->GetAnnotDict()->SetAtString("M", str); 633 } 634 635 FX_SYSTEMTIME CPDFSDK_BAAnnot::GetModifiedDate() const { 636 FX_SYSTEMTIME systime; 637 CFX_ByteString str = m_pAnnot->GetAnnotDict()->GetString("M"); 638 639 CPDFSDK_DateTime dt(str); 640 dt.ToSystemTime(systime); 641 642 return systime; 643 } 644 645 void CPDFSDK_BAAnnot::SetFlags(int nFlags) { 646 m_pAnnot->GetAnnotDict()->SetAtInteger("F", nFlags); 647 } 648 649 int CPDFSDK_BAAnnot::GetFlags() const { 650 return m_pAnnot->GetAnnotDict()->GetInteger("F"); 651 } 652 653 void CPDFSDK_BAAnnot::SetAppState(const CFX_ByteString& str) { 654 if (str.IsEmpty()) 655 m_pAnnot->GetAnnotDict()->RemoveAt("AS"); 656 else 657 m_pAnnot->GetAnnotDict()->SetAtString("AS", str); 658 } 659 660 CFX_ByteString CPDFSDK_BAAnnot::GetAppState() const { 661 return m_pAnnot->GetAnnotDict()->GetString("AS"); 662 } 663 664 void CPDFSDK_BAAnnot::SetStructParent(int key) { 665 m_pAnnot->GetAnnotDict()->SetAtInteger("StructParent", key); 666 } 667 668 int CPDFSDK_BAAnnot::GetStructParent() const { 669 return m_pAnnot->GetAnnotDict()->GetInteger("StructParent"); 670 } 671 672 // border 673 void CPDFSDK_BAAnnot::SetBorderWidth(int nWidth) { 674 CPDF_Array* pBorder = m_pAnnot->GetAnnotDict()->GetArray("Border"); 675 676 if (pBorder) { 677 pBorder->SetAt(2, new CPDF_Number(nWidth)); 678 } else { 679 CPDF_Dictionary* pBSDict = m_pAnnot->GetAnnotDict()->GetDict("BS"); 680 681 if (!pBSDict) { 682 pBSDict = new CPDF_Dictionary; 683 m_pAnnot->GetAnnotDict()->SetAt("BS", pBSDict); 684 } 685 686 pBSDict->SetAtInteger("W", nWidth); 687 } 688 } 689 690 int CPDFSDK_BAAnnot::GetBorderWidth() const { 691 if (CPDF_Array* pBorder = m_pAnnot->GetAnnotDict()->GetArray("Border")) { 692 return pBorder->GetInteger(2); 693 } 694 if (CPDF_Dictionary* pBSDict = m_pAnnot->GetAnnotDict()->GetDict("BS")) { 695 return pBSDict->GetInteger("W", 1); 696 } 697 return 1; 698 } 699 700 void CPDFSDK_BAAnnot::SetBorderStyle(int nStyle) { 701 CPDF_Dictionary* pBSDict = m_pAnnot->GetAnnotDict()->GetDict("BS"); 702 if (!pBSDict) { 703 pBSDict = new CPDF_Dictionary; 704 m_pAnnot->GetAnnotDict()->SetAt("BS", pBSDict); 705 } 706 707 switch (nStyle) { 708 case BBS_SOLID: 709 pBSDict->SetAtName("S", "S"); 710 break; 711 case BBS_DASH: 712 pBSDict->SetAtName("S", "D"); 713 break; 714 case BBS_BEVELED: 715 pBSDict->SetAtName("S", "B"); 716 break; 717 case BBS_INSET: 718 pBSDict->SetAtName("S", "I"); 719 break; 720 case BBS_UNDERLINE: 721 pBSDict->SetAtName("S", "U"); 722 break; 723 } 724 } 725 726 int CPDFSDK_BAAnnot::GetBorderStyle() const { 727 CPDF_Dictionary* pBSDict = m_pAnnot->GetAnnotDict()->GetDict("BS"); 728 if (pBSDict) { 729 CFX_ByteString sBorderStyle = pBSDict->GetString("S", "S"); 730 if (sBorderStyle == "S") 731 return BBS_SOLID; 732 if (sBorderStyle == "D") 733 return BBS_DASH; 734 if (sBorderStyle == "B") 735 return BBS_BEVELED; 736 if (sBorderStyle == "I") 737 return BBS_INSET; 738 if (sBorderStyle == "U") 739 return BBS_UNDERLINE; 740 } 741 742 CPDF_Array* pBorder = m_pAnnot->GetAnnotDict()->GetArray("Border"); 743 if (pBorder) { 744 if (pBorder->GetCount() >= 4) { 745 CPDF_Array* pDP = pBorder->GetArray(3); 746 if (pDP && pDP->GetCount() > 0) 747 return BBS_DASH; 748 } 749 } 750 751 return BBS_SOLID; 752 } 753 754 void CPDFSDK_BAAnnot::SetBorderDash(const CFX_IntArray& array) { 755 CPDF_Dictionary* pBSDict = m_pAnnot->GetAnnotDict()->GetDict("BS"); 756 if (!pBSDict) { 757 pBSDict = new CPDF_Dictionary; 758 m_pAnnot->GetAnnotDict()->SetAt("BS", pBSDict); 759 } 760 761 CPDF_Array* pArray = new CPDF_Array; 762 for (int i = 0, sz = array.GetSize(); i < sz; i++) { 763 pArray->AddInteger(array[i]); 764 } 765 766 pBSDict->SetAt("D", pArray); 767 } 768 769 void CPDFSDK_BAAnnot::GetBorderDash(CFX_IntArray& array) const { 770 CPDF_Array* pDash = NULL; 771 772 CPDF_Array* pBorder = m_pAnnot->GetAnnotDict()->GetArray("Border"); 773 if (pBorder) { 774 pDash = pBorder->GetArray(3); 775 } else { 776 CPDF_Dictionary* pBSDict = m_pAnnot->GetAnnotDict()->GetDict("BS"); 777 if (pBSDict) { 778 pDash = pBSDict->GetArray("D"); 779 } 780 } 781 782 if (pDash) { 783 for (int i = 0, sz = pDash->GetCount(); i < sz; i++) { 784 array.Add(pDash->GetInteger(i)); 785 } 786 } 787 } 788 789 void CPDFSDK_BAAnnot::SetColor(FX_COLORREF color) { 790 CPDF_Array* pArray = new CPDF_Array; 791 pArray->AddNumber((FX_FLOAT)FXSYS_GetRValue(color) / 255.0f); 792 pArray->AddNumber((FX_FLOAT)FXSYS_GetGValue(color) / 255.0f); 793 pArray->AddNumber((FX_FLOAT)FXSYS_GetBValue(color) / 255.0f); 794 m_pAnnot->GetAnnotDict()->SetAt("C", pArray); 795 } 796 797 void CPDFSDK_BAAnnot::RemoveColor() { 798 m_pAnnot->GetAnnotDict()->RemoveAt("C"); 799 } 800 801 FX_BOOL CPDFSDK_BAAnnot::GetColor(FX_COLORREF& color) const { 802 if (CPDF_Array* pEntry = m_pAnnot->GetAnnotDict()->GetArray("C")) { 803 int nCount = pEntry->GetCount(); 804 if (nCount == 1) { 805 FX_FLOAT g = pEntry->GetNumber(0) * 255; 806 807 color = FXSYS_RGB((int)g, (int)g, (int)g); 808 809 return TRUE; 810 } else if (nCount == 3) { 811 FX_FLOAT r = pEntry->GetNumber(0) * 255; 812 FX_FLOAT g = pEntry->GetNumber(1) * 255; 813 FX_FLOAT b = pEntry->GetNumber(2) * 255; 814 815 color = FXSYS_RGB((int)r, (int)g, (int)b); 816 817 return TRUE; 818 } else if (nCount == 4) { 819 FX_FLOAT c = pEntry->GetNumber(0); 820 FX_FLOAT m = pEntry->GetNumber(1); 821 FX_FLOAT y = pEntry->GetNumber(2); 822 FX_FLOAT k = pEntry->GetNumber(3); 823 824 FX_FLOAT r = 1.0f - std::min(1.0f, c + k); 825 FX_FLOAT g = 1.0f - std::min(1.0f, m + k); 826 FX_FLOAT b = 1.0f - std::min(1.0f, y + k); 827 828 color = FXSYS_RGB((int)(r * 255), (int)(g * 255), (int)(b * 255)); 829 830 return TRUE; 831 } 832 } 833 834 return FALSE; 835 } 836 837 void CPDFSDK_BAAnnot::WriteAppearance(const CFX_ByteString& sAPType, 838 const CPDF_Rect& rcBBox, 839 const CFX_Matrix& matrix, 840 const CFX_ByteString& sContents, 841 const CFX_ByteString& sAPState) { 842 CPDF_Dictionary* pAPDict = m_pAnnot->GetAnnotDict()->GetDict("AP"); 843 844 if (!pAPDict) { 845 pAPDict = new CPDF_Dictionary; 846 m_pAnnot->GetAnnotDict()->SetAt("AP", pAPDict); 847 } 848 849 CPDF_Stream* pStream = nullptr; 850 CPDF_Dictionary* pParentDict = nullptr; 851 852 if (sAPState.IsEmpty()) { 853 pParentDict = pAPDict; 854 pStream = pAPDict->GetStream(sAPType); 855 } else { 856 CPDF_Dictionary* pAPTypeDict = pAPDict->GetDict(sAPType); 857 if (!pAPTypeDict) { 858 pAPTypeDict = new CPDF_Dictionary; 859 pAPDict->SetAt(sAPType, pAPTypeDict); 860 } 861 862 pParentDict = pAPTypeDict; 863 pStream = pAPTypeDict->GetStream(sAPState); 864 } 865 866 if (!pStream) { 867 pStream = new CPDF_Stream(nullptr, 0, nullptr); 868 869 CPDF_Document* pDoc = m_pPageView->GetPDFDocument(); 870 int32_t objnum = pDoc->AddIndirectObject(pStream); 871 pParentDict->SetAtReference(sAPType, pDoc, objnum); 872 } 873 874 CPDF_Dictionary* pStreamDict = pStream->GetDict(); 875 if (!pStreamDict) { 876 pStreamDict = new CPDF_Dictionary; 877 pStreamDict->SetAtName("Type", "XObject"); 878 pStreamDict->SetAtName("Subtype", "Form"); 879 pStreamDict->SetAtInteger("FormType", 1); 880 pStream->InitStream(nullptr, 0, pStreamDict); 881 } 882 883 if (pStreamDict) { 884 pStreamDict->SetAtMatrix("Matrix", matrix); 885 pStreamDict->SetAtRect("BBox", rcBBox); 886 } 887 888 pStream->SetData((uint8_t*)sContents.c_str(), sContents.GetLength(), FALSE, 889 FALSE); 890 } 891 892 #define BA_ANNOT_MINWIDTH 1 893 #define BA_ANNOT_MINHEIGHT 1 894 895 FX_FLOAT CPDFSDK_Annot::GetMinWidth() const { 896 return BA_ANNOT_MINWIDTH; 897 } 898 899 FX_FLOAT CPDFSDK_Annot::GetMinHeight() const { 900 return BA_ANNOT_MINHEIGHT; 901 } 902 903 FX_BOOL CPDFSDK_BAAnnot::CreateFormFiller() { 904 return TRUE; 905 } 906 FX_BOOL CPDFSDK_BAAnnot::IsVisible() const { 907 int nFlags = GetFlags(); 908 return !((nFlags & ANNOTFLAG_INVISIBLE) || (nFlags & ANNOTFLAG_HIDDEN) || 909 (nFlags & ANNOTFLAG_NOVIEW)); 910 } 911 912 CPDF_Action CPDFSDK_BAAnnot::GetAction() const { 913 return CPDF_Action(m_pAnnot->GetAnnotDict()->GetDict("A")); 914 } 915 916 void CPDFSDK_BAAnnot::SetAction(const CPDF_Action& action) { 917 ASSERT(action); 918 if ((CPDF_Action&)action != 919 CPDF_Action(m_pAnnot->GetAnnotDict()->GetDict("A"))) { 920 CPDF_Document* pDoc = m_pPageView->GetPDFDocument(); 921 CPDF_Dictionary* pDict = action.GetDict(); 922 if (pDict && pDict->GetObjNum() == 0) { 923 pDoc->AddIndirectObject(pDict); 924 } 925 m_pAnnot->GetAnnotDict()->SetAtReference("A", pDoc, pDict->GetObjNum()); 926 } 927 } 928 929 void CPDFSDK_BAAnnot::RemoveAction() { 930 m_pAnnot->GetAnnotDict()->RemoveAt("A"); 931 } 932 933 CPDF_AAction CPDFSDK_BAAnnot::GetAAction() const { 934 return m_pAnnot->GetAnnotDict()->GetDict("AA"); 935 } 936 937 void CPDFSDK_BAAnnot::SetAAction(const CPDF_AAction& aa) { 938 if ((CPDF_AAction&)aa != m_pAnnot->GetAnnotDict()->GetDict("AA")) 939 m_pAnnot->GetAnnotDict()->SetAt("AA", (CPDF_AAction&)aa); 940 } 941 942 void CPDFSDK_BAAnnot::RemoveAAction() { 943 m_pAnnot->GetAnnotDict()->RemoveAt("AA"); 944 } 945 946 CPDF_Action CPDFSDK_BAAnnot::GetAAction(CPDF_AAction::AActionType eAAT) { 947 CPDF_AAction AAction = GetAAction(); 948 949 if (AAction.ActionExist(eAAT)) 950 return AAction.GetAction(eAAT); 951 952 if (eAAT == CPDF_AAction::ButtonUp) 953 return GetAction(); 954 955 return CPDF_Action(); 956 } 957 958 #ifdef PDF_ENABLE_XFA 959 FX_BOOL CPDFSDK_BAAnnot::IsXFAField() { 960 return FALSE; 961 } 962 #endif // PDF_ENABLE_XFA 963 964 void CPDFSDK_BAAnnot::Annot_OnDraw(CFX_RenderDevice* pDevice, 965 CFX_Matrix* pUser2Device, 966 CPDF_RenderOptions* pOptions) { 967 m_pAnnot->GetAPForm(m_pPageView->GetPDFPage(), CPDF_Annot::Normal); 968 m_pAnnot->DrawAppearance(m_pPageView->GetPDFPage(), pDevice, pUser2Device, 969 CPDF_Annot::Normal, NULL); 970 } 971 972 UnderlyingPageType* CPDFSDK_Annot::GetUnderlyingPage() { 973 #ifdef PDF_ENABLE_XFA 974 return GetPDFXFAPage(); 975 #else // PDF_ENABLE_XFA 976 return GetPDFPage(); 977 #endif // PDF_ENABLE_XFA 978 } 979 980 CPDF_Page* CPDFSDK_Annot::GetPDFPage() { 981 if (m_pPageView) 982 return m_pPageView->GetPDFPage(); 983 return NULL; 984 } 985 986 #ifdef PDF_ENABLE_XFA 987 CPDFXFA_Page* CPDFSDK_Annot::GetPDFXFAPage() { 988 if (m_pPageView) 989 return m_pPageView->GetPDFXFAPage(); 990 return NULL; 991 } 992 #endif // PDF_ENABLE_XFA 993