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