OLD | NEW |
1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
6 | 6 |
7 #include "../../../third_party/base/nonstd_unique_ptr.h" | 7 #include "../../../third_party/base/nonstd_unique_ptr.h" |
8 #include "../../include/fpdfdoc/fpdf_doc.h" | 8 #include "../../include/fpdfdoc/fpdf_doc.h" |
9 #include "../../include/fpdfapi/fpdf_pageobj.h" | 9 #include "../../include/fpdfapi/fpdf_pageobj.h" |
10 | 10 |
11 CPDF_AnnotList::CPDF_AnnotList(CPDF_Page* pPage) | 11 CPDF_AnnotList::CPDF_AnnotList(CPDF_Page* pPage) { |
12 { | 12 ASSERT(pPage != NULL); |
13 ASSERT(pPage != NULL); | 13 m_pPageDict = pPage->m_pFormDict; |
14 m_pPageDict = pPage->m_pFormDict; | 14 if (m_pPageDict == NULL) { |
15 if (m_pPageDict == NULL) { | 15 return; |
16 return; | 16 } |
17 } | 17 m_pDocument = pPage->m_pDocument; |
18 m_pDocument = pPage->m_pDocument; | 18 CPDF_Array* pAnnots = m_pPageDict->GetArray("Annots"); |
19 CPDF_Array* pAnnots = m_pPageDict->GetArray("Annots"); | 19 if (pAnnots == NULL) { |
20 if (pAnnots == NULL) { | 20 return; |
21 return; | 21 } |
22 } | 22 CPDF_Dictionary* pRoot = m_pDocument->GetRoot(); |
23 CPDF_Dictionary* pRoot = m_pDocument->GetRoot(); | 23 CPDF_Dictionary* pAcroForm = pRoot->GetDict("AcroForm"); |
24 CPDF_Dictionary* pAcroForm = pRoot->GetDict("AcroForm"); | 24 FX_BOOL bRegenerateAP = pAcroForm && pAcroForm->GetBoolean("NeedAppearances"); |
25 FX_BOOL bRegenerateAP = pAcroForm && pAcroForm->GetBoolean("NeedAppearances"
); | 25 for (FX_DWORD i = 0; i < pAnnots->GetCount(); ++i) { |
26 for (FX_DWORD i = 0; i < pAnnots->GetCount(); ++i) { | 26 CPDF_Dictionary* pDict = (CPDF_Dictionary*)pAnnots->GetElementValue(i); |
27 CPDF_Dictionary* pDict = (CPDF_Dictionary*)pAnnots->GetElementValue(i); | 27 if (pDict == NULL || pDict->GetType() != PDFOBJ_DICTIONARY) { |
28 if (pDict == NULL || pDict->GetType() != PDFOBJ_DICTIONARY) { | 28 continue; |
29 continue; | 29 } |
30 } | 30 FX_DWORD dwObjNum = pDict->GetObjNum(); |
31 FX_DWORD dwObjNum = pDict->GetObjNum(); | 31 if (dwObjNum == 0) { |
32 if (dwObjNum == 0) { | 32 dwObjNum = m_pDocument->AddIndirectObject(pDict); |
33 dwObjNum = m_pDocument->AddIndirectObject(pDict); | 33 CPDF_Reference* pAction = new CPDF_Reference(m_pDocument, dwObjNum); |
34 CPDF_Reference* pAction = new CPDF_Reference(m_pDocument, dwObjNum); | 34 pAnnots->InsertAt(i, pAction); |
35 pAnnots->InsertAt(i, pAction); | 35 pAnnots->RemoveAt(i + 1); |
36 pAnnots->RemoveAt(i + 1); | 36 pDict = pAnnots->GetDict(i); |
37 pDict = pAnnots->GetDict(i); | 37 } |
38 } | 38 CPDF_Annot* pAnnot = new CPDF_Annot(pDict, this); |
39 CPDF_Annot* pAnnot = new CPDF_Annot(pDict, this); | 39 m_AnnotList.Add(pAnnot); |
40 m_AnnotList.Add(pAnnot); | 40 if (bRegenerateAP && |
41 if (bRegenerateAP && pDict->GetConstString(FX_BSTRC("Subtype")) == FX_BS
TRC("Widget")) | 41 pDict->GetConstString(FX_BSTRC("Subtype")) == FX_BSTRC("Widget")) |
42 if (CPDF_InterForm::UpdatingAPEnabled()) { | 42 if (CPDF_InterForm::UpdatingAPEnabled()) { |
43 FPDF_GenerateAP(m_pDocument, pDict); | 43 FPDF_GenerateAP(m_pDocument, pDict); |
44 } | 44 } |
45 } | 45 } |
46 } | 46 } |
47 CPDF_AnnotList::~CPDF_AnnotList() | 47 CPDF_AnnotList::~CPDF_AnnotList() { |
48 { | 48 int i = 0; |
49 int i = 0; | 49 for (i = 0; i < m_AnnotList.GetSize(); ++i) { |
50 for (i = 0; i < m_AnnotList.GetSize(); ++i) { | 50 delete (CPDF_Annot*)m_AnnotList[i]; |
51 delete (CPDF_Annot*)m_AnnotList[i]; | 51 } |
52 } | 52 for (i = 0; i < m_Borders.GetSize(); ++i) { |
53 for (i = 0; i < m_Borders.GetSize(); ++i) { | 53 delete (CPDF_PageObjects*)m_Borders[i]; |
54 delete (CPDF_PageObjects*)m_Borders[i]; | 54 } |
55 } | 55 } |
56 } | 56 void CPDF_AnnotList::DisplayPass(const CPDF_Page* pPage, |
57 void CPDF_AnnotList::DisplayPass(const CPDF_Page* pPage, CFX_RenderDevice* pDevi
ce, | 57 CFX_RenderDevice* pDevice, |
58 CPDF_RenderContext* pContext, FX_BOOL bPrinting
, CFX_AffineMatrix* pMatrix, | 58 CPDF_RenderContext* pContext, |
59 FX_BOOL bWidgetPass, CPDF_RenderOptions* pOptio
ns, FX_RECT* clip_rect) | 59 FX_BOOL bPrinting, |
60 { | 60 CFX_AffineMatrix* pMatrix, |
61 for (int i = 0; i < m_AnnotList.GetSize(); ++i) { | 61 FX_BOOL bWidgetPass, |
62 CPDF_Annot* pAnnot = (CPDF_Annot*)m_AnnotList[i]; | 62 CPDF_RenderOptions* pOptions, |
63 FX_BOOL bWidget = pAnnot->GetSubType() == "Widget"; | 63 FX_RECT* clip_rect) { |
64 if ((bWidgetPass && !bWidget) || (!bWidgetPass && bWidget)) { | 64 for (int i = 0; i < m_AnnotList.GetSize(); ++i) { |
65 continue; | 65 CPDF_Annot* pAnnot = (CPDF_Annot*)m_AnnotList[i]; |
66 } | 66 FX_BOOL bWidget = pAnnot->GetSubType() == "Widget"; |
67 FX_DWORD annot_flags = pAnnot->GetFlags(); | 67 if ((bWidgetPass && !bWidget) || (!bWidgetPass && bWidget)) { |
68 if (annot_flags & ANNOTFLAG_HIDDEN) { | 68 continue; |
69 continue; | 69 } |
70 } | 70 FX_DWORD annot_flags = pAnnot->GetFlags(); |
71 if (bPrinting && (annot_flags & ANNOTFLAG_PRINT) == 0) { | 71 if (annot_flags & ANNOTFLAG_HIDDEN) { |
72 continue; | 72 continue; |
73 } | 73 } |
74 if (!bPrinting && (annot_flags & ANNOTFLAG_NOVIEW)) { | 74 if (bPrinting && (annot_flags & ANNOTFLAG_PRINT) == 0) { |
75 continue; | 75 continue; |
76 } | 76 } |
77 if (pOptions != NULL) { | 77 if (!bPrinting && (annot_flags & ANNOTFLAG_NOVIEW)) { |
78 IPDF_OCContext* pOCContext = pOptions->m_pOCContext; | 78 continue; |
79 CPDF_Dictionary* pAnnotDict = pAnnot->GetAnnotDict(); | 79 } |
80 if (pOCContext != NULL && pAnnotDict != NULL && | 80 if (pOptions != NULL) { |
81 !pOCContext->CheckOCGVisible(pAnnotDict->GetDict(FX_BSTRC("O
C")))) { | 81 IPDF_OCContext* pOCContext = pOptions->m_pOCContext; |
82 continue; | 82 CPDF_Dictionary* pAnnotDict = pAnnot->GetAnnotDict(); |
83 } | 83 if (pOCContext != NULL && pAnnotDict != NULL && |
84 } | 84 !pOCContext->CheckOCGVisible(pAnnotDict->GetDict(FX_BSTRC("OC")))) { |
85 CPDF_Rect annot_rect_f; | 85 continue; |
86 pAnnot->GetRect(annot_rect_f); | 86 } |
87 CFX_Matrix matrix; | 87 } |
88 matrix = *pMatrix; | 88 CPDF_Rect annot_rect_f; |
89 if (clip_rect) { | 89 pAnnot->GetRect(annot_rect_f); |
90 annot_rect_f.Transform(&matrix); | 90 CFX_Matrix matrix; |
91 FX_RECT annot_rect = annot_rect_f.GetOutterRect(); | 91 matrix = *pMatrix; |
92 annot_rect.Intersect(*clip_rect); | 92 if (clip_rect) { |
93 if (annot_rect.IsEmpty()) { | 93 annot_rect_f.Transform(&matrix); |
94 continue; | 94 FX_RECT annot_rect = annot_rect_f.GetOutterRect(); |
95 } | 95 annot_rect.Intersect(*clip_rect); |
96 } | 96 if (annot_rect.IsEmpty()) { |
97 if (pContext) { | 97 continue; |
98 pAnnot->DrawInContext(pPage, pContext, &matrix, CPDF_Annot::Normal); | 98 } |
99 } else if (!pAnnot->DrawAppearance(pPage, pDevice, &matrix, CPDF_Annot::
Normal, pOptions)) { | 99 } |
100 pAnnot->DrawBorder(pDevice, &matrix, pOptions); | 100 if (pContext) { |
101 } | 101 pAnnot->DrawInContext(pPage, pContext, &matrix, CPDF_Annot::Normal); |
102 } | 102 } else if (!pAnnot->DrawAppearance(pPage, pDevice, &matrix, |
103 } | 103 CPDF_Annot::Normal, pOptions)) { |
104 void CPDF_AnnotList::DisplayAnnots(const CPDF_Page* pPage, CFX_RenderDevice* pDe
vice, | 104 pAnnot->DrawBorder(pDevice, &matrix, pOptions); |
| 105 } |
| 106 } |
| 107 } |
| 108 void CPDF_AnnotList::DisplayAnnots(const CPDF_Page* pPage, |
| 109 CFX_RenderDevice* pDevice, |
105 CFX_AffineMatrix* pUser2Device, | 110 CFX_AffineMatrix* pUser2Device, |
106 FX_BOOL bShowWidget, CPDF_RenderOptions* pOpt
ions) | 111 FX_BOOL bShowWidget, |
107 { | 112 CPDF_RenderOptions* pOptions) { |
108 FX_RECT clip_rect; | 113 FX_RECT clip_rect; |
109 if (pDevice) { | 114 if (pDevice) { |
110 clip_rect = pDevice->GetClipBox(); | 115 clip_rect = pDevice->GetClipBox(); |
111 } | 116 } |
112 FX_BOOL bPrinting = pDevice->GetDeviceClass() == FXDC_PRINTER || (pOptions &
& (pOptions->m_Flags & RENDER_PRINTPREVIEW)); | 117 FX_BOOL bPrinting = pDevice->GetDeviceClass() == FXDC_PRINTER || |
113 DisplayAnnots(pPage, pDevice, NULL, bPrinting, pUser2Device, bShowWidget ? 3
: 1, pOptions, &clip_rect); | 118 (pOptions && (pOptions->m_Flags & RENDER_PRINTPREVIEW)); |
114 } | 119 DisplayAnnots(pPage, pDevice, NULL, bPrinting, pUser2Device, |
115 void CPDF_AnnotList::DisplayAnnots(const CPDF_Page* pPage, CFX_RenderDevice* pDe
vice, CPDF_RenderContext* pContext, | 120 bShowWidget ? 3 : 1, pOptions, &clip_rect); |
116 FX_BOOL bPrinting, CFX_AffineMatrix* pUser2De
vice, FX_DWORD dwAnnotFlags, | 121 } |
117 CPDF_RenderOptions* pOptions, FX_RECT* pClipR
ect) | 122 void CPDF_AnnotList::DisplayAnnots(const CPDF_Page* pPage, |
118 { | 123 CFX_RenderDevice* pDevice, |
119 if (dwAnnotFlags & 0x01) { | 124 CPDF_RenderContext* pContext, |
120 DisplayPass(pPage, pDevice, pContext, bPrinting, pUser2Device, FALSE, pO
ptions, pClipRect); | 125 FX_BOOL bPrinting, |
121 } | 126 CFX_AffineMatrix* pUser2Device, |
122 if (dwAnnotFlags & 0x02) { | 127 FX_DWORD dwAnnotFlags, |
123 DisplayPass(pPage, pDevice, pContext, bPrinting, pUser2Device, TRUE, pOp
tions, pClipRect); | 128 CPDF_RenderOptions* pOptions, |
124 } | 129 FX_RECT* pClipRect) { |
125 } | 130 if (dwAnnotFlags & 0x01) { |
126 int CPDF_AnnotList::GetIndex(CPDF_Annot* pAnnot) | 131 DisplayPass(pPage, pDevice, pContext, bPrinting, pUser2Device, FALSE, |
127 { | 132 pOptions, pClipRect); |
128 for (int i = 0; i < m_AnnotList.GetSize(); ++i) | 133 } |
129 if (m_AnnotList[i] == (void*)pAnnot) { | 134 if (dwAnnotFlags & 0x02) { |
130 return i; | 135 DisplayPass(pPage, pDevice, pContext, bPrinting, pUser2Device, TRUE, |
131 } | 136 pOptions, pClipRect); |
132 return -1; | 137 } |
| 138 } |
| 139 int CPDF_AnnotList::GetIndex(CPDF_Annot* pAnnot) { |
| 140 for (int i = 0; i < m_AnnotList.GetSize(); ++i) |
| 141 if (m_AnnotList[i] == (void*)pAnnot) { |
| 142 return i; |
| 143 } |
| 144 return -1; |
133 } | 145 } |
134 CPDF_Annot::CPDF_Annot(CPDF_Dictionary* pDict, CPDF_AnnotList* pList) | 146 CPDF_Annot::CPDF_Annot(CPDF_Dictionary* pDict, CPDF_AnnotList* pList) |
135 : m_pAnnotDict(pDict), | 147 : m_pAnnotDict(pDict), |
136 m_pList(pList), | 148 m_pList(pList), |
137 m_sSubtype(m_pAnnotDict->GetConstString(FX_BSTRC("Subtype"))) | 149 m_sSubtype(m_pAnnotDict->GetConstString(FX_BSTRC("Subtype"))) {} |
138 { | 150 CPDF_Annot::~CPDF_Annot() { |
139 } | 151 ClearCachedAP(); |
140 CPDF_Annot::~CPDF_Annot() | 152 } |
141 { | 153 void CPDF_Annot::ClearCachedAP() { |
142 ClearCachedAP(); | 154 FX_POSITION pos = m_APMap.GetStartPosition(); |
143 } | 155 while (pos) { |
144 void CPDF_Annot::ClearCachedAP() | 156 void* pForm; |
145 { | 157 void* pObjects; |
146 FX_POSITION pos = m_APMap.GetStartPosition(); | 158 m_APMap.GetNextAssoc(pos, pForm, pObjects); |
147 while (pos) { | 159 delete (CPDF_PageObjects*)pObjects; |
148 void* pForm; | 160 } |
149 void* pObjects; | 161 m_APMap.RemoveAll(); |
150 m_APMap.GetNextAssoc(pos, pForm, pObjects); | 162 } |
151 delete (CPDF_PageObjects*)pObjects; | 163 CFX_ByteString CPDF_Annot::GetSubType() const { |
152 } | 164 return m_sSubtype; |
153 m_APMap.RemoveAll(); | 165 } |
154 } | 166 |
155 CFX_ByteString CPDF_Annot::GetSubType() const | 167 void CPDF_Annot::GetRect(CPDF_Rect& rect) const { |
156 { | 168 if (m_pAnnotDict == NULL) { |
157 return m_sSubtype; | 169 return; |
158 } | 170 } |
159 | 171 rect = m_pAnnotDict->GetRect("Rect"); |
160 void CPDF_Annot::GetRect(CPDF_Rect& rect) const | 172 rect.Normalize(); |
161 { | 173 } |
162 if (m_pAnnotDict == NULL) { | 174 |
163 return; | 175 FX_DWORD CPDF_Annot::GetFlags() const { |
164 } | 176 return m_pAnnotDict->GetInteger("F"); |
165 rect = m_pAnnotDict->GetRect("Rect"); | 177 } |
166 rect.Normalize(); | 178 |
167 } | 179 CPDF_Dictionary* CPDF_Annot::GetAnnotDict() { |
168 | 180 return m_pAnnotDict; |
169 FX_DWORD CPDF_Annot::GetFlags() const | 181 } |
170 { | 182 |
171 return m_pAnnotDict->GetInteger("F"); | 183 CPDF_Stream* FPDFDOC_GetAnnotAP(CPDF_Dictionary* pAnnotDict, |
172 } | 184 CPDF_Annot::AppearanceMode mode) { |
173 | 185 CPDF_Dictionary* pAP = pAnnotDict->GetDict("AP"); |
174 CPDF_Dictionary* CPDF_Annot::GetAnnotDict() | 186 if (pAP == NULL) { |
175 { | 187 return NULL; |
176 return m_pAnnotDict; | 188 } |
177 } | 189 const FX_CHAR* ap_entry = "N"; |
178 | 190 if (mode == CPDF_Annot::Down) { |
179 CPDF_Stream* FPDFDOC_GetAnnotAP(CPDF_Dictionary* pAnnotDict, CPDF_Annot::Appeara
nceMode mode) | 191 ap_entry = "D"; |
180 { | 192 } else if (mode == CPDF_Annot::Rollover) { |
181 CPDF_Dictionary* pAP = pAnnotDict->GetDict("AP"); | 193 ap_entry = "R"; |
182 if (pAP == NULL) { | 194 } |
183 return NULL; | 195 if (!pAP->KeyExist(ap_entry)) { |
184 } | 196 ap_entry = "N"; |
185 const FX_CHAR* ap_entry = "N"; | 197 } |
186 if (mode == CPDF_Annot::Down) { | 198 CPDF_Object* psub = pAP->GetElementValue(ap_entry); |
187 ap_entry = "D"; | 199 if (psub == NULL) { |
188 } else if (mode == CPDF_Annot::Rollover) { | 200 return NULL; |
189 ap_entry = "R"; | 201 } |
190 } | 202 CPDF_Stream* pStream = NULL; |
191 if (!pAP->KeyExist(ap_entry)) { | 203 if (psub->GetType() == PDFOBJ_STREAM) { |
192 ap_entry = "N"; | 204 pStream = (CPDF_Stream*)psub; |
193 } | 205 } else if (psub->GetType() == PDFOBJ_DICTIONARY) { |
194 CPDF_Object* psub = pAP->GetElementValue(ap_entry); | 206 CFX_ByteString as = pAnnotDict->GetString("AS"); |
195 if (psub == NULL) { | 207 if (as.IsEmpty()) { |
196 return NULL; | 208 CFX_ByteString value = pAnnotDict->GetString(FX_BSTRC("V")); |
197 } | 209 if (value.IsEmpty()) { |
198 CPDF_Stream* pStream = NULL; | 210 CPDF_Dictionary* pDict = pAnnotDict->GetDict(FX_BSTRC("Parent")); |
199 if (psub->GetType() == PDFOBJ_STREAM) { | 211 value = pDict ? pDict->GetString(FX_BSTRC("V")) : CFX_ByteString(); |
200 pStream = (CPDF_Stream*)psub; | 212 } |
201 } else if (psub->GetType() == PDFOBJ_DICTIONARY) { | 213 if (value.IsEmpty() || !((CPDF_Dictionary*)psub)->KeyExist(value)) { |
202 CFX_ByteString as = pAnnotDict->GetString("AS"); | 214 as = FX_BSTRC("Off"); |
203 if (as.IsEmpty()) { | 215 } else { |
204 CFX_ByteString value = pAnnotDict->GetString(FX_BSTRC("V")); | 216 as = value; |
205 if (value.IsEmpty()) { | 217 } |
206 CPDF_Dictionary* pDict = pAnnotDict->GetDict(FX_BSTRC("Parent"))
; | 218 } |
207 value = pDict ? pDict->GetString(FX_BSTRC("V")) : CFX_ByteString
(); | 219 pStream = ((CPDF_Dictionary*)psub)->GetStream(as); |
208 } | 220 } |
209 if (value.IsEmpty() || !((CPDF_Dictionary*)psub)->KeyExist(value)) { | 221 return pStream; |
210 as = FX_BSTRC("Off"); | 222 } |
211 } else { | 223 CPDF_Form* CPDF_Annot::GetAPForm(const CPDF_Page* pPage, AppearanceMode mode) { |
212 as = value; | 224 CPDF_Stream* pStream = FPDFDOC_GetAnnotAP(m_pAnnotDict, mode); |
213 } | 225 if (pStream == NULL) { |
| 226 return NULL; |
| 227 } |
| 228 CPDF_Form* pForm; |
| 229 if (m_APMap.Lookup(pStream, (void*&)pForm)) { |
| 230 return pForm; |
| 231 } |
| 232 pForm = new CPDF_Form(m_pList->m_pDocument, pPage->m_pResources, pStream); |
| 233 pForm->ParseContent(NULL, NULL, NULL, NULL); |
| 234 m_APMap.SetAt(pStream, pForm); |
| 235 return pForm; |
| 236 } |
| 237 static CPDF_Form* FPDFDOC_Annot_GetMatrix(const CPDF_Page* pPage, |
| 238 CPDF_Annot* pAnnot, |
| 239 CPDF_Annot::AppearanceMode mode, |
| 240 const CFX_AffineMatrix* pUser2Device, |
| 241 CFX_Matrix& matrix) { |
| 242 CPDF_Form* pForm = pAnnot->GetAPForm(pPage, mode); |
| 243 if (!pForm) { |
| 244 return NULL; |
| 245 } |
| 246 CFX_FloatRect form_bbox = pForm->m_pFormDict->GetRect(FX_BSTRC("BBox")); |
| 247 CFX_Matrix form_matrix = pForm->m_pFormDict->GetMatrix(FX_BSTRC("Matrix")); |
| 248 form_matrix.TransformRect(form_bbox); |
| 249 CPDF_Rect arect; |
| 250 pAnnot->GetRect(arect); |
| 251 matrix.MatchRect(arect, form_bbox); |
| 252 matrix.Concat(*pUser2Device); |
| 253 return pForm; |
| 254 } |
| 255 FX_BOOL CPDF_Annot::DrawAppearance(const CPDF_Page* pPage, |
| 256 CFX_RenderDevice* pDevice, |
| 257 const CFX_AffineMatrix* pUser2Device, |
| 258 AppearanceMode mode, |
| 259 const CPDF_RenderOptions* pOptions) { |
| 260 CFX_Matrix matrix; |
| 261 CPDF_Form* pForm = |
| 262 FPDFDOC_Annot_GetMatrix(pPage, this, mode, pUser2Device, matrix); |
| 263 if (!pForm) { |
| 264 return FALSE; |
| 265 } |
| 266 CPDF_RenderContext context; |
| 267 context.Create((CPDF_Page*)pPage); |
| 268 context.DrawObjectList(pDevice, pForm, &matrix, pOptions); |
| 269 return TRUE; |
| 270 } |
| 271 FX_BOOL CPDF_Annot::DrawInContext(const CPDF_Page* pPage, |
| 272 const CPDF_RenderContext* pContext, |
| 273 const CFX_AffineMatrix* pUser2Device, |
| 274 AppearanceMode mode) { |
| 275 CFX_Matrix matrix; |
| 276 CPDF_Form* pForm = |
| 277 FPDFDOC_Annot_GetMatrix(pPage, this, mode, pUser2Device, matrix); |
| 278 if (!pForm) { |
| 279 return FALSE; |
| 280 } |
| 281 ((CPDF_RenderContext*)pContext)->AppendObjectList(pForm, &matrix); |
| 282 return TRUE; |
| 283 } |
| 284 void CPDF_Annot::DrawBorder(CFX_RenderDevice* pDevice, |
| 285 const CFX_AffineMatrix* pUser2Device, |
| 286 const CPDF_RenderOptions* pOptions) { |
| 287 if (GetSubType() == "Popup") { |
| 288 return; |
| 289 } |
| 290 FX_DWORD annot_flags = GetFlags(); |
| 291 if (annot_flags & ANNOTFLAG_HIDDEN) { |
| 292 return; |
| 293 } |
| 294 FX_BOOL bPrinting = pDevice->GetDeviceClass() == FXDC_PRINTER || |
| 295 (pOptions && (pOptions->m_Flags & RENDER_PRINTPREVIEW)); |
| 296 if (bPrinting && (annot_flags & ANNOTFLAG_PRINT) == 0) { |
| 297 return; |
| 298 } |
| 299 if (!bPrinting && (annot_flags & ANNOTFLAG_NOVIEW)) { |
| 300 return; |
| 301 } |
| 302 CPDF_Dictionary* pBS = m_pAnnotDict->GetDict("BS"); |
| 303 char style_char; |
| 304 FX_FLOAT width; |
| 305 CPDF_Array* pDashArray = NULL; |
| 306 if (pBS == NULL) { |
| 307 CPDF_Array* pBorderArray = m_pAnnotDict->GetArray("Border"); |
| 308 style_char = 'S'; |
| 309 if (pBorderArray) { |
| 310 width = pBorderArray->GetNumber(2); |
| 311 if (pBorderArray->GetCount() == 4) { |
| 312 pDashArray = pBorderArray->GetArray(3); |
| 313 if (pDashArray == NULL) { |
| 314 return; |
214 } | 315 } |
215 pStream = ((CPDF_Dictionary*)psub)->GetStream(as); | 316 int nLen = pDashArray->GetCount(); |
216 } | 317 int i = 0; |
217 return pStream; | 318 for (; i < nLen; ++i) { |
218 } | 319 CPDF_Object* pObj = pDashArray->GetElementValue(i); |
219 CPDF_Form* CPDF_Annot::GetAPForm(const CPDF_Page* pPage, AppearanceMode mode) | 320 if (pObj && pObj->GetInteger()) { |
220 { | 321 break; |
221 CPDF_Stream* pStream = FPDFDOC_GetAnnotAP(m_pAnnotDict, mode); | 322 } |
222 if (pStream == NULL) { | |
223 return NULL; | |
224 } | |
225 CPDF_Form* pForm; | |
226 if (m_APMap.Lookup(pStream, (void*&)pForm)) { | |
227 return pForm; | |
228 } | |
229 pForm = new CPDF_Form(m_pList->m_pDocument, pPage->m_pResources, pStream); | |
230 pForm->ParseContent(NULL, NULL, NULL, NULL); | |
231 m_APMap.SetAt(pStream, pForm); | |
232 return pForm; | |
233 } | |
234 static CPDF_Form* FPDFDOC_Annot_GetMatrix(const CPDF_Page* pPage, CPDF_Annot* pA
nnot, CPDF_Annot::AppearanceMode mode, const CFX_AffineMatrix* pUser2Device, CFX
_Matrix &matrix) | |
235 { | |
236 CPDF_Form* pForm = pAnnot->GetAPForm(pPage, mode); | |
237 if (!pForm) { | |
238 return NULL; | |
239 } | |
240 CFX_FloatRect form_bbox = pForm->m_pFormDict->GetRect(FX_BSTRC("BBox")); | |
241 CFX_Matrix form_matrix = pForm->m_pFormDict->GetMatrix(FX_BSTRC("Matrix")); | |
242 form_matrix.TransformRect(form_bbox); | |
243 CPDF_Rect arect; | |
244 pAnnot->GetRect(arect); | |
245 matrix.MatchRect(arect, form_bbox); | |
246 matrix.Concat(*pUser2Device); | |
247 return pForm; | |
248 } | |
249 FX_BOOL CPDF_Annot::DrawAppearance(const CPDF_Page* pPage, CFX_RenderDevice* pDe
vice, const CFX_AffineMatrix* pUser2Device, | |
250 AppearanceMode mode, const CPDF_RenderOptions
* pOptions) | |
251 { | |
252 CFX_Matrix matrix; | |
253 CPDF_Form* pForm = FPDFDOC_Annot_GetMatrix(pPage, this, mode, pUser2Device,
matrix); | |
254 if (!pForm) { | |
255 return FALSE; | |
256 } | |
257 CPDF_RenderContext context; | |
258 context.Create((CPDF_Page*)pPage); | |
259 context.DrawObjectList(pDevice, pForm, &matrix, pOptions); | |
260 return TRUE; | |
261 } | |
262 FX_BOOL CPDF_Annot::DrawInContext(const CPDF_Page* pPage, const CPDF_RenderConte
xt* pContext, const CFX_AffineMatrix* pUser2Device, AppearanceMode mode) | |
263 { | |
264 CFX_Matrix matrix; | |
265 CPDF_Form* pForm = FPDFDOC_Annot_GetMatrix(pPage, this, mode, pUser2Device,
matrix); | |
266 if (!pForm) { | |
267 return FALSE; | |
268 } | |
269 ((CPDF_RenderContext*)pContext)->AppendObjectList(pForm, &matrix); | |
270 return TRUE; | |
271 } | |
272 void CPDF_Annot::DrawBorder(CFX_RenderDevice* pDevice, const CFX_AffineMatrix* p
User2Device, const CPDF_RenderOptions* pOptions) | |
273 { | |
274 if (GetSubType() == "Popup") { | |
275 return; | |
276 } | |
277 FX_DWORD annot_flags = GetFlags(); | |
278 if (annot_flags & ANNOTFLAG_HIDDEN) { | |
279 return; | |
280 } | |
281 FX_BOOL bPrinting = pDevice->GetDeviceClass() == FXDC_PRINTER || (pOptions &
& (pOptions->m_Flags & RENDER_PRINTPREVIEW)); | |
282 if (bPrinting && (annot_flags & ANNOTFLAG_PRINT) == 0) { | |
283 return; | |
284 } | |
285 if (!bPrinting && (annot_flags & ANNOTFLAG_NOVIEW)) { | |
286 return; | |
287 } | |
288 CPDF_Dictionary* pBS = m_pAnnotDict->GetDict("BS"); | |
289 char style_char; | |
290 FX_FLOAT width; | |
291 CPDF_Array* pDashArray = NULL; | |
292 if (pBS == NULL) { | |
293 CPDF_Array* pBorderArray = m_pAnnotDict->GetArray("Border"); | |
294 style_char = 'S'; | |
295 if (pBorderArray) { | |
296 width = pBorderArray->GetNumber(2); | |
297 if (pBorderArray->GetCount() == 4) { | |
298 pDashArray = pBorderArray->GetArray(3); | |
299 if (pDashArray == NULL) { | |
300 return; | |
301 } | |
302 int nLen = pDashArray->GetCount(); | |
303 int i = 0; | |
304 for (; i < nLen; ++i) { | |
305 CPDF_Object*pObj = pDashArray->GetElementValue(i); | |
306 if (pObj && pObj->GetInteger()) { | |
307 break; | |
308 } | |
309 } | |
310 if (i == nLen) { | |
311 return; | |
312 } | |
313 style_char = 'D'; | |
314 } | |
315 } else { | |
316 width = 1; | |
317 } | 323 } |
| 324 if (i == nLen) { |
| 325 return; |
| 326 } |
| 327 style_char = 'D'; |
| 328 } |
318 } else { | 329 } else { |
319 CFX_ByteString style = pBS->GetString("S"); | 330 width = 1; |
320 pDashArray = pBS->GetArray("D"); | 331 } |
321 style_char = style[1]; | 332 } else { |
322 width = pBS->GetNumber("W"); | 333 CFX_ByteString style = pBS->GetString("S"); |
323 } | 334 pDashArray = pBS->GetArray("D"); |
324 if (width <= 0) { | 335 style_char = style[1]; |
325 return; | 336 width = pBS->GetNumber("W"); |
326 } | 337 } |
327 CPDF_Array* pColor = m_pAnnotDict->GetArray("C"); | 338 if (width <= 0) { |
328 FX_DWORD argb = 0xff000000; | 339 return; |
329 if (pColor != NULL) { | 340 } |
330 int R = (int32_t)(pColor->GetNumber(0) * 255); | 341 CPDF_Array* pColor = m_pAnnotDict->GetArray("C"); |
331 int G = (int32_t)(pColor->GetNumber(1) * 255); | 342 FX_DWORD argb = 0xff000000; |
332 int B = (int32_t)(pColor->GetNumber(2) * 255); | 343 if (pColor != NULL) { |
333 argb = ArgbEncode(0xff, R, G, B); | 344 int R = (int32_t)(pColor->GetNumber(0) * 255); |
334 } | 345 int G = (int32_t)(pColor->GetNumber(1) * 255); |
335 CPDF_GraphStateData graph_state; | 346 int B = (int32_t)(pColor->GetNumber(2) * 255); |
336 graph_state.m_LineWidth = width; | 347 argb = ArgbEncode(0xff, R, G, B); |
337 if (style_char == 'D') { | 348 } |
338 if (pDashArray) { | 349 CPDF_GraphStateData graph_state; |
339 FX_DWORD dash_count = pDashArray->GetCount(); | 350 graph_state.m_LineWidth = width; |
340 if (dash_count % 2) { | 351 if (style_char == 'D') { |
341 dash_count++; | 352 if (pDashArray) { |
342 } | 353 FX_DWORD dash_count = pDashArray->GetCount(); |
343 graph_state.m_DashArray = FX_Alloc(FX_FLOAT, dash_count); | 354 if (dash_count % 2) { |
344 graph_state.m_DashCount = dash_count; | 355 dash_count++; |
345 FX_DWORD i; | 356 } |
346 for (i = 0; i < pDashArray->GetCount(); ++i) { | 357 graph_state.m_DashArray = FX_Alloc(FX_FLOAT, dash_count); |
347 graph_state.m_DashArray[i] = pDashArray->GetNumber(i); | 358 graph_state.m_DashCount = dash_count; |
348 } | 359 FX_DWORD i; |
349 if (i < dash_count) { | 360 for (i = 0; i < pDashArray->GetCount(); ++i) { |
350 graph_state.m_DashArray[i] = graph_state.m_DashArray[i - 1]; | 361 graph_state.m_DashArray[i] = pDashArray->GetNumber(i); |
351 } | 362 } |
352 } else { | 363 if (i < dash_count) { |
353 graph_state.m_DashArray = FX_Alloc(FX_FLOAT, 2); | 364 graph_state.m_DashArray[i] = graph_state.m_DashArray[i - 1]; |
354 graph_state.m_DashCount = 2; | 365 } |
355 graph_state.m_DashArray[0] = graph_state.m_DashArray[1] = 3 * 1.0f; | 366 } else { |
356 } | 367 graph_state.m_DashArray = FX_Alloc(FX_FLOAT, 2); |
357 } | 368 graph_state.m_DashCount = 2; |
358 CFX_FloatRect rect; | 369 graph_state.m_DashArray[0] = graph_state.m_DashArray[1] = 3 * 1.0f; |
359 GetRect(rect); | 370 } |
360 CPDF_PathData path; | 371 } |
361 width /= 2; | 372 CFX_FloatRect rect; |
362 path.AppendRect(rect.left + width, rect.bottom + width, rect.right - width,
rect.top - width); | 373 GetRect(rect); |
363 int fill_type = 0; | 374 CPDF_PathData path; |
364 if (pOptions && (pOptions->m_Flags & RENDER_NOPATHSMOOTH)) { | 375 width /= 2; |
365 fill_type |= FXFILL_NOPATHSMOOTH; | 376 path.AppendRect(rect.left + width, rect.bottom + width, rect.right - width, |
366 } | 377 rect.top - width); |
367 pDevice->DrawPath(&path, pUser2Device, &graph_state, argb, argb, fill_type); | 378 int fill_type = 0; |
368 } | 379 if (pOptions && (pOptions->m_Flags & RENDER_NOPATHSMOOTH)) { |
| 380 fill_type |= FXFILL_NOPATHSMOOTH; |
| 381 } |
| 382 pDevice->DrawPath(&path, pUser2Device, &graph_state, argb, argb, fill_type); |
| 383 } |
OLD | NEW |