Convert all line endings to LF.
[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::ResetAppearance()
600 {
601         ASSERT(FALSE);
602 }
603
604 void CPDFSDK_Annot::DrawAppearance(CFX_RenderDevice* pDevice, const CPDF_Matrix* pUser2Device,
605                                                                    CPDF_Annot::AppearanceMode mode, const CPDF_RenderOptions* pOptions) 
606 {
607         ASSERT(m_pPageView != NULL);
608         ASSERT(m_pAnnot != NULL);
609         
610         m_pAnnot->DrawAppearance(m_pPageView->GetPDFPage(), pDevice, pUser2Device, mode, pOptions);
611 }
612
613 FX_BOOL CPDFSDK_Annot::IsAppearanceValid()
614 {
615         ASSERT(m_pAnnot != NULL);
616         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
617         
618         return m_pAnnot->m_pAnnotDict->GetDict("AP") != NULL;
619 }
620
621 FX_BOOL CPDFSDK_Annot::IsAppearanceValid(CPDF_Annot::AppearanceMode mode)
622 {
623         ASSERT(m_pAnnot != NULL);
624         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
625         
626         CPDF_Dictionary* pAP = m_pAnnot->m_pAnnotDict->GetDict("AP");
627         if (pAP == NULL) return FALSE;
628         
629         // Choose the right sub-ap
630         const FX_CHAR* ap_entry = "N";
631         if (mode == CPDF_Annot::Down)
632                 ap_entry = "D";
633         else if (mode == CPDF_Annot::Rollover)
634                 ap_entry = "R";
635         if (!pAP->KeyExist(ap_entry))
636                 ap_entry = "N";
637         
638         // Get the AP stream or subdirectory
639         CPDF_Object* psub = pAP->GetElementValue(ap_entry);
640         if (psub == NULL) return FALSE;
641         
642         return TRUE;
643 }
644
645 void CPDFSDK_Annot::DrawBorder(CFX_RenderDevice* pDevice, const CPDF_Matrix* pUser2Device,
646                                                    const CPDF_RenderOptions* pOptions)
647 {
648         ASSERT(m_pAnnot != NULL);
649         m_pAnnot->DrawBorder(pDevice, pUser2Device, pOptions); 
650 }
651
652 void CPDFSDK_Annot::ClearCachedAP()
653 {
654         ASSERT(m_pAnnot != NULL);
655         m_pAnnot->ClearCachedAP();
656 }    
657
658 void CPDFSDK_Annot::SetContents(const CFX_WideString& sContents)
659 {
660         ASSERT(m_pAnnot != NULL);
661         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
662         
663         if (sContents.IsEmpty())
664                 m_pAnnot->m_pAnnotDict->RemoveAt("Contents");
665         else
666                 m_pAnnot->m_pAnnotDict->SetAtString("Contents", PDF_EncodeText(sContents));
667 }
668
669 CFX_WideString CPDFSDK_Annot::GetContents() const
670 {
671         ASSERT(m_pAnnot != NULL);
672         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
673         
674         return m_pAnnot->m_pAnnotDict->GetUnicodeText("Contents");
675 }
676
677 void CPDFSDK_Annot::SetAnnotName(const CFX_WideString& sName)
678 {
679         ASSERT(m_pAnnot != NULL);
680         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
681         
682         if (sName.IsEmpty())
683                 m_pAnnot->m_pAnnotDict->RemoveAt("NM");
684         else
685                 m_pAnnot->m_pAnnotDict->SetAtString("NM", PDF_EncodeText(sName));
686 }
687
688 CFX_WideString CPDFSDK_Annot::GetAnnotName() const
689 {
690         ASSERT(m_pAnnot != NULL);
691         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
692         
693         return m_pAnnot->m_pAnnotDict->GetUnicodeText("NM");
694 }
695
696 void CPDFSDK_Annot::SetModifiedDate(const FX_SYSTEMTIME& st)
697 {
698         ASSERT(m_pAnnot != NULL);
699         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
700         
701         CPDFSDK_DateTime dt(st);
702         CFX_ByteString str = dt.ToPDFDateTimeString();
703         
704         if (str.IsEmpty())
705                 m_pAnnot->m_pAnnotDict->RemoveAt("M");
706         else
707                 m_pAnnot->m_pAnnotDict->SetAtString("M", str);
708 }
709
710 FX_SYSTEMTIME CPDFSDK_Annot::GetModifiedDate() const
711 {
712         ASSERT(m_pAnnot != NULL);
713         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
714         
715         FX_SYSTEMTIME systime;  
716         CFX_ByteString str = m_pAnnot->m_pAnnotDict->GetString("M");
717         
718         CPDFSDK_DateTime dt(str);
719         dt.ToSystemTime(systime);
720         
721         return systime;
722 }
723
724 void CPDFSDK_Annot::SetFlags(int nFlags)
725 {
726         ASSERT(m_pAnnot != NULL);
727         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
728         
729         m_pAnnot->m_pAnnotDict->SetAtInteger("F", nFlags);
730 }
731
732 int CPDFSDK_Annot::GetFlags() const
733 {
734         ASSERT(m_pAnnot != NULL);
735         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
736         
737         return m_pAnnot->m_pAnnotDict->GetInteger("F");
738 }
739
740 void CPDFSDK_Annot::SetAppState(const CFX_ByteString& str)
741 {
742         ASSERT(m_pAnnot != NULL);
743         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
744
745         if (str.IsEmpty())
746                 m_pAnnot->m_pAnnotDict->RemoveAt("AS");
747         else
748                 m_pAnnot->m_pAnnotDict->SetAtString("AS", str);
749 }
750
751 CFX_ByteString CPDFSDK_Annot::GetAppState() const
752 {
753         ASSERT(m_pAnnot != NULL);
754         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
755
756         return m_pAnnot->m_pAnnotDict->GetString("AS");
757 }
758
759 void CPDFSDK_Annot::SetStructParent(int key)
760 {
761         ASSERT(m_pAnnot != NULL);
762         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
763         
764         m_pAnnot->m_pAnnotDict->SetAtInteger("StructParent", key);
765 }
766
767 int     CPDFSDK_Annot::GetStructParent() const
768 {
769         ASSERT(m_pAnnot != NULL);
770         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
771         
772         return m_pAnnot->m_pAnnotDict->GetInteger("StructParent");
773 }
774
775 //border
776 void CPDFSDK_Annot::SetBorderWidth(int nWidth)
777 {
778         ASSERT(m_pAnnot != NULL);
779         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
780
781         CPDF_Array* pBorder = m_pAnnot->m_pAnnotDict->GetArray("Border");
782
783         if (pBorder)
784         {
785                 pBorder->SetAt(2, FX_NEW CPDF_Number(nWidth));
786         }
787         else
788         {
789                 CPDF_Dictionary* pBSDict = m_pAnnot->m_pAnnotDict->GetDict("BS");
790
791                 if (!pBSDict)
792                 {
793                         pBSDict = FX_NEW CPDF_Dictionary;
794                         m_pAnnot->m_pAnnotDict->SetAt("BS", pBSDict);
795                 }
796
797                 pBSDict->SetAtInteger("W", nWidth);
798         }
799 }
800
801 int     CPDFSDK_Annot::GetBorderWidth() const
802 {
803         ASSERT(m_pAnnot != NULL);
804         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
805
806         CPDF_Array* pBorder = m_pAnnot->m_pAnnotDict->GetArray("Border");
807
808         if (pBorder)
809         {
810                 return pBorder->GetInteger(2);
811         }
812         else
813         {
814                 CPDF_Dictionary* pBSDict = m_pAnnot->m_pAnnotDict->GetDict("BS");
815
816                 if (pBSDict)
817                 {
818                         return pBSDict->GetInteger("W", 1);
819                 }
820         }
821         return 1;
822 }
823
824 void CPDFSDK_Annot::SetBorderStyle(int nStyle)
825 {
826         ASSERT(m_pAnnot != NULL);
827         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
828
829         CPDF_Dictionary* pBSDict = m_pAnnot->m_pAnnotDict->GetDict("BS");
830         if (!pBSDict)
831         {
832                 pBSDict = FX_NEW CPDF_Dictionary;
833                 m_pAnnot->m_pAnnotDict->SetAt("BS", pBSDict);
834         }
835
836         switch (nStyle)
837         {
838         case BBS_SOLID:
839                 pBSDict->SetAtName("S", "S");
840                 break;
841         case BBS_DASH:
842                 pBSDict->SetAtName("S", "D");
843                 break;
844         case BBS_BEVELED:
845                 pBSDict->SetAtName("S", "B");
846                 break;
847         case BBS_INSET:
848                 pBSDict->SetAtName("S", "I");
849                 break;
850         case BBS_UNDERLINE:
851                 pBSDict->SetAtName("S", "U");
852                 break;
853         }
854 }
855
856 int     CPDFSDK_Annot::GetBorderStyle() const
857 {
858         ASSERT(m_pAnnot != NULL);
859         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
860
861         CPDF_Dictionary* pBSDict = m_pAnnot->m_pAnnotDict->GetDict("BS");
862         if (pBSDict)
863         {
864                 CFX_ByteString sBorderStyle = pBSDict->GetString("S", "S");
865                 if (sBorderStyle == "S") return BBS_SOLID;
866                 if (sBorderStyle == "D") return BBS_DASH;
867                 if (sBorderStyle == "B") return BBS_BEVELED;
868                 if (sBorderStyle == "I") return BBS_INSET;
869                 if (sBorderStyle == "U") return BBS_UNDERLINE;
870         }
871
872         CPDF_Array* pBorder = m_pAnnot->m_pAnnotDict->GetArray("Border");
873         if (pBorder)
874         {
875                 if (pBorder->GetCount() >= 4) 
876                 { 
877                         CPDF_Array *pDP = pBorder->GetArray(3);
878                         if (pDP && pDP->GetCount() > 0)
879                                 return BBS_DASH;
880                 }
881         }
882
883         return BBS_SOLID;
884 }
885
886 void CPDFSDK_Annot::SetBorderDash(const CFX_IntArray& array)
887 {
888         ASSERT(m_pAnnot != NULL);
889         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
890
891         CPDF_Dictionary* pBSDict = m_pAnnot->m_pAnnotDict->GetDict("BS");
892         if (!pBSDict)
893         {
894                 pBSDict = FX_NEW CPDF_Dictionary;
895                 m_pAnnot->m_pAnnotDict->SetAt("BS", pBSDict);
896         }
897
898         CPDF_Array* pArray = FX_NEW CPDF_Array;
899         for (int i=0,sz=array.GetSize(); i<sz; i++)
900         {
901                 pArray->AddInteger(array[i]);
902         }
903
904         pBSDict->SetAt("D", pArray);
905 }
906
907 void CPDFSDK_Annot::GetBorderDash(CFX_IntArray& array) const
908 {
909         ASSERT(m_pAnnot != NULL);
910         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
911
912         CPDF_Array* pDash = NULL;
913
914         CPDF_Array* pBorder = m_pAnnot->m_pAnnotDict->GetArray("Border");
915         if (pBorder)
916         {
917                 pDash = pBorder->GetArray(3);
918         }
919         else
920         {
921                 CPDF_Dictionary* pBSDict = m_pAnnot->m_pAnnotDict->GetDict("BS");
922                 if (pBSDict)
923                 {
924                         pDash = pBSDict->GetArray("D");
925                 }
926         }
927
928         if (pDash)
929         {
930                 for (int i=0,sz=pDash->GetCount(); i<sz; i++)
931                 {
932                         array.Add(pDash->GetInteger(i));
933                 }
934         }
935 }
936
937 void CPDFSDK_Annot::SetColor(FX_COLORREF color)
938 {
939         ASSERT(m_pAnnot != NULL);
940         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
941
942         CPDF_Array* pArray = FX_NEW CPDF_Array;
943         pArray->AddNumber((FX_FLOAT)FXSYS_GetRValue(color) / 255.0f);
944         pArray->AddNumber((FX_FLOAT)FXSYS_GetGValue(color) / 255.0f);
945         pArray->AddNumber((FX_FLOAT)FXSYS_GetBValue(color) / 255.0f);
946         m_pAnnot->m_pAnnotDict->SetAt("C", pArray);
947 }
948
949 void CPDFSDK_Annot::RemoveColor()
950 {
951         ASSERT(m_pAnnot != NULL);
952         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
953
954         m_pAnnot->m_pAnnotDict->RemoveAt("C") ; 
955 }
956
957 FX_BOOL CPDFSDK_Annot::GetColor(FX_COLORREF& color) const
958 {
959         ASSERT(m_pAnnot != NULL);
960         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
961
962         if (CPDF_Array* pEntry = m_pAnnot->m_pAnnotDict->GetArray("C"))         
963         {
964                 int nCount = pEntry->GetCount();
965                 if (nCount == 1)
966                 {
967                         FX_FLOAT g = pEntry->GetNumber(0) * 255;
968
969                         color = FXSYS_RGB((int)g, (int)g, (int)g);
970
971                         return TRUE;
972                 }
973                 else if (nCount == 3)
974                 {
975                         FX_FLOAT r = pEntry->GetNumber(0) * 255;
976                         FX_FLOAT g = pEntry->GetNumber(1) * 255;
977                         FX_FLOAT b = pEntry->GetNumber(2) * 255;
978
979                         color = FXSYS_RGB((int)r, (int)g, (int)b);
980
981                         return TRUE;
982                 }
983                 else if (nCount == 4)
984                 {
985                         FX_FLOAT c = pEntry->GetNumber(0);
986                         FX_FLOAT m = pEntry->GetNumber(1);
987                         FX_FLOAT y = pEntry->GetNumber(2);
988                         FX_FLOAT k = pEntry->GetNumber(3);
989
990                         FX_FLOAT r = 1.0f - FX_MIN(1.0f, c + k);
991                         FX_FLOAT g = 1.0f - FX_MIN(1.0f, m + k);
992                         FX_FLOAT b = 1.0f - FX_MIN(1.0f, y + k);
993
994                         color = FXSYS_RGB((int)(r * 255), (int)(g * 255), (int)(b * 255));
995
996                         return TRUE;
997                 }
998         }
999
1000         return FALSE;
1001 }
1002
1003
1004 void CPDFSDK_Annot::WriteAppearance(const CFX_ByteString& sAPType, const CPDF_Rect& rcBBox, 
1005                                                                 const CPDF_Matrix& matrix, const CFX_ByteString& sContents,
1006                                                                 const CFX_ByteString& sAPState)
1007 {
1008         ASSERT(m_pAnnot != NULL);
1009         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
1010         
1011         CPDF_Dictionary* pAPDict = m_pAnnot->m_pAnnotDict->GetDict("AP");
1012         
1013         if (!pAPDict) 
1014         {
1015                 pAPDict = FX_NEW CPDF_Dictionary;
1016                 m_pAnnot->m_pAnnotDict->SetAt("AP", pAPDict);
1017         }
1018         
1019         CPDF_Stream* pStream = NULL;
1020         CPDF_Dictionary* pParentDict = NULL;
1021         
1022         if (sAPState.IsEmpty())
1023         {
1024                 pParentDict = pAPDict;
1025                 pStream = pAPDict->GetStream(sAPType);
1026         }
1027         else
1028         {
1029                 CPDF_Dictionary* pAPTypeDict = pAPDict->GetDict(sAPType);
1030                 if (!pAPTypeDict)
1031                 {
1032                         pAPTypeDict = FX_NEW CPDF_Dictionary;
1033                         pAPDict->SetAt(sAPType, pAPTypeDict);
1034                 }
1035                 
1036                 pParentDict = pAPTypeDict;
1037                 pStream = pAPTypeDict->GetStream(sAPState);
1038         }
1039         
1040         if (!pStream) 
1041         {
1042                 ASSERT(m_pPageView != NULL);
1043                 CPDF_Document* pDoc = m_pPageView->GetPDFDocument();
1044                 ASSERT(pDoc != NULL);
1045                 
1046                 pStream = FX_NEW CPDF_Stream(NULL, 0, NULL);
1047                 FX_INT32 objnum = pDoc->AddIndirectObject(pStream);
1048                 //pAPDict->SetAtReference(sAPType, pDoc, objnum);
1049                 ASSERT(pParentDict != NULL);
1050                 pParentDict->SetAtReference(sAPType, pDoc, objnum);
1051         }
1052         
1053         CPDF_Dictionary * pStreamDict = pStream->GetDict();
1054         
1055         if (!pStreamDict)
1056         {
1057                 pStreamDict = FX_NEW CPDF_Dictionary;
1058                 pStreamDict->SetAtName("Type", "XObject");
1059                 pStreamDict->SetAtName("Subtype", "Form");
1060                 pStreamDict->SetAtInteger("FormType", 1);
1061                 pStream->InitStream(NULL,0,pStreamDict);
1062         }
1063         
1064         if (pStreamDict)
1065         {
1066                 pStreamDict->SetAtMatrix("Matrix",matrix);      
1067                 pStreamDict->SetAtRect("BBox", rcBBox);         
1068         }
1069         
1070         pStream->SetData((FX_BYTE*)(FX_LPCSTR)sContents, sContents.GetLength(), FALSE, FALSE);
1071 }
1072
1073 #define BA_ANNOT_MINWIDTH                       1
1074 #define BA_ANNOT_MINHEIGHT                      1
1075
1076 FX_FLOAT CPDFSDK_Annot::GetMinWidth() const
1077 {
1078         return BA_ANNOT_MINWIDTH;
1079 }
1080
1081 FX_FLOAT CPDFSDK_Annot::GetMinHeight() const
1082 {
1083         return BA_ANNOT_MINHEIGHT;
1084 }
1085
1086 FX_BOOL CPDFSDK_Annot::CreateFormFiller()
1087 {
1088         return TRUE;
1089 }
1090 FX_BOOL CPDFSDK_Annot::IsVisible() const
1091 {
1092         int nFlags = GetFlags();
1093         return !((nFlags & ANNOTFLAG_INVISIBLE) || (nFlags & ANNOTFLAG_HIDDEN) || (nFlags & ANNOTFLAG_NOVIEW));
1094 }
1095
1096 CPDF_Action CPDFSDK_Annot::GetAction() const
1097 {
1098         ASSERT(m_pAnnot != NULL);
1099         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
1100         
1101         return m_pAnnot->m_pAnnotDict->GetDict("A");
1102 }
1103
1104 void CPDFSDK_Annot::SetAction(const CPDF_Action& action)
1105 {
1106         ASSERT(m_pAnnot != NULL);
1107         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
1108         
1109         ASSERT(action != NULL);
1110         
1111         if ((CPDF_Action&)action != m_pAnnot->m_pAnnotDict->GetDict("A"))
1112         {
1113                 CPDF_Document* pDoc = m_pPageView->GetPDFDocument();
1114                 ASSERT(pDoc != NULL);
1115                 
1116                 if (action.m_pDict && (action.m_pDict->GetObjNum() == 0))
1117                         pDoc->AddIndirectObject(action.m_pDict); 
1118                 m_pAnnot->m_pAnnotDict->SetAtReference("A", pDoc, action.m_pDict->GetObjNum());
1119         }
1120 }
1121
1122 void CPDFSDK_Annot::RemoveAction()
1123 {
1124         ASSERT(m_pAnnot != NULL);
1125         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
1126         
1127         m_pAnnot->m_pAnnotDict->RemoveAt("A");
1128 }
1129
1130 CPDF_AAction CPDFSDK_Annot::GetAAction() const
1131 {
1132         ASSERT(m_pAnnot != NULL);
1133         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
1134         
1135         return m_pAnnot->m_pAnnotDict->GetDict("AA");
1136 }
1137
1138 void CPDFSDK_Annot::SetAAction(const CPDF_AAction& aa)
1139 {
1140         ASSERT(m_pAnnot != NULL);
1141         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
1142         ASSERT(aa != NULL);
1143         
1144         if ((CPDF_AAction&)aa != m_pAnnot->m_pAnnotDict->GetDict("AA"))
1145                 m_pAnnot->m_pAnnotDict->SetAt("AA", (CPDF_AAction&)aa);
1146 }
1147
1148 void CPDFSDK_Annot::RemoveAAction()
1149 {
1150         ASSERT(m_pAnnot != NULL);
1151         ASSERT(m_pAnnot->m_pAnnotDict != NULL);
1152         
1153         m_pAnnot->m_pAnnotDict->RemoveAt("AA");
1154 }
1155
1156 CPDF_Action     CPDFSDK_Annot::GetAAction(CPDF_AAction::AActionType eAAT)
1157 {
1158         CPDF_AAction AAction = GetAAction();
1159         
1160         if (AAction.ActionExist(eAAT))
1161         {
1162                 return AAction.GetAction(eAAT);
1163         }
1164         else if (eAAT == CPDF_AAction::ButtonUp)
1165         {
1166                 return GetAction();
1167         }
1168         
1169         return NULL;
1170 }
1171
1172 void  CPDFSDK_Annot::Annot_OnDraw(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device, CPDF_RenderOptions* pOptions)
1173 {
1174         
1175         m_pAnnot->GetAPForm(m_pPageView->GetPDFPage(), CPDF_Annot::Normal);
1176         m_pAnnot->DrawAppearance(m_pPageView->GetPDFPage(), pDevice, pUser2Device, CPDF_Annot::Normal, NULL);
1177
1178         return ;
1179 }
1180
1181 CPDF_Page* CPDFSDK_Annot::GetPDFPage()
1182 {
1183         if(m_pPageView)
1184                 return m_pPageView->GetPDFPage();
1185         return NULL;
1186 }
1187