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 
_gAfxGetTimeZoneInSeconds(FX_CHAR tzhour,uint8_t tzminute)18 int _gAfxGetTimeZoneInSeconds(FX_CHAR tzhour, uint8_t tzminute) {
19   return (int)tzhour * 3600 + (int)tzminute * (tzhour >= 0 ? 60 : -60);
20 }
21 
_gAfxIsLeapYear(int16_t year)22 FX_BOOL _gAfxIsLeapYear(int16_t year) {
23   return ((year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0)));
24 }
25 
_gAfxGetYearDays(int16_t year)26 FX_WORD _gAfxGetYearDays(int16_t year) {
27   return (_gAfxIsLeapYear(year) == TRUE ? 366 : 365);
28 }
29 
_gAfxGetMonthDays(int16_t year,uint8_t month)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 
CPDFSDK_DateTime()65 CPDFSDK_DateTime::CPDFSDK_DateTime() {
66   ResetDateTime();
67 }
68 
CPDFSDK_DateTime(const CFX_ByteString & dtStr)69 CPDFSDK_DateTime::CPDFSDK_DateTime(const CFX_ByteString& dtStr) {
70   ResetDateTime();
71 
72   FromPDFDateTimeString(dtStr);
73 }
74 
CPDFSDK_DateTime(const CPDFSDK_DateTime & datetime)75 CPDFSDK_DateTime::CPDFSDK_DateTime(const CPDFSDK_DateTime& datetime) {
76   operator=(datetime);
77 }
78 
CPDFSDK_DateTime(const FX_SYSTEMTIME & st)79 CPDFSDK_DateTime::CPDFSDK_DateTime(const FX_SYSTEMTIME& st) {
80   operator=(st);
81 }
82 
ResetDateTime()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 
operator =(const CPDFSDK_DateTime & datetime)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 
operator =(const FX_SYSTEMTIME & st)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 
operator ==(CPDFSDK_DateTime & datetime)122 FX_BOOL CPDFSDK_DateTime::operator==(CPDFSDK_DateTime& datetime) {
123   return (FXSYS_memcmp(&dt, &datetime.dt, sizeof(FX_DATETIME)) == 0);
124 }
125 
operator !=(CPDFSDK_DateTime & datetime)126 FX_BOOL CPDFSDK_DateTime::operator!=(CPDFSDK_DateTime& datetime) {
127   return (FXSYS_memcmp(&dt, &datetime.dt, sizeof(FX_DATETIME)) != 0);
128 }
129 
operator >(CPDFSDK_DateTime & datetime)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 
operator >=(CPDFSDK_DateTime & datetime)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 
operator <(CPDFSDK_DateTime & datetime)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 
operator <=(CPDFSDK_DateTime & datetime)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 
operator time_t()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 
FromPDFDateTimeString(const CFX_ByteString & dtStr)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 
ToCommonDateTimeString()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 
ToPDFDateTimeString()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 
ToSystemTime(FX_SYSTEMTIME & st)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 
ToGMT()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 
AddDays(short days)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 
AddSeconds(int seconds)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 
CPDFSDK_Annot(CPDFSDK_PageView * pPageView)506 CPDFSDK_Annot::CPDFSDK_Annot(CPDFSDK_PageView* pPageView)
507     : m_pPageView(pPageView), m_bSelected(FALSE), m_nTabOrder(-1) {
508 }
509 
CPDFSDK_BAAnnot(CPDF_Annot * pAnnot,CPDFSDK_PageView * pPageView)510 CPDFSDK_BAAnnot::CPDFSDK_BAAnnot(CPDF_Annot* pAnnot,
511                                  CPDFSDK_PageView* pPageView)
512     : CPDFSDK_Annot(pPageView), m_pAnnot(pAnnot) {
513 }
514 
GetPDFAnnot() const515 CPDF_Annot* CPDFSDK_BAAnnot::GetPDFAnnot() const {
516   return m_pAnnot;
517 }
518 
IsSelected()519 FX_BOOL CPDFSDK_Annot::IsSelected() {
520   return m_bSelected;
521 }
522 
SetSelected(FX_BOOL bSelected)523 void CPDFSDK_Annot::SetSelected(FX_BOOL bSelected) {
524   m_bSelected = bSelected;
525 }
526 
527 // Tab Order
GetTabOrder()528 int CPDFSDK_Annot::GetTabOrder() {
529   return m_nTabOrder;
530 }
531 
SetTabOrder(int iTabOrder)532 void CPDFSDK_Annot::SetTabOrder(int iTabOrder) {
533   m_nTabOrder = iTabOrder;
534 }
535 
GetAnnotDict() const536 CPDF_Dictionary* CPDFSDK_BAAnnot::GetAnnotDict() const {
537   return m_pAnnot->GetAnnotDict();
538 }
539 
SetRect(const CPDF_Rect & rect)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 
GetRect() const547 CPDF_Rect CPDFSDK_BAAnnot::GetRect() const {
548   CPDF_Rect rect;
549   m_pAnnot->GetRect(rect);
550   return rect;
551 }
552 
GetType() const553 CFX_ByteString CPDFSDK_BAAnnot::GetType() const {
554   return m_pAnnot->GetSubType();
555 }
556 
GetSubType() const557 CFX_ByteString CPDFSDK_BAAnnot::GetSubType() const {
558   return "";
559 }
560 
DrawAppearance(CFX_RenderDevice * pDevice,const CFX_Matrix * pUser2Device,CPDF_Annot::AppearanceMode mode,const CPDF_RenderOptions * pOptions)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 
IsAppearanceValid()569 FX_BOOL CPDFSDK_BAAnnot::IsAppearanceValid() {
570   return m_pAnnot->GetAnnotDict()->GetDict("AP") != NULL;
571 }
572 
IsAppearanceValid(CPDF_Annot::AppearanceMode mode)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 
DrawBorder(CFX_RenderDevice * pDevice,const CFX_Matrix * pUser2Device,const CPDF_RenderOptions * pOptions)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 
ClearCachedAP()598 void CPDFSDK_BAAnnot::ClearCachedAP() {
599   m_pAnnot->ClearCachedAP();
600 }
601 
SetContents(const CFX_WideString & sContents)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 
GetContents() const610 CFX_WideString CPDFSDK_BAAnnot::GetContents() const {
611   return m_pAnnot->GetAnnotDict()->GetUnicodeText("Contents");
612 }
613 
SetAnnotName(const CFX_WideString & sName)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 
GetAnnotName() const621 CFX_WideString CPDFSDK_BAAnnot::GetAnnotName() const {
622   return m_pAnnot->GetAnnotDict()->GetUnicodeText("NM");
623 }
624 
SetModifiedDate(const FX_SYSTEMTIME & st)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 
GetModifiedDate() const635 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 
SetFlags(int nFlags)645 void CPDFSDK_BAAnnot::SetFlags(int nFlags) {
646   m_pAnnot->GetAnnotDict()->SetAtInteger("F", nFlags);
647 }
648 
GetFlags() const649 int CPDFSDK_BAAnnot::GetFlags() const {
650   return m_pAnnot->GetAnnotDict()->GetInteger("F");
651 }
652 
SetAppState(const CFX_ByteString & str)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 
GetAppState() const660 CFX_ByteString CPDFSDK_BAAnnot::GetAppState() const {
661   return m_pAnnot->GetAnnotDict()->GetString("AS");
662 }
663 
SetStructParent(int key)664 void CPDFSDK_BAAnnot::SetStructParent(int key) {
665   m_pAnnot->GetAnnotDict()->SetAtInteger("StructParent", key);
666 }
667 
GetStructParent() const668 int CPDFSDK_BAAnnot::GetStructParent() const {
669   return m_pAnnot->GetAnnotDict()->GetInteger("StructParent");
670 }
671 
672 // border
SetBorderWidth(int nWidth)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 
GetBorderWidth() const690 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 
SetBorderStyle(int nStyle)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 
GetBorderStyle() const726 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 
SetBorderDash(const CFX_IntArray & array)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 
GetBorderDash(CFX_IntArray & array) const769 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 
SetColor(FX_COLORREF color)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 
RemoveColor()797 void CPDFSDK_BAAnnot::RemoveColor() {
798   m_pAnnot->GetAnnotDict()->RemoveAt("C");
799 }
800 
GetColor(FX_COLORREF & color) const801 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 
WriteAppearance(const CFX_ByteString & sAPType,const CPDF_Rect & rcBBox,const CFX_Matrix & matrix,const CFX_ByteString & sContents,const CFX_ByteString & sAPState)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 
GetMinWidth() const895 FX_FLOAT CPDFSDK_Annot::GetMinWidth() const {
896   return BA_ANNOT_MINWIDTH;
897 }
898 
GetMinHeight() const899 FX_FLOAT CPDFSDK_Annot::GetMinHeight() const {
900   return BA_ANNOT_MINHEIGHT;
901 }
902 
CreateFormFiller()903 FX_BOOL CPDFSDK_BAAnnot::CreateFormFiller() {
904   return TRUE;
905 }
IsVisible() const906 FX_BOOL CPDFSDK_BAAnnot::IsVisible() const {
907   int nFlags = GetFlags();
908   return !((nFlags & ANNOTFLAG_INVISIBLE) || (nFlags & ANNOTFLAG_HIDDEN) ||
909            (nFlags & ANNOTFLAG_NOVIEW));
910 }
911 
GetAction() const912 CPDF_Action CPDFSDK_BAAnnot::GetAction() const {
913   return CPDF_Action(m_pAnnot->GetAnnotDict()->GetDict("A"));
914 }
915 
SetAction(const CPDF_Action & action)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 
RemoveAction()929 void CPDFSDK_BAAnnot::RemoveAction() {
930   m_pAnnot->GetAnnotDict()->RemoveAt("A");
931 }
932 
GetAAction() const933 CPDF_AAction CPDFSDK_BAAnnot::GetAAction() const {
934   return m_pAnnot->GetAnnotDict()->GetDict("AA");
935 }
936 
SetAAction(const CPDF_AAction & aa)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 
RemoveAAction()942 void CPDFSDK_BAAnnot::RemoveAAction() {
943   m_pAnnot->GetAnnotDict()->RemoveAt("AA");
944 }
945 
GetAAction(CPDF_AAction::AActionType eAAT)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
IsXFAField()959 FX_BOOL CPDFSDK_BAAnnot::IsXFAField() {
960   return FALSE;
961 }
962 #endif  // PDF_ENABLE_XFA
963 
Annot_OnDraw(CFX_RenderDevice * pDevice,CFX_Matrix * pUser2Device,CPDF_RenderOptions * pOptions)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 
GetUnderlyingPage()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 
GetPDFPage()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
GetPDFXFAPage()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