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