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/fsdk_mgr.h"
9 #include "../include/fsdk_baseannot.h"
10
11
12 //---------------------------------------------------------------------------
13 //                                                              CPDFSDK_DateTime        
14 //---------------------------------------------------------------------------
15 int _gAfxGetTimeZoneInSeconds(FX_CHAR tzhour, FX_BYTE tzminute)
16 {
17         return (int)tzhour * 3600 + (int)tzminute * (tzhour >= 0 ? 60 : -60);
18 }
19
20 FX_BOOL _gAfxIsLeapYear(FX_SHORT year)
21 {
22         return ((year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0)));
23 }
24
25 FX_WORD _gAfxGetYearDays(FX_SHORT year)
26 {
27         return (_gAfxIsLeapYear(year) == TRUE ? 366 : 365);
28 }
29
30 FX_BYTE _gAfxGetMonthDays(FX_SHORT year, FX_BYTE month)
31 {
32         FX_BYTE 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 = (FX_SHORT)st.wYear;
121         dt.month = (FX_BYTE)st.wMonth;
122         dt.day = (FX_BYTE)st.wDay;
123         dt.hour = (FX_BYTE)st.wHour;
124         dt.minute = (FX_BYTE)st.wMinute;
125         dt.second = (FX_BYTE)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 = (FX_SHORT)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 = (FX_BYTE)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 = (FX_BYTE)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 = (FX_BYTE)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 = (FX_BYTE)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 = (FX_BYTE)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 = (FX_BYTE)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         sprintf(tempStr, "D:%04d%02d%02d%02d%02d%02d", dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second);
361         dtStr = CFX_ByteString(tempStr);
362         if (dt.tzHour < 0)
363                 dtStr += CFX_ByteString("-");
364         else
365                 dtStr += CFX_ByteString("+");
366         sprintf(tempStr, "%02d'%02d'", abs(dt.tzHour), dt.tzMinute);
367         dtStr += CFX_ByteString(tempStr);
368         return dtStr;
369 }
370
371 void CPDFSDK_DateTime::ToSystemTime(FX_SYSTEMTIME& st)
372 {
373         CPDFSDK_DateTime dt = *this;
374         time_t t = (time_t)dt;
375         struct tm* pTime = localtime(&t);
376         if(pTime){ 
377                 st.wYear = (FX_WORD)pTime->tm_year + 1900;
378                 st.wMonth = (FX_WORD)pTime->tm_mon + 1;
379                 st.wDay = (FX_WORD)pTime->tm_mday;
380                 st.wDayOfWeek = (FX_WORD)pTime->tm_wday;
381                 st.wHour = (FX_WORD)pTime->tm_hour;
382                 st.wMinute = (FX_WORD)pTime->tm_min;
383                 st.wSecond = (FX_WORD)pTime->tm_sec;
384                 st.wMilliseconds = 0;
385         }
386 }
387
388 CPDFSDK_DateTime CPDFSDK_DateTime::ToGMT()
389 {
390         CPDFSDK_DateTime dt = *this;
391         dt.AddSeconds(-_gAfxGetTimeZoneInSeconds(dt.dt.tzHour, dt.dt.tzMinute));
392         dt.dt.tzHour = 0;
393         dt.dt.tzMinute = 0;
394         return dt;
395 }
396
397 CPDFSDK_DateTime& CPDFSDK_DateTime::AddDays(short days)
398 {
399         if (days == 0) return *this;
400
401         FX_SHORT        y = dt.year, yy;
402         FX_BYTE         m = dt.month;
403         FX_BYTE         d = dt.day;
404         int                     mdays, ydays, ldays;
405
406         ldays = days;
407         if (ldays > 0)
408         {
409                 yy = y;
410                 if (((FX_WORD)m * 100 + d) > 300) yy ++;
411                 ydays = _gAfxGetYearDays(yy);
412                 while (ldays >= ydays)
413                 {
414                         y ++;
415                         ldays -= ydays;
416                         yy ++;
417                         mdays = _gAfxGetMonthDays(y, m);
418                         if (d > mdays)
419                         {
420                                 m ++;
421                                 d -= mdays;
422                         }
423                         ydays = _gAfxGetYearDays(yy);
424                 }
425                 mdays = _gAfxGetMonthDays(y, m) - d + 1;
426                 while (ldays >= mdays)
427                 {
428                         ldays -= mdays;
429                         m ++;
430                         d = 1;
431                         mdays = _gAfxGetMonthDays(y, m);
432                 }
433                 d += ldays;
434         }
435         else
436         {
437                 ldays *= -1;
438                 yy = y;
439                 if (((FX_WORD)m * 100 + d) < 300) yy --;
440                 ydays = _gAfxGetYearDays(yy);
441                 while (ldays >= ydays)
442                 {
443                         y --;
444                         ldays -= ydays;
445                         yy --;
446                         mdays = _gAfxGetMonthDays(y, m);
447                         if (d > mdays)
448                         {
449                                 m ++;
450                                 d -= mdays;
451                         }
452                         ydays = _gAfxGetYearDays(yy);
453                 }
454                 while (ldays >= d)
455                 {
456                         ldays -= d;
457                         m --;
458                         mdays = _gAfxGetMonthDays(y, m);
459                         d = mdays;
460                 }
461                 d -= ldays;
462         }
463
464         dt.year = y;
465         dt.month = m;
466         dt.day = d;
467
468         return *this;
469 }
470
471 CPDFSDK_DateTime& CPDFSDK_DateTime::AddSeconds(int seconds)
472 {
473         if (seconds == 0) return *this;
474
475         int     n;
476         int     days;
477
478         n = dt.hour * 3600 + dt.minute * 60 + dt.second + seconds;
479         if (n < 0)
480         {
481                 days = (n - 86399) / 86400;
482                 n -= days * 86400;
483         }
484         else
485         {
486                 days = n / 86400;
487                 n %= 86400;
488         }
489         dt.hour = (FX_BYTE)(n / 3600);
490         dt.hour %= 24;
491         n %= 3600;
492         dt.minute = (FX_BYTE)(n / 60);
493         dt.second = (FX_BYTE)(n % 60);
494         if (days != 0) AddDays(days);
495
496         return *this;
497 }
498
499
500 //---------------------------------------------------------------------------
501 //                                                              CPDFSDK_Annot   
502 //---------------------------------------------------------------------------
503 CPDFSDK_Annot::CPDFSDK_Annot(CPDF_Annot* pAnnot, CPDFSDK_PageView* pPageView) :
504 m_pAnnot(pAnnot),
505 m_pPageView(pPageView),
506 m_bSelected(FALSE),
507 m_nTabOrder(-1)
508 {
509 }
510
511 CPDFSDK_Annot::~CPDFSDK_Annot()
512 {
513         m_pAnnot = NULL;
514         m_pPageView = NULL;
515 }
516
517 CPDF_Annot*     CPDFSDK_Annot::GetPDFAnnot()
518 {
519         return m_pAnnot;
520 }
521
522 FX_DWORD CPDFSDK_Annot::GetFlags()
523 {
524         ASSERT(m_pAnnot != NULL);
525         
526         return m_pAnnot->GetFlags();
527 }
528
529 void CPDFSDK_Annot::SetPage(CPDFSDK_PageView* pPageView)
530 {
531         m_pPageView = pPageView;
532 }
533
534 CPDFSDK_PageView* CPDFSDK_Annot::GetPageView()
535 {
536         return m_pPageView;
537 }
538
539 FX_BOOL CPDFSDK_Annot::IsSelected()
540 {
541         return m_bSelected;
542 }
543
544 void CPDFSDK_Annot::SetSelected(FX_BOOL bSelected)
545 {
546         m_bSelected = bSelected;
547 }
548
549 // Tab Order    
550 int CPDFSDK_Annot::GetTabOrder()
551 {
552         return m_nTabOrder;
553 }
554
555 void CPDFSDK_Annot::SetTabOrder(int iTabOrder)
556 {
557         m_nTabOrder = iTabOrder;
558 }
559
560 CPDF_Dictionary* CPDFSDK_Annot::GetAnnotDict() const
561 {
562         ASSERT(m_pAnnot != NULL);
563         
564         return m_pAnnot->m_pAnnotDict;
565 }
566
567 void CPDFSDK_Annot::SetRect(const CPDF_Rect& rect)
568 {
569         ASSERT(m_pAnnot != NULL);
570         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
571         ASSERT(rect.right - rect.left >= GetMinWidth());
572         ASSERT(rect.top - rect.bottom >= GetMinHeight());
573         
574         m_pAnnot->m_pAnnotDict->SetAtRect("Rect", rect);
575 }
576
577 CPDF_Rect CPDFSDK_Annot::GetRect() const
578 {
579         ASSERT(m_pAnnot != NULL);
580         
581         CPDF_Rect rect;
582         m_pAnnot->GetRect(rect);
583         
584         return rect;
585 }
586
587 CFX_ByteString CPDFSDK_Annot::GetType() const
588 {
589         ASSERT(m_pAnnot != NULL);
590         
591         return m_pAnnot->GetSubType();
592 }
593
594 CFX_ByteString CPDFSDK_Annot::GetSubType() const
595 {
596         return "";
597 }
598
599 void CPDFSDK_Annot::DrawAppearance(CFX_RenderDevice* pDevice, const CPDF_Matrix* pUser2Device,
600                                                                    CPDF_Annot::AppearanceMode mode, const CPDF_RenderOptions* pOptions) 
601 {
602         ASSERT(m_pPageView != NULL);
603         ASSERT(m_pAnnot != NULL);
604         
605         m_pAnnot->DrawAppearance(m_pPageView->GetPDFPage(), pDevice, pUser2Device, mode, pOptions);
606 }
607
608 FX_BOOL CPDFSDK_Annot::IsAppearanceValid()
609 {
610         ASSERT(m_pAnnot != NULL);
611         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
612         
613         return m_pAnnot->m_pAnnotDict->GetDict("AP") != NULL;
614 }
615
616 FX_BOOL CPDFSDK_Annot::IsAppearanceValid(CPDF_Annot::AppearanceMode mode)
617 {
618         ASSERT(m_pAnnot != NULL);
619         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
620         
621         CPDF_Dictionary* pAP = m_pAnnot->m_pAnnotDict->GetDict("AP");
622         if (pAP == NULL) return FALSE;
623         
624         // Choose the right sub-ap
625         const FX_CHAR* ap_entry = "N";
626         if (mode == CPDF_Annot::Down)
627                 ap_entry = "D";
628         else if (mode == CPDF_Annot::Rollover)
629                 ap_entry = "R";
630         if (!pAP->KeyExist(ap_entry))
631                 ap_entry = "N";
632         
633         // Get the AP stream or subdirectory
634         CPDF_Object* psub = pAP->GetElementValue(ap_entry);
635         if (psub == NULL) return FALSE;
636         
637         return TRUE;
638 }
639
640 void CPDFSDK_Annot::DrawBorder(CFX_RenderDevice* pDevice, const CPDF_Matrix* pUser2Device,
641                                                    const CPDF_RenderOptions* pOptions)
642 {
643         ASSERT(m_pAnnot != NULL);
644         m_pAnnot->DrawBorder(pDevice, pUser2Device, pOptions); 
645 }
646
647 void CPDFSDK_Annot::ClearCachedAP()
648 {
649         ASSERT(m_pAnnot != NULL);
650         m_pAnnot->ClearCachedAP();
651 }    
652
653 void CPDFSDK_Annot::SetContents(const CFX_WideString& sContents)
654 {
655         ASSERT(m_pAnnot != NULL);
656         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
657         
658         if (sContents.IsEmpty())
659                 m_pAnnot->m_pAnnotDict->RemoveAt("Contents");
660         else
661                 m_pAnnot->m_pAnnotDict->SetAtString("Contents", PDF_EncodeText(sContents));
662 }
663
664 CFX_WideString CPDFSDK_Annot::GetContents() const
665 {
666         ASSERT(m_pAnnot != NULL);
667         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
668         
669         return m_pAnnot->m_pAnnotDict->GetUnicodeText("Contents");
670 }
671
672 void CPDFSDK_Annot::SetAnnotName(const CFX_WideString& sName)
673 {
674         ASSERT(m_pAnnot != NULL);
675         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
676         
677         if (sName.IsEmpty())
678                 m_pAnnot->m_pAnnotDict->RemoveAt("NM");
679         else
680                 m_pAnnot->m_pAnnotDict->SetAtString("NM", PDF_EncodeText(sName));
681 }
682
683 CFX_WideString CPDFSDK_Annot::GetAnnotName() const
684 {
685         ASSERT(m_pAnnot != NULL);
686         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
687         
688         return m_pAnnot->m_pAnnotDict->GetUnicodeText("NM");
689 }
690
691 void CPDFSDK_Annot::SetModifiedDate(const FX_SYSTEMTIME& st)
692 {
693         ASSERT(m_pAnnot != NULL);
694         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
695         
696         CPDFSDK_DateTime dt(st);
697         CFX_ByteString str = dt.ToPDFDateTimeString();
698         
699         if (str.IsEmpty())
700                 m_pAnnot->m_pAnnotDict->RemoveAt("M");
701         else
702                 m_pAnnot->m_pAnnotDict->SetAtString("M", str);
703 }
704
705 FX_SYSTEMTIME CPDFSDK_Annot::GetModifiedDate() const
706 {
707         ASSERT(m_pAnnot != NULL);
708         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
709         
710         FX_SYSTEMTIME systime;  
711         CFX_ByteString str = m_pAnnot->m_pAnnotDict->GetString("M");
712         
713         CPDFSDK_DateTime dt(str);
714         dt.ToSystemTime(systime);
715         
716         return systime;
717 }
718
719 void CPDFSDK_Annot::SetFlags(int nFlags)
720 {
721         ASSERT(m_pAnnot != NULL);
722         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
723         
724         m_pAnnot->m_pAnnotDict->SetAtInteger("F", nFlags);
725 }
726
727 int CPDFSDK_Annot::GetFlags() const
728 {
729         ASSERT(m_pAnnot != NULL);
730         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
731         
732         return m_pAnnot->m_pAnnotDict->GetInteger("F");
733 }
734
735 void CPDFSDK_Annot::SetAppState(const CFX_ByteString& str)
736 {
737         ASSERT(m_pAnnot != NULL);
738         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
739
740         if (str.IsEmpty())
741                 m_pAnnot->m_pAnnotDict->RemoveAt("AS");
742         else
743                 m_pAnnot->m_pAnnotDict->SetAtString("AS", str);
744 }
745
746 CFX_ByteString CPDFSDK_Annot::GetAppState() const
747 {
748         ASSERT(m_pAnnot != NULL);
749         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
750
751         return m_pAnnot->m_pAnnotDict->GetString("AS");
752 }
753
754 void CPDFSDK_Annot::SetStructParent(int key)
755 {
756         ASSERT(m_pAnnot != NULL);
757         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
758         
759         m_pAnnot->m_pAnnotDict->SetAtInteger("StructParent", key);
760 }
761
762 int     CPDFSDK_Annot::GetStructParent() const
763 {
764         ASSERT(m_pAnnot != NULL);
765         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
766         
767         return m_pAnnot->m_pAnnotDict->GetInteger("StructParent");
768 }
769
770 //border
771 void CPDFSDK_Annot::SetBorderWidth(int nWidth)
772 {
773         ASSERT(m_pAnnot != NULL);
774         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
775
776         CPDF_Array* pBorder = m_pAnnot->m_pAnnotDict->GetArray("Border");
777
778         if (pBorder)
779         {
780                 pBorder->SetAt(2, FX_NEW CPDF_Number(nWidth));
781         }
782         else
783         {
784                 CPDF_Dictionary* pBSDict = m_pAnnot->m_pAnnotDict->GetDict("BS");
785
786                 if (!pBSDict)
787                 {
788                         pBSDict = FX_NEW CPDF_Dictionary;
789                         m_pAnnot->m_pAnnotDict->SetAt("BS", pBSDict);
790                 }
791
792                 pBSDict->SetAtInteger("W", nWidth);
793         }
794 }
795
796 int     CPDFSDK_Annot::GetBorderWidth() const
797 {
798         ASSERT(m_pAnnot != NULL);
799         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
800
801         CPDF_Array* pBorder = m_pAnnot->m_pAnnotDict->GetArray("Border");
802
803         if (pBorder)
804         {
805                 return pBorder->GetInteger(2);
806         }
807         else
808         {
809                 CPDF_Dictionary* pBSDict = m_pAnnot->m_pAnnotDict->GetDict("BS");
810
811                 if (pBSDict)
812                 {
813                         return pBSDict->GetInteger("W", 1);
814                 }
815         }
816         return 1;
817 }
818
819 void CPDFSDK_Annot::SetBorderStyle(int nStyle)
820 {
821         ASSERT(m_pAnnot != NULL);
822         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
823
824         CPDF_Dictionary* pBSDict = m_pAnnot->m_pAnnotDict->GetDict("BS");
825         if (!pBSDict)
826         {
827                 pBSDict = FX_NEW CPDF_Dictionary;
828                 m_pAnnot->m_pAnnotDict->SetAt("BS", pBSDict);
829         }
830
831         switch (nStyle)
832         {
833         case BBS_SOLID:
834                 pBSDict->SetAtName("S", "S");
835                 break;
836         case BBS_DASH:
837                 pBSDict->SetAtName("S", "D");
838                 break;
839         case BBS_BEVELED:
840                 pBSDict->SetAtName("S", "B");
841                 break;
842         case BBS_INSET:
843                 pBSDict->SetAtName("S", "I");
844                 break;
845         case BBS_UNDERLINE:
846                 pBSDict->SetAtName("S", "U");
847                 break;
848         }
849 }
850
851 int     CPDFSDK_Annot::GetBorderStyle() const
852 {
853         ASSERT(m_pAnnot != NULL);
854         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
855
856         CPDF_Dictionary* pBSDict = m_pAnnot->m_pAnnotDict->GetDict("BS");
857         if (pBSDict)
858         {
859                 CFX_ByteString sBorderStyle = pBSDict->GetString("S", "S");
860                 if (sBorderStyle == "S") return BBS_SOLID;
861                 if (sBorderStyle == "D") return BBS_DASH;
862                 if (sBorderStyle == "B") return BBS_BEVELED;
863                 if (sBorderStyle == "I") return BBS_INSET;
864                 if (sBorderStyle == "U") return BBS_UNDERLINE;
865         }
866
867         CPDF_Array* pBorder = m_pAnnot->m_pAnnotDict->GetArray("Border");
868         if (pBorder)
869         {
870                 if (pBorder->GetCount() >= 4) 
871                 { 
872                         CPDF_Array *pDP = pBorder->GetArray(3);
873                         if (pDP && pDP->GetCount() > 0)
874                                 return BBS_DASH;
875                 }
876         }
877
878         return BBS_SOLID;
879 }
880
881 void CPDFSDK_Annot::SetBorderDash(const CFX_IntArray& array)
882 {
883         ASSERT(m_pAnnot != NULL);
884         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
885
886         CPDF_Dictionary* pBSDict = m_pAnnot->m_pAnnotDict->GetDict("BS");
887         if (!pBSDict)
888         {
889                 pBSDict = FX_NEW CPDF_Dictionary;
890                 m_pAnnot->m_pAnnotDict->SetAt("BS", pBSDict);
891         }
892
893         CPDF_Array* pArray = FX_NEW CPDF_Array;
894         for (int i=0,sz=array.GetSize(); i<sz; i++)
895         {
896                 pArray->AddInteger(array[i]);
897         }
898
899         pBSDict->SetAt("D", pArray);
900 }
901
902 void CPDFSDK_Annot::GetBorderDash(CFX_IntArray& array) const
903 {
904         ASSERT(m_pAnnot != NULL);
905         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
906
907         CPDF_Array* pDash = NULL;
908
909         CPDF_Array* pBorder = m_pAnnot->m_pAnnotDict->GetArray("Border");
910         if (pBorder)
911         {
912                 pDash = pBorder->GetArray(3);
913         }
914         else
915         {
916                 CPDF_Dictionary* pBSDict = m_pAnnot->m_pAnnotDict->GetDict("BS");
917                 if (pBSDict)
918                 {
919                         pDash = pBSDict->GetArray("D");
920                 }
921         }
922
923         if (pDash)
924         {
925                 for (int i=0,sz=pDash->GetCount(); i<sz; i++)
926                 {
927                         array.Add(pDash->GetInteger(i));
928                 }
929         }
930 }
931
932 void CPDFSDK_Annot::SetColor(FX_COLORREF color)
933 {
934         ASSERT(m_pAnnot != NULL);
935         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
936
937         CPDF_Array* pArray = FX_NEW CPDF_Array;
938         pArray->AddNumber((FX_FLOAT)FXSYS_GetRValue(color) / 255.0f);
939         pArray->AddNumber((FX_FLOAT)FXSYS_GetGValue(color) / 255.0f);
940         pArray->AddNumber((FX_FLOAT)FXSYS_GetBValue(color) / 255.0f);
941         m_pAnnot->m_pAnnotDict->SetAt("C", pArray);
942 }
943
944 void CPDFSDK_Annot::RemoveColor()
945 {
946         ASSERT(m_pAnnot != NULL);
947         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
948
949         m_pAnnot->m_pAnnotDict->RemoveAt("C") ; 
950 }
951
952 FX_BOOL CPDFSDK_Annot::GetColor(FX_COLORREF& color) const
953 {
954         ASSERT(m_pAnnot != NULL);
955         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
956
957         if (CPDF_Array* pEntry = m_pAnnot->m_pAnnotDict->GetArray("C"))         
958         {
959                 int nCount = pEntry->GetCount();
960                 if (nCount == 1)
961                 {
962                         FX_FLOAT g = pEntry->GetNumber(0) * 255;
963
964                         color = FXSYS_RGB((int)g, (int)g, (int)g);
965
966                         return TRUE;
967                 }
968                 else if (nCount == 3)
969                 {
970                         FX_FLOAT r = pEntry->GetNumber(0) * 255;
971                         FX_FLOAT g = pEntry->GetNumber(1) * 255;
972                         FX_FLOAT b = pEntry->GetNumber(2) * 255;
973
974                         color = FXSYS_RGB((int)r, (int)g, (int)b);
975
976                         return TRUE;
977                 }
978                 else if (nCount == 4)
979                 {
980                         FX_FLOAT c = pEntry->GetNumber(0);
981                         FX_FLOAT m = pEntry->GetNumber(1);
982                         FX_FLOAT y = pEntry->GetNumber(2);
983                         FX_FLOAT k = pEntry->GetNumber(3);
984
985                         FX_FLOAT r = 1.0f - FX_MIN(1.0f, c + k);
986                         FX_FLOAT g = 1.0f - FX_MIN(1.0f, m + k);
987                         FX_FLOAT b = 1.0f - FX_MIN(1.0f, y + k);
988
989                         color = FXSYS_RGB((int)(r * 255), (int)(g * 255), (int)(b * 255));
990
991                         return TRUE;
992                 }
993         }
994
995         return FALSE;
996 }
997
998
999 void CPDFSDK_Annot::WriteAppearance(const CFX_ByteString& sAPType, const CPDF_Rect& rcBBox, 
1000                                                                 const CPDF_Matrix& matrix, const CFX_ByteString& sContents,
1001                                                                 const CFX_ByteString& sAPState)
1002 {
1003         ASSERT(m_pAnnot != NULL);
1004         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
1005         
1006         CPDF_Dictionary* pAPDict = m_pAnnot->m_pAnnotDict->GetDict("AP");
1007         
1008         if (!pAPDict) 
1009         {
1010                 pAPDict = FX_NEW CPDF_Dictionary;
1011                 m_pAnnot->m_pAnnotDict->SetAt("AP", pAPDict);
1012         }
1013         
1014         CPDF_Stream* pStream = NULL;
1015         CPDF_Dictionary* pParentDict = NULL;
1016         
1017         if (sAPState.IsEmpty())
1018         {
1019                 pParentDict = pAPDict;
1020                 pStream = pAPDict->GetStream(sAPType);
1021         }
1022         else
1023         {
1024                 CPDF_Dictionary* pAPTypeDict = pAPDict->GetDict(sAPType);
1025                 if (!pAPTypeDict)
1026                 {
1027                         pAPTypeDict = FX_NEW CPDF_Dictionary;
1028                         pAPDict->SetAt(sAPType, pAPTypeDict);
1029                 }
1030                 
1031                 pParentDict = pAPTypeDict;
1032                 pStream = pAPTypeDict->GetStream(sAPState);
1033         }
1034         
1035         if (!pStream) 
1036         {
1037                 ASSERT(m_pPageView != NULL);
1038                 CPDF_Document* pDoc = m_pPageView->GetPDFDocument();
1039                 ASSERT(pDoc != NULL);
1040                 
1041                 pStream = FX_NEW CPDF_Stream(NULL, 0, NULL);
1042                 FX_INT32 objnum = pDoc->AddIndirectObject(pStream);
1043                 //pAPDict->SetAtReference(sAPType, pDoc, objnum);
1044                 ASSERT(pParentDict != NULL);
1045                 pParentDict->SetAtReference(sAPType, pDoc, objnum);
1046         }
1047         
1048         CPDF_Dictionary * pStreamDict = pStream->GetDict();
1049         
1050         if (!pStreamDict)
1051         {
1052                 pStreamDict = FX_NEW CPDF_Dictionary;
1053                 pStreamDict->SetAtName("Type", "XObject");
1054                 pStreamDict->SetAtName("Subtype", "Form");
1055                 pStreamDict->SetAtInteger("FormType", 1);
1056                 pStream->InitStream(NULL,0,pStreamDict);
1057         }
1058         
1059         if (pStreamDict)
1060         {
1061                 pStreamDict->SetAtMatrix("Matrix",matrix);      
1062                 pStreamDict->SetAtRect("BBox", rcBBox);         
1063         }
1064         
1065         pStream->SetData((FX_BYTE*)sContents.c_str(), sContents.GetLength(), FALSE, FALSE);
1066 }
1067
1068 #define BA_ANNOT_MINWIDTH                       1
1069 #define BA_ANNOT_MINHEIGHT                      1
1070
1071 FX_FLOAT CPDFSDK_Annot::GetMinWidth() const
1072 {
1073         return BA_ANNOT_MINWIDTH;
1074 }
1075
1076 FX_FLOAT CPDFSDK_Annot::GetMinHeight() const
1077 {
1078         return BA_ANNOT_MINHEIGHT;
1079 }
1080
1081 FX_BOOL CPDFSDK_Annot::CreateFormFiller()
1082 {
1083         return TRUE;
1084 }
1085 FX_BOOL CPDFSDK_Annot::IsVisible() const
1086 {
1087         int nFlags = GetFlags();
1088         return !((nFlags & ANNOTFLAG_INVISIBLE) || (nFlags & ANNOTFLAG_HIDDEN) || (nFlags & ANNOTFLAG_NOVIEW));
1089 }
1090
1091 CPDF_Action CPDFSDK_Annot::GetAction() const
1092 {
1093         return CPDF_Action(m_pAnnot->m_pAnnotDict->GetDict("A"));
1094 }
1095
1096 void CPDFSDK_Annot::SetAction(const CPDF_Action& action)
1097 {
1098         ASSERT(action);
1099         if ((CPDF_Action&)action != CPDF_Action(m_pAnnot->m_pAnnotDict->GetDict("A")))
1100         {
1101                 CPDF_Document* pDoc = m_pPageView->GetPDFDocument();
1102                 CPDF_Dictionary* pDict = action.GetDict();
1103                 if (pDict && pDict->GetObjNum() == 0) {
1104                         pDoc->AddIndirectObject(pDict);
1105                 }
1106                 m_pAnnot->m_pAnnotDict->SetAtReference("A", pDoc, pDict->GetObjNum());
1107         }
1108 }
1109
1110 void CPDFSDK_Annot::RemoveAction()
1111 {
1112         m_pAnnot->m_pAnnotDict->RemoveAt("A");
1113 }
1114
1115 CPDF_AAction CPDFSDK_Annot::GetAAction() const
1116 {
1117         return m_pAnnot->m_pAnnotDict->GetDict("AA");
1118 }
1119
1120 void CPDFSDK_Annot::SetAAction(const CPDF_AAction& aa)
1121 {
1122         ASSERT(m_pAnnot != NULL);
1123         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
1124         ASSERT(aa != NULL);
1125         
1126         if ((CPDF_AAction&)aa != m_pAnnot->m_pAnnotDict->GetDict("AA"))
1127                 m_pAnnot->m_pAnnotDict->SetAt("AA", (CPDF_AAction&)aa);
1128 }
1129
1130 void CPDFSDK_Annot::RemoveAAction()
1131 {
1132         ASSERT(m_pAnnot != NULL);
1133         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
1134         
1135         m_pAnnot->m_pAnnotDict->RemoveAt("AA");
1136 }
1137
1138 CPDF_Action     CPDFSDK_Annot::GetAAction(CPDF_AAction::AActionType eAAT)
1139 {
1140         CPDF_AAction AAction = GetAAction();
1141
1142         if (AAction.ActionExist(eAAT))
1143                 return AAction.GetAction(eAAT);
1144
1145         if (eAAT == CPDF_AAction::ButtonUp)
1146                 return GetAction();
1147
1148         return CPDF_Action();
1149 }
1150
1151 void  CPDFSDK_Annot::Annot_OnDraw(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device, CPDF_RenderOptions* pOptions)
1152 {
1153         
1154         m_pAnnot->GetAPForm(m_pPageView->GetPDFPage(), CPDF_Annot::Normal);
1155         m_pAnnot->DrawAppearance(m_pPageView->GetPDFPage(), pDevice, pUser2Device, CPDF_Annot::Normal, NULL);
1156
1157         return ;
1158 }
1159
1160 CPDF_Page* CPDFSDK_Annot::GetPDFPage()
1161 {
1162         if(m_pPageView)
1163                 return m_pPageView->GetPDFPage();
1164         return NULL;
1165 }
1166