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