// Copyright 2014 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com #include "../include/fsdk_define.h" #include "../include/fsdk_mgr.h" #include "../include/fsdk_baseannot.h" //--------------------------------------------------------------------------- // CPDFSDK_DateTime //--------------------------------------------------------------------------- int _gAfxGetTimeZoneInSeconds(FX_CHAR tzhour, FX_BYTE tzminute) { return (int)tzhour * 3600 + (int)tzminute * (tzhour >= 0 ? 60 : -60); } FX_BOOL _gAfxIsLeapYear(FX_SHORT year) { return ((year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0))); } FX_WORD _gAfxGetYearDays(FX_SHORT year) { return (_gAfxIsLeapYear(year) == TRUE ? 366 : 365); } FX_BYTE _gAfxGetMonthDays(FX_SHORT year, FX_BYTE month) { FX_BYTE mDays; switch (month) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: mDays = 31; break; case 4: case 6: case 9: case 11: mDays = 30; break; case 2: if (_gAfxIsLeapYear(year) == TRUE) mDays = 29; else mDays = 28; break; default: mDays = 0; break; } return mDays; } CPDFSDK_DateTime::CPDFSDK_DateTime() { ResetDateTime(); } CPDFSDK_DateTime::CPDFSDK_DateTime(const CFX_ByteString& dtStr) { ResetDateTime(); FromPDFDateTimeString(dtStr); } CPDFSDK_DateTime::CPDFSDK_DateTime(const CPDFSDK_DateTime& datetime) { operator = (datetime); } CPDFSDK_DateTime::CPDFSDK_DateTime(const FX_SYSTEMTIME& st) { operator = (st) ; } void CPDFSDK_DateTime::ResetDateTime() { tzset(); time_t curTime; time(&curTime); struct tm* newtime; //newtime = gmtime(&curTime); newtime = localtime(&curTime); dt.year = newtime->tm_year + 1900; dt.month = newtime->tm_mon + 1; dt.day = newtime->tm_mday; dt.hour = newtime->tm_hour; dt.minute = newtime->tm_min; dt.second = newtime->tm_sec; // dt.tzHour = _timezone / 3600 * -1; // dt.tzMinute = (abs(_timezone) % 3600) / 60; } CPDFSDK_DateTime& CPDFSDK_DateTime::operator = (const CPDFSDK_DateTime& datetime) { FXSYS_memcpy(&dt, &datetime.dt, sizeof(FX_DATETIME)); return *this; } CPDFSDK_DateTime& CPDFSDK_DateTime::operator = (const FX_SYSTEMTIME& st) { tzset(); dt.year = (FX_SHORT)st.wYear; dt.month = (FX_BYTE)st.wMonth; dt.day = (FX_BYTE)st.wDay; dt.hour = (FX_BYTE)st.wHour; dt.minute = (FX_BYTE)st.wMinute; dt.second = (FX_BYTE)st.wSecond; // dt.tzHour = _timezone / 3600 * -1; // dt.tzMinute = (abs(_timezone) % 3600) / 60; return *this; } FX_BOOL CPDFSDK_DateTime::operator == (CPDFSDK_DateTime& datetime) { return (FXSYS_memcmp(&dt, &datetime.dt, sizeof(FX_DATETIME)) == 0); } FX_BOOL CPDFSDK_DateTime::operator != (CPDFSDK_DateTime& datetime) { return (FXSYS_memcmp(&dt, &datetime.dt, sizeof(FX_DATETIME)) != 0); } FX_BOOL CPDFSDK_DateTime::operator > (CPDFSDK_DateTime& datetime) { CPDFSDK_DateTime dt1 = ToGMT(); CPDFSDK_DateTime dt2 = datetime.ToGMT(); int d1 = (((int)dt1.dt.year) << 16) | (((int)dt1.dt.month) << 8) | (int)dt1.dt.day; int d2 = (((int)dt1.dt.hour) << 16) | (((int)dt1.dt.minute) << 8) | (int)dt1.dt.second; int d3 = (((int)dt2.dt.year) << 16) | (((int)dt2.dt.month) << 8) | (int)dt2.dt.day; int d4 = (((int)dt2.dt.hour) << 16) | (((int)dt2.dt.minute) << 8) | (int)dt2.dt.second; if (d1 > d3) return TRUE; if (d2 > d4) return TRUE; return FALSE; } FX_BOOL CPDFSDK_DateTime::operator >= (CPDFSDK_DateTime& datetime) { CPDFSDK_DateTime dt1 = ToGMT(); CPDFSDK_DateTime dt2 = datetime.ToGMT(); int d1 = (((int)dt1.dt.year) << 16) | (((int)dt1.dt.month) << 8) | (int)dt1.dt.day; int d2 = (((int)dt1.dt.hour) << 16) | (((int)dt1.dt.minute) << 8) | (int)dt1.dt.second; int d3 = (((int)dt2.dt.year) << 16) | (((int)dt2.dt.month) << 8) | (int)dt2.dt.day; int d4 = (((int)dt2.dt.hour) << 16) | (((int)dt2.dt.minute) << 8) | (int)dt2.dt.second; if (d1 >= d3) return TRUE; if (d2 >= d4) return TRUE; return FALSE; } FX_BOOL CPDFSDK_DateTime::operator < (CPDFSDK_DateTime& datetime) { CPDFSDK_DateTime dt1 = ToGMT(); CPDFSDK_DateTime dt2 = datetime.ToGMT(); int d1 = (((int)dt1.dt.year) << 16) | (((int)dt1.dt.month) << 8) | (int)dt1.dt.day; int d2 = (((int)dt1.dt.hour) << 16) | (((int)dt1.dt.minute) << 8) | (int)dt1.dt.second; int d3 = (((int)dt2.dt.year) << 16) | (((int)dt2.dt.month) << 8) | (int)dt2.dt.day; int d4 = (((int)dt2.dt.hour) << 16) | (((int)dt2.dt.minute) << 8) | (int)dt2.dt.second; if (d1 < d3) return TRUE; if (d2 < d4) return TRUE; return FALSE; } FX_BOOL CPDFSDK_DateTime::operator <= (CPDFSDK_DateTime& datetime) { CPDFSDK_DateTime dt1 = ToGMT(); CPDFSDK_DateTime dt2 = datetime.ToGMT(); int d1 = (((int)dt1.dt.year) << 16) | (((int)dt1.dt.month) << 8) | (int)dt1.dt.day; int d2 = (((int)dt1.dt.hour) << 16) | (((int)dt1.dt.minute) << 8) | (int)dt1.dt.second; int d3 = (((int)dt2.dt.year) << 16) | (((int)dt2.dt.month) << 8) | (int)dt2.dt.day; int d4 = (((int)dt2.dt.hour) << 16) | (((int)dt2.dt.minute) << 8) | (int)dt2.dt.second; if (d1 <= d3) return TRUE; if (d2 <= d4) return TRUE; return FALSE; } CPDFSDK_DateTime::operator time_t() { struct tm newtime; newtime.tm_year = dt.year - 1900; newtime.tm_mon = dt.month - 1; newtime.tm_mday = dt.day; newtime.tm_hour = dt.hour; newtime.tm_min = dt.minute; newtime.tm_sec = dt.second; return mktime(&newtime); } CPDFSDK_DateTime& CPDFSDK_DateTime::FromPDFDateTimeString(const CFX_ByteString& dtStr) { int strLength = dtStr.GetLength(); if (strLength > 0) { int i = 0; int j, k; FX_CHAR ch; while (i < strLength) { ch = dtStr[i]; if (ch >= '0' && ch <= '9') break; i ++; } if (i >= strLength) return *this; j = 0; k = 0; while (i < strLength && j < 4) { ch = dtStr[i]; k = k * 10 + ch - '0'; j ++; if (ch < '0' || ch > '9') break; i ++; } dt.year = (FX_SHORT)k; if (i >= strLength || j < 4) return *this; j = 0; k = 0; while (i < strLength && j < 2) { ch = dtStr[i]; k = k * 10 + ch - '0'; j ++; if (ch < '0' || ch > '9') break; i ++; } dt.month = (FX_BYTE)k; if (i >= strLength || j < 2) return *this; j = 0; k = 0; while (i < strLength && j < 2) { ch = dtStr[i]; k = k * 10 + ch - '0'; j ++; if (ch < '0' || ch > '9') break; i ++; } dt.day = (FX_BYTE)k; if (i >= strLength || j < 2) return *this; j = 0; k = 0; while (i < strLength && j < 2) { ch = dtStr[i]; k = k * 10 + ch - '0'; j ++; if (ch < '0' || ch > '9') break; i ++; } dt.hour = (FX_BYTE)k; if (i >= strLength || j < 2) return *this; j = 0; k = 0; while (i < strLength && j < 2) { ch = dtStr[i]; k = k * 10 + ch - '0'; j ++; if (ch < '0' || ch > '9') break; i ++; } dt.minute = (FX_BYTE)k; if (i >= strLength || j < 2) return *this; j = 0; k = 0; while (i < strLength && j < 2) { ch = dtStr[i]; k = k * 10 + ch - '0'; j ++; if (ch < '0' || ch > '9') break; i ++; } dt.second = (FX_BYTE)k; if (i >= strLength || j < 2) return *this; ch = dtStr[i ++]; if (ch != '-' && ch != '+') return *this; if (ch == '-') dt.tzHour = -1; else dt.tzHour = 1; j = 0; k = 0; while (i < strLength && j < 2) { ch = dtStr[i]; k = k * 10 + ch - '0'; j ++; if (ch < '0' || ch > '9') break; i ++; } dt.tzHour *= (FX_CHAR)k; if (i >= strLength || j < 2) return *this; ch = dtStr[i ++]; if (ch != '\'') return *this; j = 0; k = 0; while (i < strLength && j < 2) { ch = dtStr[i]; k = k * 10 + ch - '0'; j ++; if (ch < '0' || ch > '9') break; i ++; } dt.tzMinute = (FX_BYTE)k; if (i >= strLength || j < 2) return *this; } return *this; } CFX_ByteString CPDFSDK_DateTime::ToCommonDateTimeString() { CFX_ByteString str1; str1.Format("%04d-%02d-%02d %02d:%02d:%02d ", dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second); if (dt.tzHour < 0) str1 += "-"; else str1 += "+"; CFX_ByteString str2; str2.Format("%02d:%02d", abs(dt.tzHour), dt.tzMinute); return str1 + str2; } CFX_ByteString CPDFSDK_DateTime::ToPDFDateTimeString() { CFX_ByteString dtStr; char tempStr[32]; sprintf(tempStr, "D:%04d%02d%02d%02d%02d%02d", dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second); dtStr = CFX_ByteString(tempStr); if (dt.tzHour < 0) dtStr += CFX_ByteString("-"); else dtStr += CFX_ByteString("+"); sprintf(tempStr, "%02d'%02d'", abs(dt.tzHour), dt.tzMinute); dtStr += CFX_ByteString(tempStr); return dtStr; } void CPDFSDK_DateTime::ToSystemTime(FX_SYSTEMTIME& st) { CPDFSDK_DateTime dt = *this; time_t t = (time_t)dt; struct tm* pTime = localtime(&t); if(pTime){ st.wYear = (FX_WORD)pTime->tm_year + 1900; st.wMonth = (FX_WORD)pTime->tm_mon + 1; st.wDay = (FX_WORD)pTime->tm_mday; st.wDayOfWeek = (FX_WORD)pTime->tm_wday; st.wHour = (FX_WORD)pTime->tm_hour; st.wMinute = (FX_WORD)pTime->tm_min; st.wSecond = (FX_WORD)pTime->tm_sec; st.wMilliseconds = 0; } } CPDFSDK_DateTime CPDFSDK_DateTime::ToGMT() { CPDFSDK_DateTime dt = *this; dt.AddSeconds(-_gAfxGetTimeZoneInSeconds(dt.dt.tzHour, dt.dt.tzMinute)); dt.dt.tzHour = 0; dt.dt.tzMinute = 0; return dt; } CPDFSDK_DateTime& CPDFSDK_DateTime::AddDays(short days) { if (days == 0) return *this; FX_SHORT y = dt.year, yy; FX_BYTE m = dt.month; FX_BYTE d = dt.day; int mdays, ydays, ldays; ldays = days; if (ldays > 0) { yy = y; if (((FX_WORD)m * 100 + d) > 300) yy ++; ydays = _gAfxGetYearDays(yy); while (ldays >= ydays) { y ++; ldays -= ydays; yy ++; mdays = _gAfxGetMonthDays(y, m); if (d > mdays) { m ++; d -= mdays; } ydays = _gAfxGetYearDays(yy); } mdays = _gAfxGetMonthDays(y, m) - d + 1; while (ldays >= mdays) { ldays -= mdays; m ++; d = 1; mdays = _gAfxGetMonthDays(y, m); } d += ldays; } else { ldays *= -1; yy = y; if (((FX_WORD)m * 100 + d) < 300) yy --; ydays = _gAfxGetYearDays(yy); while (ldays >= ydays) { y --; ldays -= ydays; yy --; mdays = _gAfxGetMonthDays(y, m); if (d > mdays) { m ++; d -= mdays; } ydays = _gAfxGetYearDays(yy); } while (ldays >= d) { ldays -= d; m --; mdays = _gAfxGetMonthDays(y, m); d = mdays; } d -= ldays; } dt.year = y; dt.month = m; dt.day = d; return *this; } CPDFSDK_DateTime& CPDFSDK_DateTime::AddSeconds(int seconds) { if (seconds == 0) return *this; int n; int days; n = dt.hour * 3600 + dt.minute * 60 + dt.second + seconds; if (n < 0) { days = (n - 86399) / 86400; n -= days * 86400; } else { days = n / 86400; n %= 86400; } dt.hour = (FX_BYTE)(n / 3600); dt.hour %= 24; n %= 3600; dt.minute = (FX_BYTE)(n / 60); dt.second = (FX_BYTE)(n % 60); if (days != 0) AddDays(days); return *this; } //--------------------------------------------------------------------------- // CPDFSDK_Annot //--------------------------------------------------------------------------- CPDFSDK_Annot::CPDFSDK_Annot(CPDF_Annot* pAnnot, CPDFSDK_PageView* pPageView) : m_pAnnot(pAnnot), m_pPageView(pPageView), m_bSelected(FALSE), m_nTabOrder(-1) { } CPDFSDK_Annot::~CPDFSDK_Annot() { m_pAnnot = NULL; m_pPageView = NULL; } CPDF_Annot* CPDFSDK_Annot::GetPDFAnnot() { return m_pAnnot; } FX_DWORD CPDFSDK_Annot::GetFlags() { ASSERT(m_pAnnot != NULL); return m_pAnnot->GetFlags(); } void CPDFSDK_Annot::SetPage(CPDFSDK_PageView* pPageView) { m_pPageView = pPageView; } CPDFSDK_PageView* CPDFSDK_Annot::GetPageView() { return m_pPageView; } FX_BOOL CPDFSDK_Annot::IsSelected() { return m_bSelected; } void CPDFSDK_Annot::SetSelected(FX_BOOL bSelected) { m_bSelected = bSelected; } // Tab Order int CPDFSDK_Annot::GetTabOrder() { return m_nTabOrder; } void CPDFSDK_Annot::SetTabOrder(int iTabOrder) { m_nTabOrder = iTabOrder; } CPDF_Dictionary* CPDFSDK_Annot::GetAnnotDict() const { ASSERT(m_pAnnot != NULL); return m_pAnnot->m_pAnnotDict; } void CPDFSDK_Annot::SetRect(const CPDF_Rect& rect) { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); ASSERT(rect.right - rect.left >= GetMinWidth()); ASSERT(rect.top - rect.bottom >= GetMinHeight()); m_pAnnot->m_pAnnotDict->SetAtRect("Rect", rect); } CPDF_Rect CPDFSDK_Annot::GetRect() const { ASSERT(m_pAnnot != NULL); CPDF_Rect rect; m_pAnnot->GetRect(rect); return rect; } CFX_ByteString CPDFSDK_Annot::GetType() const { ASSERT(m_pAnnot != NULL); return m_pAnnot->GetSubType(); } CFX_ByteString CPDFSDK_Annot::GetSubType() const { return ""; } void CPDFSDK_Annot::ResetAppearance() { ASSERT(FALSE); } void CPDFSDK_Annot::DrawAppearance(CFX_RenderDevice* pDevice, const CPDF_Matrix* pUser2Device, CPDF_Annot::AppearanceMode mode, const CPDF_RenderOptions* pOptions) { ASSERT(m_pPageView != NULL); ASSERT(m_pAnnot != NULL); m_pAnnot->DrawAppearance(m_pPageView->GetPDFPage(), pDevice, pUser2Device, mode, pOptions); } FX_BOOL CPDFSDK_Annot::IsAppearanceValid() { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); return m_pAnnot->m_pAnnotDict->GetDict("AP") != NULL; } FX_BOOL CPDFSDK_Annot::IsAppearanceValid(CPDF_Annot::AppearanceMode mode) { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); CPDF_Dictionary* pAP = m_pAnnot->m_pAnnotDict->GetDict("AP"); if (pAP == NULL) return FALSE; // Choose the right sub-ap const FX_CHAR* ap_entry = "N"; if (mode == CPDF_Annot::Down) ap_entry = "D"; else if (mode == CPDF_Annot::Rollover) ap_entry = "R"; if (!pAP->KeyExist(ap_entry)) ap_entry = "N"; // Get the AP stream or subdirectory CPDF_Object* psub = pAP->GetElementValue(ap_entry); if (psub == NULL) return FALSE; return TRUE; } void CPDFSDK_Annot::DrawBorder(CFX_RenderDevice* pDevice, const CPDF_Matrix* pUser2Device, const CPDF_RenderOptions* pOptions) { ASSERT(m_pAnnot != NULL); m_pAnnot->DrawBorder(pDevice, pUser2Device, pOptions); } void CPDFSDK_Annot::ClearCachedAP() { ASSERT(m_pAnnot != NULL); m_pAnnot->ClearCachedAP(); } void CPDFSDK_Annot::SetContents(const CFX_WideString& sContents) { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); if (sContents.IsEmpty()) m_pAnnot->m_pAnnotDict->RemoveAt("Contents"); else m_pAnnot->m_pAnnotDict->SetAtString("Contents", PDF_EncodeText(sContents)); } CFX_WideString CPDFSDK_Annot::GetContents() const { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); return m_pAnnot->m_pAnnotDict->GetUnicodeText("Contents"); } void CPDFSDK_Annot::SetAnnotName(const CFX_WideString& sName) { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); if (sName.IsEmpty()) m_pAnnot->m_pAnnotDict->RemoveAt("NM"); else m_pAnnot->m_pAnnotDict->SetAtString("NM", PDF_EncodeText(sName)); } CFX_WideString CPDFSDK_Annot::GetAnnotName() const { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); return m_pAnnot->m_pAnnotDict->GetUnicodeText("NM"); } void CPDFSDK_Annot::SetModifiedDate(const FX_SYSTEMTIME& st) { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); CPDFSDK_DateTime dt(st); CFX_ByteString str = dt.ToPDFDateTimeString(); if (str.IsEmpty()) m_pAnnot->m_pAnnotDict->RemoveAt("M"); else m_pAnnot->m_pAnnotDict->SetAtString("M", str); } FX_SYSTEMTIME CPDFSDK_Annot::GetModifiedDate() const { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); FX_SYSTEMTIME systime; CFX_ByteString str = m_pAnnot->m_pAnnotDict->GetString("M"); CPDFSDK_DateTime dt(str); dt.ToSystemTime(systime); return systime; } void CPDFSDK_Annot::SetFlags(int nFlags) { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); m_pAnnot->m_pAnnotDict->SetAtInteger("F", nFlags); } int CPDFSDK_Annot::GetFlags() const { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); return m_pAnnot->m_pAnnotDict->GetInteger("F"); } void CPDFSDK_Annot::SetAppState(const CFX_ByteString& str) { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); if (str.IsEmpty()) m_pAnnot->m_pAnnotDict->RemoveAt("AS"); else m_pAnnot->m_pAnnotDict->SetAtString("AS", str); } CFX_ByteString CPDFSDK_Annot::GetAppState() const { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); return m_pAnnot->m_pAnnotDict->GetString("AS"); } void CPDFSDK_Annot::SetStructParent(int key) { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); m_pAnnot->m_pAnnotDict->SetAtInteger("StructParent", key); } int CPDFSDK_Annot::GetStructParent() const { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); return m_pAnnot->m_pAnnotDict->GetInteger("StructParent"); } //border void CPDFSDK_Annot::SetBorderWidth(int nWidth) { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); CPDF_Array* pBorder = m_pAnnot->m_pAnnotDict->GetArray("Border"); if (pBorder) { pBorder->SetAt(2, FX_NEW CPDF_Number(nWidth)); } else { CPDF_Dictionary* pBSDict = m_pAnnot->m_pAnnotDict->GetDict("BS"); if (!pBSDict) { pBSDict = FX_NEW CPDF_Dictionary; m_pAnnot->m_pAnnotDict->SetAt("BS", pBSDict); } pBSDict->SetAtInteger("W", nWidth); } } int CPDFSDK_Annot::GetBorderWidth() const { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); CPDF_Array* pBorder = m_pAnnot->m_pAnnotDict->GetArray("Border"); if (pBorder) { return pBorder->GetInteger(2); } else { CPDF_Dictionary* pBSDict = m_pAnnot->m_pAnnotDict->GetDict("BS"); if (pBSDict) { return pBSDict->GetInteger("W", 1); } } return 1; } void CPDFSDK_Annot::SetBorderStyle(int nStyle) { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); CPDF_Dictionary* pBSDict = m_pAnnot->m_pAnnotDict->GetDict("BS"); if (!pBSDict) { pBSDict = FX_NEW CPDF_Dictionary; m_pAnnot->m_pAnnotDict->SetAt("BS", pBSDict); } switch (nStyle) { case BBS_SOLID: pBSDict->SetAtName("S", "S"); break; case BBS_DASH: pBSDict->SetAtName("S", "D"); break; case BBS_BEVELED: pBSDict->SetAtName("S", "B"); break; case BBS_INSET: pBSDict->SetAtName("S", "I"); break; case BBS_UNDERLINE: pBSDict->SetAtName("S", "U"); break; } } int CPDFSDK_Annot::GetBorderStyle() const { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); CPDF_Dictionary* pBSDict = m_pAnnot->m_pAnnotDict->GetDict("BS"); if (pBSDict) { CFX_ByteString sBorderStyle = pBSDict->GetString("S", "S"); if (sBorderStyle == "S") return BBS_SOLID; if (sBorderStyle == "D") return BBS_DASH; if (sBorderStyle == "B") return BBS_BEVELED; if (sBorderStyle == "I") return BBS_INSET; if (sBorderStyle == "U") return BBS_UNDERLINE; } CPDF_Array* pBorder = m_pAnnot->m_pAnnotDict->GetArray("Border"); if (pBorder) { if (pBorder->GetCount() >= 4) { CPDF_Array *pDP = pBorder->GetArray(3); if (pDP && pDP->GetCount() > 0) return BBS_DASH; } } return BBS_SOLID; } void CPDFSDK_Annot::SetBorderDash(const CFX_IntArray& array) { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); CPDF_Dictionary* pBSDict = m_pAnnot->m_pAnnotDict->GetDict("BS"); if (!pBSDict) { pBSDict = FX_NEW CPDF_Dictionary; m_pAnnot->m_pAnnotDict->SetAt("BS", pBSDict); } CPDF_Array* pArray = FX_NEW CPDF_Array; for (int i=0,sz=array.GetSize(); i<sz; i++) { pArray->AddInteger(array[i]); } pBSDict->SetAt("D", pArray); } void CPDFSDK_Annot::GetBorderDash(CFX_IntArray& array) const { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); CPDF_Array* pDash = NULL; CPDF_Array* pBorder = m_pAnnot->m_pAnnotDict->GetArray("Border"); if (pBorder) { pDash = pBorder->GetArray(3); } else { CPDF_Dictionary* pBSDict = m_pAnnot->m_pAnnotDict->GetDict("BS"); if (pBSDict) { pDash = pBSDict->GetArray("D"); } } if (pDash) { for (int i=0,sz=pDash->GetCount(); i<sz; i++) { array.Add(pDash->GetInteger(i)); } } } void CPDFSDK_Annot::SetColor(FX_COLORREF color) { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); CPDF_Array* pArray = FX_NEW CPDF_Array; pArray->AddNumber((FX_FLOAT)FXSYS_GetRValue(color) / 255.0f); pArray->AddNumber((FX_FLOAT)FXSYS_GetGValue(color) / 255.0f); pArray->AddNumber((FX_FLOAT)FXSYS_GetBValue(color) / 255.0f); m_pAnnot->m_pAnnotDict->SetAt("C", pArray); } void CPDFSDK_Annot::RemoveColor() { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); m_pAnnot->m_pAnnotDict->RemoveAt("C") ; } FX_BOOL CPDFSDK_Annot::GetColor(FX_COLORREF& color) const { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); if (CPDF_Array* pEntry = m_pAnnot->m_pAnnotDict->GetArray("C")) { int nCount = pEntry->GetCount(); if (nCount == 1) { FX_FLOAT g = pEntry->GetNumber(0) * 255; color = FXSYS_RGB((int)g, (int)g, (int)g); return TRUE; } else if (nCount == 3) { FX_FLOAT r = pEntry->GetNumber(0) * 255; FX_FLOAT g = pEntry->GetNumber(1) * 255; FX_FLOAT b = pEntry->GetNumber(2) * 255; color = FXSYS_RGB((int)r, (int)g, (int)b); return TRUE; } else if (nCount == 4) { FX_FLOAT c = pEntry->GetNumber(0); FX_FLOAT m = pEntry->GetNumber(1); FX_FLOAT y = pEntry->GetNumber(2); FX_FLOAT k = pEntry->GetNumber(3); FX_FLOAT r = 1.0f - FX_MIN(1.0f, c + k); FX_FLOAT g = 1.0f - FX_MIN(1.0f, m + k); FX_FLOAT b = 1.0f - FX_MIN(1.0f, y + k); color = FXSYS_RGB((int)(r * 255), (int)(g * 255), (int)(b * 255)); return TRUE; } } return FALSE; } void CPDFSDK_Annot::WriteAppearance(const CFX_ByteString& sAPType, const CPDF_Rect& rcBBox, const CPDF_Matrix& matrix, const CFX_ByteString& sContents, const CFX_ByteString& sAPState) { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); CPDF_Dictionary* pAPDict = m_pAnnot->m_pAnnotDict->GetDict("AP"); if (!pAPDict) { pAPDict = FX_NEW CPDF_Dictionary; m_pAnnot->m_pAnnotDict->SetAt("AP", pAPDict); } CPDF_Stream* pStream = NULL; CPDF_Dictionary* pParentDict = NULL; if (sAPState.IsEmpty()) { pParentDict = pAPDict; pStream = pAPDict->GetStream(sAPType); } else { CPDF_Dictionary* pAPTypeDict = pAPDict->GetDict(sAPType); if (!pAPTypeDict) { pAPTypeDict = FX_NEW CPDF_Dictionary; pAPDict->SetAt(sAPType, pAPTypeDict); } pParentDict = pAPTypeDict; pStream = pAPTypeDict->GetStream(sAPState); } if (!pStream) { ASSERT(m_pPageView != NULL); CPDF_Document* pDoc = m_pPageView->GetPDFDocument(); ASSERT(pDoc != NULL); pStream = FX_NEW CPDF_Stream(NULL, 0, NULL); FX_INT32 objnum = pDoc->AddIndirectObject(pStream); //pAPDict->SetAtReference(sAPType, pDoc, objnum); ASSERT(pParentDict != NULL); pParentDict->SetAtReference(sAPType, pDoc, objnum); } CPDF_Dictionary * pStreamDict = pStream->GetDict(); if (!pStreamDict) { pStreamDict = FX_NEW CPDF_Dictionary; pStreamDict->SetAtName("Type", "XObject"); pStreamDict->SetAtName("Subtype", "Form"); pStreamDict->SetAtInteger("FormType", 1); pStream->InitStream(NULL,0,pStreamDict); } if (pStreamDict) { pStreamDict->SetAtMatrix("Matrix",matrix); pStreamDict->SetAtRect("BBox", rcBBox); } pStream->SetData((FX_BYTE*)(FX_LPCSTR)sContents, sContents.GetLength(), FALSE, FALSE); } #define BA_ANNOT_MINWIDTH 1 #define BA_ANNOT_MINHEIGHT 1 FX_FLOAT CPDFSDK_Annot::GetMinWidth() const { return BA_ANNOT_MINWIDTH; } FX_FLOAT CPDFSDK_Annot::GetMinHeight() const { return BA_ANNOT_MINHEIGHT; } FX_BOOL CPDFSDK_Annot::CreateFormFiller() { return TRUE; } FX_BOOL CPDFSDK_Annot::IsVisible() const { int nFlags = GetFlags(); return !((nFlags & ANNOTFLAG_INVISIBLE) || (nFlags & ANNOTFLAG_HIDDEN) || (nFlags & ANNOTFLAG_NOVIEW)); } CPDF_Action CPDFSDK_Annot::GetAction() const { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); return m_pAnnot->m_pAnnotDict->GetDict("A"); } void CPDFSDK_Annot::SetAction(const CPDF_Action& action) { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); ASSERT(action != NULL); if ((CPDF_Action&)action != m_pAnnot->m_pAnnotDict->GetDict("A")) { CPDF_Document* pDoc = m_pPageView->GetPDFDocument(); ASSERT(pDoc != NULL); if (action.m_pDict && (action.m_pDict->GetObjNum() == 0)) pDoc->AddIndirectObject(action.m_pDict); m_pAnnot->m_pAnnotDict->SetAtReference("A", pDoc, action.m_pDict->GetObjNum()); } } void CPDFSDK_Annot::RemoveAction() { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); m_pAnnot->m_pAnnotDict->RemoveAt("A"); } CPDF_AAction CPDFSDK_Annot::GetAAction() const { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); return m_pAnnot->m_pAnnotDict->GetDict("AA"); } void CPDFSDK_Annot::SetAAction(const CPDF_AAction& aa) { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); ASSERT(aa != NULL); if ((CPDF_AAction&)aa != m_pAnnot->m_pAnnotDict->GetDict("AA")) m_pAnnot->m_pAnnotDict->SetAt("AA", (CPDF_AAction&)aa); } void CPDFSDK_Annot::RemoveAAction() { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); m_pAnnot->m_pAnnotDict->RemoveAt("AA"); } CPDF_Action CPDFSDK_Annot::GetAAction(CPDF_AAction::AActionType eAAT) { CPDF_AAction AAction = GetAAction(); if (AAction.ActionExist(eAAT)) { return AAction.GetAction(eAAT); } else if (eAAT == CPDF_AAction::ButtonUp) { return GetAction(); } return NULL; } void CPDFSDK_Annot::Annot_OnDraw(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device, CPDF_RenderOptions* pOptions) { m_pAnnot->GetAPForm(m_pPageView->GetPDFPage(), CPDF_Annot::Normal); m_pAnnot->DrawAppearance(m_pPageView->GetPDFPage(), pDevice, pUser2Device, CPDF_Annot::Normal, NULL); return ; } CPDF_Page* CPDFSDK_Annot::GetPDFPage() { if(m_pPageView) return m_pPageView->GetPDFPage(); return NULL; }