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