Revert "FX Bool considered harmful, part 3"
[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     if (CPDF_Array* pBorder = m_pAnnot->GetAnnotDict()->GetArray("Border")) {
755         return pBorder->GetInteger(2);
756     }
757     if (CPDF_Dictionary* pBSDict = m_pAnnot->GetAnnotDict()->GetDict("BS")) {
758         return pBSDict->GetInteger("W", 1);
759     }
760     return 1;
761 }
762
763 void CPDFSDK_Annot::SetBorderStyle(int nStyle)
764 {
765     CPDF_Dictionary* pBSDict = m_pAnnot->GetAnnotDict()->GetDict("BS");
766     if (!pBSDict)
767     {
768         pBSDict = new CPDF_Dictionary;
769         m_pAnnot->GetAnnotDict()->SetAt("BS", pBSDict);
770     }
771
772     switch (nStyle)
773     {
774     case BBS_SOLID:
775         pBSDict->SetAtName("S", "S");
776         break;
777     case BBS_DASH:
778         pBSDict->SetAtName("S", "D");
779         break;
780     case BBS_BEVELED:
781         pBSDict->SetAtName("S", "B");
782         break;
783     case BBS_INSET:
784         pBSDict->SetAtName("S", "I");
785         break;
786     case BBS_UNDERLINE:
787         pBSDict->SetAtName("S", "U");
788         break;
789     }
790 }
791
792 int CPDFSDK_Annot::GetBorderStyle() const
793 {
794     CPDF_Dictionary* pBSDict = m_pAnnot->GetAnnotDict()->GetDict("BS");
795     if (pBSDict)
796     {
797         CFX_ByteString sBorderStyle = pBSDict->GetString("S", "S");
798         if (sBorderStyle == "S") return BBS_SOLID;
799         if (sBorderStyle == "D") return BBS_DASH;
800         if (sBorderStyle == "B") return BBS_BEVELED;
801         if (sBorderStyle == "I") return BBS_INSET;
802         if (sBorderStyle == "U") return BBS_UNDERLINE;
803     }
804
805     CPDF_Array* pBorder = m_pAnnot->GetAnnotDict()->GetArray("Border");
806     if (pBorder)
807     {
808         if (pBorder->GetCount() >= 4)
809         {
810             CPDF_Array *pDP = pBorder->GetArray(3);
811             if (pDP && pDP->GetCount() > 0)
812                 return BBS_DASH;
813         }
814     }
815
816     return BBS_SOLID;
817 }
818
819 void CPDFSDK_Annot::SetBorderDash(const CFX_IntArray& array)
820 {
821     CPDF_Dictionary* pBSDict = m_pAnnot->GetAnnotDict()->GetDict("BS");
822     if (!pBSDict)
823     {
824         pBSDict = new CPDF_Dictionary;
825         m_pAnnot->GetAnnotDict()->SetAt("BS", pBSDict);
826     }
827
828     CPDF_Array* pArray = new CPDF_Array;
829     for (int i=0,sz=array.GetSize(); i<sz; i++)
830     {
831         pArray->AddInteger(array[i]);
832     }
833
834     pBSDict->SetAt("D", pArray);
835 }
836
837 void CPDFSDK_Annot::GetBorderDash(CFX_IntArray& array) const
838 {
839     CPDF_Array* pDash = NULL;
840
841     CPDF_Array* pBorder = m_pAnnot->GetAnnotDict()->GetArray("Border");
842     if (pBorder)
843     {
844         pDash = pBorder->GetArray(3);
845     }
846     else
847     {
848         CPDF_Dictionary* pBSDict = m_pAnnot->GetAnnotDict()->GetDict("BS");
849         if (pBSDict)
850         {
851             pDash = pBSDict->GetArray("D");
852         }
853     }
854
855     if (pDash)
856     {
857         for (int i=0,sz=pDash->GetCount(); i<sz; i++)
858         {
859             array.Add(pDash->GetInteger(i));
860         }
861     }
862 }
863
864 void CPDFSDK_Annot::SetColor(FX_COLORREF color)
865 {
866     CPDF_Array* pArray = new CPDF_Array;
867     pArray->AddNumber((FX_FLOAT)FXSYS_GetRValue(color) / 255.0f);
868     pArray->AddNumber((FX_FLOAT)FXSYS_GetGValue(color) / 255.0f);
869     pArray->AddNumber((FX_FLOAT)FXSYS_GetBValue(color) / 255.0f);
870     m_pAnnot->GetAnnotDict()->SetAt("C", pArray);
871 }
872
873 void CPDFSDK_Annot::RemoveColor()
874 {
875     m_pAnnot->GetAnnotDict()->RemoveAt("C");
876 }
877
878 FX_BOOL CPDFSDK_Annot::GetColor(FX_COLORREF& color) const
879 {
880     if (CPDF_Array* pEntry = m_pAnnot->GetAnnotDict()->GetArray("C"))
881     {
882         int nCount = pEntry->GetCount();
883         if (nCount == 1)
884         {
885             FX_FLOAT g = pEntry->GetNumber(0) * 255;
886
887             color = FXSYS_RGB((int)g, (int)g, (int)g);
888
889             return TRUE;
890         }
891         else if (nCount == 3)
892         {
893             FX_FLOAT r = pEntry->GetNumber(0) * 255;
894             FX_FLOAT g = pEntry->GetNumber(1) * 255;
895             FX_FLOAT b = pEntry->GetNumber(2) * 255;
896
897             color = FXSYS_RGB((int)r, (int)g, (int)b);
898
899             return TRUE;
900         }
901         else if (nCount == 4)
902         {
903             FX_FLOAT c = pEntry->GetNumber(0);
904             FX_FLOAT m = pEntry->GetNumber(1);
905             FX_FLOAT y = pEntry->GetNumber(2);
906             FX_FLOAT k = pEntry->GetNumber(3);
907
908             FX_FLOAT r = 1.0f - FX_MIN(1.0f, c + k);
909             FX_FLOAT g = 1.0f - FX_MIN(1.0f, m + k);
910             FX_FLOAT b = 1.0f - FX_MIN(1.0f, y + k);
911
912             color = FXSYS_RGB((int)(r * 255), (int)(g * 255), (int)(b * 255));
913
914             return TRUE;
915         }
916     }
917
918     return FALSE;
919 }
920
921
922 void CPDFSDK_Annot::WriteAppearance(const CFX_ByteString& sAPType, const CPDF_Rect& rcBBox,
923                                 const CPDF_Matrix& matrix, const CFX_ByteString& sContents,
924                                 const CFX_ByteString& sAPState)
925 {
926     CPDF_Dictionary* pAPDict = m_pAnnot->GetAnnotDict()->GetDict("AP");
927
928     if (!pAPDict)
929     {
930         pAPDict = new CPDF_Dictionary;
931         m_pAnnot->GetAnnotDict()->SetAt("AP", pAPDict);
932     }
933
934     CPDF_Stream* pStream = NULL;
935     CPDF_Dictionary* pParentDict = NULL;
936
937     if (sAPState.IsEmpty())
938     {
939         pParentDict = pAPDict;
940         pStream = pAPDict->GetStream(sAPType);
941     }
942     else
943     {
944         CPDF_Dictionary* pAPTypeDict = pAPDict->GetDict(sAPType);
945         if (!pAPTypeDict)
946         {
947             pAPTypeDict = new CPDF_Dictionary;
948             pAPDict->SetAt(sAPType, pAPTypeDict);
949         }
950
951         pParentDict = pAPTypeDict;
952         pStream = pAPTypeDict->GetStream(sAPState);
953     }
954
955     if (!pStream)
956     {
957         CPDF_Document* pDoc = m_pPageView->GetPDFDocument();
958         pStream = new CPDF_Stream(NULL, 0, NULL);
959         int32_t objnum = pDoc->AddIndirectObject(pStream);
960         pParentDict->SetAtReference(sAPType, pDoc, objnum);
961     }
962
963     CPDF_Dictionary *pStreamDict = pStream->GetDict();
964     if (!pStreamDict)
965     {
966         pStreamDict = new CPDF_Dictionary;
967         pStreamDict->SetAtName("Type", "XObject");
968         pStreamDict->SetAtName("Subtype", "Form");
969         pStreamDict->SetAtInteger("FormType", 1);
970         pStream->InitStream(NULL,0,pStreamDict);
971     }
972
973     if (pStreamDict)
974     {
975         pStreamDict->SetAtMatrix("Matrix",matrix);
976         pStreamDict->SetAtRect("BBox", rcBBox);
977     }
978
979     pStream->SetData((uint8_t*)sContents.c_str(), sContents.GetLength(), FALSE, FALSE);
980 }
981
982 #define BA_ANNOT_MINWIDTH           1
983 #define BA_ANNOT_MINHEIGHT          1
984
985 FX_FLOAT CPDFSDK_Annot::GetMinWidth() const
986 {
987     return BA_ANNOT_MINWIDTH;
988 }
989
990 FX_FLOAT CPDFSDK_Annot::GetMinHeight() const
991 {
992     return BA_ANNOT_MINHEIGHT;
993 }
994
995 FX_BOOL CPDFSDK_Annot::CreateFormFiller()
996 {
997     return TRUE;
998 }
999 FX_BOOL CPDFSDK_Annot::IsVisible() const
1000 {
1001     int nFlags = GetFlags();
1002     return !((nFlags & ANNOTFLAG_INVISIBLE) || (nFlags & ANNOTFLAG_HIDDEN) || (nFlags & ANNOTFLAG_NOVIEW));
1003 }
1004
1005 CPDF_Action CPDFSDK_Annot::GetAction() const
1006 {
1007     return CPDF_Action(m_pAnnot->GetAnnotDict()->GetDict("A"));
1008 }
1009
1010 void CPDFSDK_Annot::SetAction(const CPDF_Action& action)
1011 {
1012     ASSERT(action);
1013     if ((CPDF_Action&)action != CPDF_Action(m_pAnnot->GetAnnotDict()->GetDict("A")))
1014     {
1015         CPDF_Document* pDoc = m_pPageView->GetPDFDocument();
1016         CPDF_Dictionary* pDict = action.GetDict();
1017         if (pDict && pDict->GetObjNum() == 0) {
1018             pDoc->AddIndirectObject(pDict);
1019         }
1020         m_pAnnot->GetAnnotDict()->SetAtReference("A", pDoc, pDict->GetObjNum());
1021     }
1022 }
1023
1024 void CPDFSDK_Annot::RemoveAction()
1025 {
1026     m_pAnnot->GetAnnotDict()->RemoveAt("A");
1027 }
1028
1029 CPDF_AAction CPDFSDK_Annot::GetAAction() const
1030 {
1031     return m_pAnnot->GetAnnotDict()->GetDict("AA");
1032 }
1033
1034 void CPDFSDK_Annot::SetAAction(const CPDF_AAction& aa)
1035 {
1036     ASSERT(aa != NULL);
1037
1038     if ((CPDF_AAction&)aa != m_pAnnot->GetAnnotDict()->GetDict("AA"))
1039         m_pAnnot->GetAnnotDict()->SetAt("AA", (CPDF_AAction&)aa);
1040 }
1041
1042 void CPDFSDK_Annot::RemoveAAction()
1043 {
1044     m_pAnnot->GetAnnotDict()->RemoveAt("AA");
1045 }
1046
1047 CPDF_Action CPDFSDK_Annot::GetAAction(CPDF_AAction::AActionType eAAT)
1048 {
1049     CPDF_AAction AAction = GetAAction();
1050
1051     if (AAction.ActionExist(eAAT))
1052         return AAction.GetAction(eAAT);
1053
1054     if (eAAT == CPDF_AAction::ButtonUp)
1055         return GetAction();
1056
1057     return CPDF_Action();
1058 }
1059
1060 void  CPDFSDK_Annot::Annot_OnDraw(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device, CPDF_RenderOptions* pOptions)
1061 {
1062
1063     m_pAnnot->GetAPForm(m_pPageView->GetPDFPage(), CPDF_Annot::Normal);
1064     m_pAnnot->DrawAppearance(m_pPageView->GetPDFPage(), pDevice, pUser2Device, CPDF_Annot::Normal, NULL);
1065
1066     return ;
1067 }
1068
1069 CPDF_Page* CPDFSDK_Annot::GetPDFPage()
1070 {
1071     if(m_pPageView)
1072         return m_pPageView->GetPDFPage();
1073     return NULL;
1074 }
1075