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 "core/include/fpdfdoc/fpdf_ap.h"
8 #include "core/include/fpdfdoc/fpdf_doc.h"
9 #include "core/include/fpdfdoc/fpdf_vt.h"
10 #include "doc_utils.h"
11 #include "pdf_vt.h"
12
FPDF_GenerateAP(CPDF_Document * pDoc,CPDF_Dictionary * pAnnotDict)13 FX_BOOL FPDF_GenerateAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) {
14 if (!pAnnotDict || pAnnotDict->GetConstString("Subtype") != "Widget") {
15 return FALSE;
16 }
17 CFX_ByteString field_type = FPDF_GetFieldAttr(pAnnotDict, "FT")->GetString();
18 FX_DWORD flags = FPDF_GetFieldAttr(pAnnotDict, "Ff")
19 ? FPDF_GetFieldAttr(pAnnotDict, "Ff")->GetInteger()
20 : 0;
21 if (field_type == "Tx") {
22 return CPVT_GenerateAP::GenerateTextFieldAP(pDoc, pAnnotDict);
23 }
24 if (field_type == "Ch") {
25 return (flags & (1 << 17))
26 ? CPVT_GenerateAP::GenerateComboBoxAP(pDoc, pAnnotDict)
27 : CPVT_GenerateAP::GenerateListBoxAP(pDoc, pAnnotDict);
28 }
29 if (field_type == "Btn") {
30 if (!(flags & (1 << 16))) {
31 if (!pAnnotDict->KeyExist("AS")) {
32 if (CPDF_Dictionary* pParentDict = pAnnotDict->GetDict("Parent")) {
33 if (pParentDict->KeyExist("AS")) {
34 pAnnotDict->SetAtString("AS", pParentDict->GetString("AS"));
35 }
36 }
37 }
38 }
39 }
40 return FALSE;
41 }
42
43 class CPVT_FontMap : public IPVT_FontMap {
44 public:
45 CPVT_FontMap(CPDF_Document* pDoc,
46 CPDF_Dictionary* pResDict,
47 CPDF_Font* pDefFont,
48 const CFX_ByteString& sDefFontAlias);
49 ~CPVT_FontMap() override;
50
51 // IPVT_FontMap
52 CPDF_Font* GetPDFFont(int32_t nFontIndex) override;
53 CFX_ByteString GetPDFFontAlias(int32_t nFontIndex) override;
54
55 static void GetAnnotSysPDFFont(CPDF_Document* pDoc,
56 CPDF_Dictionary* pResDict,
57 CPDF_Font*& pSysFont,
58 CFX_ByteString& sSysFontAlias);
59
60 private:
61 CPDF_Document* m_pDocument;
62 CPDF_Dictionary* m_pResDict;
63 CPDF_Font* m_pDefFont;
64 CFX_ByteString m_sDefFontAlias;
65 CPDF_Font* m_pSysFont;
66 CFX_ByteString m_sSysFontAlias;
67 };
68
CPVT_FontMap(CPDF_Document * pDoc,CPDF_Dictionary * pResDict,CPDF_Font * pDefFont,const CFX_ByteString & sDefFontAlias)69 CPVT_FontMap::CPVT_FontMap(CPDF_Document* pDoc,
70 CPDF_Dictionary* pResDict,
71 CPDF_Font* pDefFont,
72 const CFX_ByteString& sDefFontAlias)
73 : m_pDocument(pDoc),
74 m_pResDict(pResDict),
75 m_pDefFont(pDefFont),
76 m_sDefFontAlias(sDefFontAlias),
77 m_pSysFont(NULL),
78 m_sSysFontAlias() {}
~CPVT_FontMap()79 CPVT_FontMap::~CPVT_FontMap() {}
GetAnnotSysPDFFont(CPDF_Document * pDoc,CPDF_Dictionary * pResDict,CPDF_Font * & pSysFont,CFX_ByteString & sSysFontAlias)80 void CPVT_FontMap::GetAnnotSysPDFFont(CPDF_Document* pDoc,
81 CPDF_Dictionary* pResDict,
82 CPDF_Font*& pSysFont,
83 CFX_ByteString& sSysFontAlias) {
84 if (pDoc && pResDict) {
85 CFX_ByteString sFontAlias;
86 CPDF_Dictionary* pFormDict = pDoc->GetRoot()->GetDict("AcroForm");
87 if (CPDF_Font* pPDFFont =
88 AddNativeInterFormFont(pFormDict, pDoc, sSysFontAlias)) {
89 if (CPDF_Dictionary* pFontList = pResDict->GetDict("Font")) {
90 if (!pFontList->KeyExist(sSysFontAlias)) {
91 pFontList->SetAtReference(sSysFontAlias, pDoc,
92 pPDFFont->GetFontDict());
93 }
94 }
95 pSysFont = pPDFFont;
96 }
97 }
98 }
GetPDFFont(int32_t nFontIndex)99 CPDF_Font* CPVT_FontMap::GetPDFFont(int32_t nFontIndex) {
100 switch (nFontIndex) {
101 case 0:
102 return m_pDefFont;
103 case 1:
104 if (!m_pSysFont) {
105 GetAnnotSysPDFFont(m_pDocument, m_pResDict, m_pSysFont,
106 m_sSysFontAlias);
107 }
108 return m_pSysFont;
109 }
110 return NULL;
111 }
GetPDFFontAlias(int32_t nFontIndex)112 CFX_ByteString CPVT_FontMap::GetPDFFontAlias(int32_t nFontIndex) {
113 switch (nFontIndex) {
114 case 0:
115 return m_sDefFontAlias;
116 case 1:
117 if (!m_pSysFont) {
118 GetAnnotSysPDFFont(m_pDocument, m_pResDict, m_pSysFont,
119 m_sSysFontAlias);
120 }
121 return m_sSysFontAlias;
122 }
123 return "";
124 }
CPVT_Provider(IPVT_FontMap * pFontMap)125 CPVT_Provider::CPVT_Provider(IPVT_FontMap* pFontMap) : m_pFontMap(pFontMap) {
126 ASSERT(m_pFontMap);
127 }
~CPVT_Provider()128 CPVT_Provider::~CPVT_Provider() {}
GetCharWidth(int32_t nFontIndex,FX_WORD word,int32_t nWordStyle)129 int32_t CPVT_Provider::GetCharWidth(int32_t nFontIndex,
130 FX_WORD word,
131 int32_t nWordStyle) {
132 if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex)) {
133 FX_DWORD charcode = pPDFFont->CharCodeFromUnicode(word);
134 if (charcode != CPDF_Font::kInvalidCharCode) {
135 return pPDFFont->GetCharWidthF(charcode);
136 }
137 }
138 return 0;
139 }
GetTypeAscent(int32_t nFontIndex)140 int32_t CPVT_Provider::GetTypeAscent(int32_t nFontIndex) {
141 if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex)) {
142 return pPDFFont->GetTypeAscent();
143 }
144 return 0;
145 }
GetTypeDescent(int32_t nFontIndex)146 int32_t CPVT_Provider::GetTypeDescent(int32_t nFontIndex) {
147 if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex)) {
148 return pPDFFont->GetTypeDescent();
149 }
150 return 0;
151 }
GetWordFontIndex(FX_WORD word,int32_t charset,int32_t nFontIndex)152 int32_t CPVT_Provider::GetWordFontIndex(FX_WORD word,
153 int32_t charset,
154 int32_t nFontIndex) {
155 if (CPDF_Font* pDefFont = m_pFontMap->GetPDFFont(0)) {
156 if (pDefFont->CharCodeFromUnicode(word) != CPDF_Font::kInvalidCharCode) {
157 return 0;
158 }
159 }
160 if (CPDF_Font* pSysFont = m_pFontMap->GetPDFFont(1)) {
161 if (pSysFont->CharCodeFromUnicode(word) != CPDF_Font::kInvalidCharCode) {
162 return 1;
163 }
164 }
165 return -1;
166 }
IsLatinWord(FX_WORD word)167 FX_BOOL CPVT_Provider::IsLatinWord(FX_WORD word) {
168 if ((word >= 0x61 && word <= 0x7A) || (word >= 0x41 && word <= 0x5A) ||
169 word == 0x2D || word == 0x27) {
170 return TRUE;
171 }
172 return FALSE;
173 }
GetDefaultFontIndex()174 int32_t CPVT_Provider::GetDefaultFontIndex() {
175 return 0;
176 }
177
GetPDFWordString(IPVT_FontMap * pFontMap,int32_t nFontIndex,FX_WORD Word,FX_WORD SubWord)178 static CFX_ByteString GetPDFWordString(IPVT_FontMap* pFontMap,
179 int32_t nFontIndex,
180 FX_WORD Word,
181 FX_WORD SubWord) {
182 CFX_ByteString sWord;
183 if (SubWord > 0) {
184 sWord.Format("%c", SubWord);
185 return sWord;
186 }
187
188 if (!pFontMap)
189 return sWord;
190
191 if (CPDF_Font* pPDFFont = pFontMap->GetPDFFont(nFontIndex)) {
192 if (pPDFFont->GetBaseFont().Compare("Symbol") == 0 ||
193 pPDFFont->GetBaseFont().Compare("ZapfDingbats") == 0) {
194 sWord.Format("%c", Word);
195 } else {
196 FX_DWORD dwCharCode = pPDFFont->CharCodeFromUnicode(Word);
197 if (dwCharCode != CPDF_Font::kInvalidCharCode) {
198 pPDFFont->AppendChar(sWord, dwCharCode);
199 }
200 }
201 }
202 return sWord;
203 }
204
GetWordRenderString(const CFX_ByteString & strWords)205 static CFX_ByteString GetWordRenderString(const CFX_ByteString& strWords) {
206 if (strWords.GetLength() > 0) {
207 return PDF_EncodeString(strWords) + " Tj\n";
208 }
209 return "";
210 }
GetFontSetString(IPVT_FontMap * pFontMap,int32_t nFontIndex,FX_FLOAT fFontSize)211 static CFX_ByteString GetFontSetString(IPVT_FontMap* pFontMap,
212 int32_t nFontIndex,
213 FX_FLOAT fFontSize) {
214 CFX_ByteTextBuf sRet;
215 if (pFontMap) {
216 CFX_ByteString sFontAlias = pFontMap->GetPDFFontAlias(nFontIndex);
217 if (sFontAlias.GetLength() > 0 && fFontSize > 0) {
218 sRet << "/" << sFontAlias << " " << fFontSize << " Tf\n";
219 }
220 }
221 return sRet.GetByteString();
222 }
ParseColor(const CFX_ByteString & str)223 static CPVT_Color ParseColor(const CFX_ByteString& str) {
224 CPDF_SimpleParser syntax(str);
225 syntax.SetPos(0);
226 if (syntax.FindTagParam("g", 1)) {
227 return CPVT_Color(CT_GRAY, FX_atof(syntax.GetWord()));
228 }
229 syntax.SetPos(0);
230 if (syntax.FindTagParam("rg", 3)) {
231 FX_FLOAT f1 = FX_atof(syntax.GetWord());
232 FX_FLOAT f2 = FX_atof(syntax.GetWord());
233 FX_FLOAT f3 = FX_atof(syntax.GetWord());
234 return CPVT_Color(CT_RGB, f1, f2, f3);
235 }
236 syntax.SetPos(0);
237 if (syntax.FindTagParam("k", 4)) {
238 FX_FLOAT f1 = FX_atof(syntax.GetWord());
239 FX_FLOAT f2 = FX_atof(syntax.GetWord());
240 FX_FLOAT f3 = FX_atof(syntax.GetWord());
241 FX_FLOAT f4 = FX_atof(syntax.GetWord());
242 return CPVT_Color(CT_CMYK, f1, f2, f3, f4);
243 }
244 return CPVT_Color(CT_TRANSPARENT);
245 }
ParseColor(const CPDF_Array & array)246 static CPVT_Color ParseColor(const CPDF_Array& array) {
247 CPVT_Color rt;
248 switch (array.GetCount()) {
249 case 1:
250 rt = CPVT_Color(CT_GRAY, array.GetFloat(0));
251 break;
252 case 3:
253 rt = CPVT_Color(CT_RGB, array.GetFloat(0), array.GetFloat(1),
254 array.GetFloat(2));
255 break;
256 case 4:
257 rt = CPVT_Color(CT_CMYK, array.GetFloat(0), array.GetFloat(1),
258 array.GetFloat(2), array.GetFloat(3));
259 break;
260 }
261 return rt;
262 }
GenerateWidgetAP(CPDF_Document * pDoc,CPDF_Dictionary * pAnnotDict,const int32_t & nWidgetType)263 static FX_BOOL GenerateWidgetAP(CPDF_Document* pDoc,
264 CPDF_Dictionary* pAnnotDict,
265 const int32_t& nWidgetType) {
266 CPDF_Dictionary* pFormDict = NULL;
267 if (CPDF_Dictionary* pRootDict = pDoc->GetRoot()) {
268 pFormDict = pRootDict->GetDict("AcroForm");
269 }
270 if (!pFormDict) {
271 return FALSE;
272 }
273 CFX_ByteString DA;
274 if (CPDF_Object* pDAObj = FPDF_GetFieldAttr(pAnnotDict, "DA")) {
275 DA = pDAObj->GetString();
276 }
277 if (DA.IsEmpty()) {
278 DA = pFormDict->GetString("DA");
279 }
280 if (DA.IsEmpty()) {
281 return FALSE;
282 }
283 CPDF_SimpleParser syntax(DA);
284 syntax.FindTagParam("Tf", 2);
285 CFX_ByteString sFontName = syntax.GetWord();
286 sFontName = PDF_NameDecode(sFontName);
287 if (sFontName.IsEmpty()) {
288 return FALSE;
289 }
290 FX_FLOAT fFontSize = FX_atof(syntax.GetWord());
291 CPVT_Color crText = ParseColor(DA);
292 FX_BOOL bUseFormRes = FALSE;
293 CPDF_Dictionary* pFontDict = NULL;
294 CPDF_Dictionary* pDRDict = pAnnotDict->GetDict("DR");
295 if (!pDRDict) {
296 pDRDict = pFormDict->GetDict("DR");
297 bUseFormRes = TRUE;
298 }
299 CPDF_Dictionary* pDRFontDict = NULL;
300 if (pDRDict && (pDRFontDict = pDRDict->GetDict("Font"))) {
301 pFontDict = pDRFontDict->GetDict(sFontName.Mid(1));
302 if (!pFontDict && !bUseFormRes) {
303 pDRDict = pFormDict->GetDict("DR");
304 pDRFontDict = pDRDict->GetDict("Font");
305 if (pDRFontDict) {
306 pFontDict = pDRFontDict->GetDict(sFontName.Mid(1));
307 }
308 }
309 }
310 if (!pDRFontDict) {
311 return FALSE;
312 }
313 if (!pFontDict) {
314 pFontDict = new CPDF_Dictionary;
315 pFontDict->SetAtName("Type", "Font");
316 pFontDict->SetAtName("Subtype", "Type1");
317 pFontDict->SetAtName("BaseFont", "Helvetica");
318 pFontDict->SetAtName("Encoding", "WinAnsiEncoding");
319 pDoc->AddIndirectObject(pFontDict);
320 pDRFontDict->SetAtReference(sFontName.Mid(1), pDoc, pFontDict);
321 }
322 CPDF_Font* pDefFont = pDoc->LoadFont(pFontDict);
323 if (!pDefFont) {
324 return FALSE;
325 }
326 CPDF_Rect rcAnnot = pAnnotDict->GetRect("Rect");
327 int32_t nRotate = 0;
328 if (CPDF_Dictionary* pMKDict = pAnnotDict->GetDict("MK")) {
329 nRotate = pMKDict->GetInteger("R");
330 }
331 CPDF_Rect rcBBox;
332 CFX_Matrix matrix;
333 switch (nRotate % 360) {
334 case 0:
335 rcBBox = CPDF_Rect(0, 0, rcAnnot.right - rcAnnot.left,
336 rcAnnot.top - rcAnnot.bottom);
337 break;
338 case 90:
339 matrix = CFX_Matrix(0, 1, -1, 0, rcAnnot.right - rcAnnot.left, 0);
340 rcBBox = CPDF_Rect(0, 0, rcAnnot.top - rcAnnot.bottom,
341 rcAnnot.right - rcAnnot.left);
342 break;
343 case 180:
344 matrix = CFX_Matrix(-1, 0, 0, -1, rcAnnot.right - rcAnnot.left,
345 rcAnnot.top - rcAnnot.bottom);
346 rcBBox = CPDF_Rect(0, 0, rcAnnot.right - rcAnnot.left,
347 rcAnnot.top - rcAnnot.bottom);
348 break;
349 case 270:
350 matrix = CFX_Matrix(0, -1, 1, 0, 0, rcAnnot.top - rcAnnot.bottom);
351 rcBBox = CPDF_Rect(0, 0, rcAnnot.top - rcAnnot.bottom,
352 rcAnnot.right - rcAnnot.left);
353 break;
354 }
355 int32_t nBorderStyle = PBS_SOLID;
356 FX_FLOAT fBorderWidth = 1;
357 CPVT_Dash dsBorder(3, 0, 0);
358 CPVT_Color crLeftTop, crRightBottom;
359 if (CPDF_Dictionary* pBSDict = pAnnotDict->GetDict("BS")) {
360 if (pBSDict->KeyExist("W")) {
361 fBorderWidth = pBSDict->GetNumber("W");
362 }
363 if (CPDF_Array* pArray = pBSDict->GetArray("D")) {
364 dsBorder = CPVT_Dash(pArray->GetInteger(0), pArray->GetInteger(1),
365 pArray->GetInteger(2));
366 }
367 switch (pBSDict->GetString("S").GetAt(0)) {
368 case 'S':
369 nBorderStyle = PBS_SOLID;
370 break;
371 case 'D':
372 nBorderStyle = PBS_DASH;
373 break;
374 case 'B':
375 nBorderStyle = PBS_BEVELED;
376 fBorderWidth *= 2;
377 crLeftTop = CPVT_Color(CT_GRAY, 1);
378 crRightBottom = CPVT_Color(CT_GRAY, 0.5);
379 break;
380 case 'I':
381 nBorderStyle = PBS_INSET;
382 fBorderWidth *= 2;
383 crLeftTop = CPVT_Color(CT_GRAY, 0.5);
384 crRightBottom = CPVT_Color(CT_GRAY, 0.75);
385 break;
386 case 'U':
387 nBorderStyle = PBS_UNDERLINED;
388 break;
389 }
390 }
391 CPVT_Color crBorder, crBG;
392 if (CPDF_Dictionary* pMKDict = pAnnotDict->GetDict("MK")) {
393 if (CPDF_Array* pArray = pMKDict->GetArray("BC")) {
394 crBorder = ParseColor(*pArray);
395 }
396 if (CPDF_Array* pArray = pMKDict->GetArray("BG")) {
397 crBG = ParseColor(*pArray);
398 }
399 }
400 CFX_ByteTextBuf sAppStream;
401 CFX_ByteString sBG = CPVT_GenerateAP::GenerateColorAP(crBG, TRUE);
402 if (sBG.GetLength() > 0) {
403 sAppStream << "q\n" << sBG << rcBBox.left << " " << rcBBox.bottom << " "
404 << rcBBox.Width() << " " << rcBBox.Height() << " re f\n"
405 << "Q\n";
406 }
407 CFX_ByteString sBorderStream = CPVT_GenerateAP::GenerateBorderAP(
408 rcBBox, fBorderWidth, crBorder, crLeftTop, crRightBottom, nBorderStyle,
409 dsBorder);
410 if (sBorderStream.GetLength() > 0) {
411 sAppStream << "q\n" << sBorderStream << "Q\n";
412 }
413 CPDF_Rect rcBody =
414 CPDF_Rect(rcBBox.left + fBorderWidth, rcBBox.bottom + fBorderWidth,
415 rcBBox.right - fBorderWidth, rcBBox.top - fBorderWidth);
416 rcBody.Normalize();
417 CPDF_Dictionary* pAPDict = pAnnotDict->GetDict("AP");
418 if (!pAPDict) {
419 pAPDict = new CPDF_Dictionary;
420 pAnnotDict->SetAt("AP", pAPDict);
421 }
422 CPDF_Stream* pNormalStream = pAPDict->GetStream("N");
423 if (!pNormalStream) {
424 pNormalStream = new CPDF_Stream(nullptr, 0, nullptr);
425 int32_t objnum = pDoc->AddIndirectObject(pNormalStream);
426 pAnnotDict->GetDict("AP")->SetAtReference("N", pDoc, objnum);
427 }
428 CPDF_Dictionary* pStreamDict = pNormalStream->GetDict();
429 if (pStreamDict) {
430 pStreamDict->SetAtMatrix("Matrix", matrix);
431 pStreamDict->SetAtRect("BBox", rcBBox);
432 CPDF_Dictionary* pStreamResList = pStreamDict->GetDict("Resources");
433 if (pStreamResList) {
434 CPDF_Dictionary* pStreamResFontList = pStreamResList->GetDict("Font");
435 if (!pStreamResFontList) {
436 pStreamResFontList = new CPDF_Dictionary;
437 pStreamResList->SetAt("Font", pStreamResFontList);
438 }
439 if (!pStreamResFontList->KeyExist(sFontName)) {
440 pStreamResFontList->SetAtReference(sFontName, pDoc, pFontDict);
441 }
442 } else {
443 pStreamDict->SetAt("Resources", pFormDict->GetDict("DR")->Clone());
444 pStreamResList = pStreamDict->GetDict("Resources");
445 }
446 }
447 switch (nWidgetType) {
448 case 0: {
449 CFX_WideString swValue =
450 FPDF_GetFieldAttr(pAnnotDict, "V")
451 ? FPDF_GetFieldAttr(pAnnotDict, "V")->GetUnicodeText()
452 : CFX_WideString();
453 int32_t nAlign = FPDF_GetFieldAttr(pAnnotDict, "Q")
454 ? FPDF_GetFieldAttr(pAnnotDict, "Q")->GetInteger()
455 : 0;
456 FX_DWORD dwFlags = FPDF_GetFieldAttr(pAnnotDict, "Ff")
457 ? FPDF_GetFieldAttr(pAnnotDict, "Ff")->GetInteger()
458 : 0;
459 FX_DWORD dwMaxLen =
460 FPDF_GetFieldAttr(pAnnotDict, "MaxLen")
461 ? FPDF_GetFieldAttr(pAnnotDict, "MaxLen")->GetInteger()
462 : 0;
463 CPVT_FontMap map(pDoc,
464 pStreamDict ? pStreamDict->GetDict("Resources") : NULL,
465 pDefFont, sFontName.Right(sFontName.GetLength() - 1));
466 CPVT_Provider prd(&map);
467 CPDF_VariableText vt;
468 vt.SetProvider(&prd);
469 vt.SetPlateRect(rcBody);
470 vt.SetAlignment(nAlign);
471 if (IsFloatZero(fFontSize)) {
472 vt.SetAutoFontSize(TRUE);
473 } else {
474 vt.SetFontSize(fFontSize);
475 }
476 FX_BOOL bMultiLine = (dwFlags >> 12) & 1;
477 if (bMultiLine) {
478 vt.SetMultiLine(TRUE);
479 vt.SetAutoReturn(TRUE);
480 }
481 FX_WORD subWord = 0;
482 if ((dwFlags >> 13) & 1) {
483 subWord = '*';
484 vt.SetPasswordChar(subWord);
485 }
486 FX_BOOL bCharArray = (dwFlags >> 24) & 1;
487 if (bCharArray) {
488 vt.SetCharArray(dwMaxLen);
489 } else {
490 vt.SetLimitChar(dwMaxLen);
491 }
492 vt.Initialize();
493 vt.SetText(swValue.c_str());
494 vt.RearrangeAll();
495 CPDF_Rect rcContent = vt.GetContentRect();
496 CPDF_Point ptOffset(0.0f, 0.0f);
497 if (!bMultiLine) {
498 ptOffset =
499 CPDF_Point(0.0f, (rcContent.Height() - rcBody.Height()) / 2.0f);
500 }
501 CFX_ByteString sBody = CPVT_GenerateAP::GenerateEditAP(
502 &map, vt.GetIterator(), ptOffset, !bCharArray, subWord);
503 if (sBody.GetLength() > 0) {
504 sAppStream << "/Tx BMC\n"
505 << "q\n";
506 if (rcContent.Width() > rcBody.Width() ||
507 rcContent.Height() > rcBody.Height()) {
508 sAppStream << rcBody.left << " " << rcBody.bottom << " "
509 << rcBody.Width() << " " << rcBody.Height()
510 << " re\nW\nn\n";
511 }
512 sAppStream << "BT\n" << CPVT_GenerateAP::GenerateColorAP(crText, TRUE)
513 << sBody << "ET\n"
514 << "Q\nEMC\n";
515 }
516 } break;
517 case 1: {
518 CFX_WideString swValue =
519 FPDF_GetFieldAttr(pAnnotDict, "V")
520 ? FPDF_GetFieldAttr(pAnnotDict, "V")->GetUnicodeText()
521 : CFX_WideString();
522 CPVT_FontMap map(pDoc,
523 pStreamDict ? pStreamDict->GetDict("Resources") : NULL,
524 pDefFont, sFontName.Right(sFontName.GetLength() - 1));
525 CPVT_Provider prd(&map);
526 CPDF_VariableText vt;
527 vt.SetProvider(&prd);
528 CPDF_Rect rcButton = rcBody;
529 rcButton.left = rcButton.right - 13;
530 rcButton.Normalize();
531 CPDF_Rect rcEdit = rcBody;
532 rcEdit.right = rcButton.left;
533 rcEdit.Normalize();
534 vt.SetPlateRect(rcEdit);
535 if (IsFloatZero(fFontSize)) {
536 vt.SetAutoFontSize(TRUE);
537 } else {
538 vt.SetFontSize(fFontSize);
539 }
540 vt.Initialize();
541 vt.SetText(swValue.c_str());
542 vt.RearrangeAll();
543 CPDF_Rect rcContent = vt.GetContentRect();
544 CPDF_Point ptOffset =
545 CPDF_Point(0.0f, (rcContent.Height() - rcEdit.Height()) / 2.0f);
546 CFX_ByteString sEdit = CPVT_GenerateAP::GenerateEditAP(
547 &map, vt.GetIterator(), ptOffset, TRUE, 0);
548 if (sEdit.GetLength() > 0) {
549 sAppStream << "/Tx BMC\n"
550 << "q\n";
551 sAppStream << rcEdit.left << " " << rcEdit.bottom << " "
552 << rcEdit.Width() << " " << rcEdit.Height() << " re\nW\nn\n";
553 sAppStream << "BT\n" << CPVT_GenerateAP::GenerateColorAP(crText, TRUE)
554 << sEdit << "ET\n"
555 << "Q\nEMC\n";
556 }
557 CFX_ByteString sButton = CPVT_GenerateAP::GenerateColorAP(
558 CPVT_Color(CT_RGB, 220.0f / 255.0f, 220.0f / 255.0f, 220.0f / 255.0f),
559 TRUE);
560 if (sButton.GetLength() > 0 && !rcButton.IsEmpty()) {
561 sAppStream << "q\n" << sButton;
562 sAppStream << rcButton.left << " " << rcButton.bottom << " "
563 << rcButton.Width() << " " << rcButton.Height() << " re f\n";
564 sAppStream << "Q\n";
565 CFX_ByteString sButtonBorder = CPVT_GenerateAP::GenerateBorderAP(
566 rcButton, 2, CPVT_Color(CT_GRAY, 0), CPVT_Color(CT_GRAY, 1),
567 CPVT_Color(CT_GRAY, 0.5), PBS_BEVELED, CPVT_Dash(3, 0, 0));
568 if (sButtonBorder.GetLength() > 0) {
569 sAppStream << "q\n" << sButtonBorder << "Q\n";
570 }
571 CPDF_Point ptCenter = CPDF_Point((rcButton.left + rcButton.right) / 2,
572 (rcButton.top + rcButton.bottom) / 2);
573 if (IsFloatBigger(rcButton.Width(), 6) &&
574 IsFloatBigger(rcButton.Height(), 6)) {
575 sAppStream << "q\n"
576 << " 0 g\n";
577 sAppStream << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " m\n";
578 sAppStream << ptCenter.x + 3 << " " << ptCenter.y + 1.5f << " l\n";
579 sAppStream << ptCenter.x << " " << ptCenter.y - 1.5f << " l\n";
580 sAppStream << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " l f\n";
581 sAppStream << sButton << "Q\n";
582 }
583 }
584 } break;
585 case 2: {
586 CPVT_FontMap map(pDoc,
587 pStreamDict ? pStreamDict->GetDict("Resources") : NULL,
588 pDefFont, sFontName.Right(sFontName.GetLength() - 1));
589 CPVT_Provider prd(&map);
590 CPDF_Array* pOpts = FPDF_GetFieldAttr(pAnnotDict, "Opt")
591 ? FPDF_GetFieldAttr(pAnnotDict, "Opt")->GetArray()
592 : NULL;
593 CPDF_Array* pSels = FPDF_GetFieldAttr(pAnnotDict, "I")
594 ? FPDF_GetFieldAttr(pAnnotDict, "I")->GetArray()
595 : NULL;
596 int32_t nTop = FPDF_GetFieldAttr(pAnnotDict, "TI")
597 ? FPDF_GetFieldAttr(pAnnotDict, "TI")->GetInteger()
598 : 0;
599 CFX_ByteTextBuf sBody;
600 if (pOpts) {
601 FX_FLOAT fy = rcBody.top;
602 for (int32_t i = nTop, sz = pOpts->GetCount(); i < sz; i++) {
603 if (IsFloatSmaller(fy, rcBody.bottom)) {
604 break;
605 }
606 if (CPDF_Object* pOpt = pOpts->GetElementValue(i)) {
607 CFX_WideString swItem;
608 if (pOpt->IsString())
609 swItem = pOpt->GetUnicodeText();
610 else if (CPDF_Array* pArray = pOpt->AsArray())
611 swItem = pArray->GetElementValue(1)->GetUnicodeText();
612
613 FX_BOOL bSelected = FALSE;
614 if (pSels) {
615 for (FX_DWORD s = 0, ssz = pSels->GetCount(); s < ssz; s++) {
616 if (i == pSels->GetInteger(s)) {
617 bSelected = TRUE;
618 break;
619 }
620 }
621 }
622 CPDF_VariableText vt;
623 vt.SetProvider(&prd);
624 vt.SetPlateRect(CPDF_Rect(rcBody.left, 0.0f, rcBody.right, 0.0f));
625 if (IsFloatZero(fFontSize)) {
626 vt.SetFontSize(12.0f);
627 } else {
628 vt.SetFontSize(fFontSize);
629 }
630 vt.Initialize();
631 vt.SetText(swItem.c_str());
632 vt.RearrangeAll();
633 FX_FLOAT fItemHeight = vt.GetContentRect().Height();
634 if (bSelected) {
635 CPDF_Rect rcItem =
636 CPDF_Rect(rcBody.left, fy - fItemHeight, rcBody.right, fy);
637 sBody << "q\n" << CPVT_GenerateAP::GenerateColorAP(
638 CPVT_Color(CT_RGB, 0, 51.0f / 255.0f,
639 113.0f / 255.0f),
640 TRUE)
641 << rcItem.left << " " << rcItem.bottom << " "
642 << rcItem.Width() << " " << rcItem.Height() << " re f\n"
643 << "Q\n";
644 sBody << "BT\n" << CPVT_GenerateAP::GenerateColorAP(
645 CPVT_Color(CT_GRAY, 1), TRUE)
646 << CPVT_GenerateAP::GenerateEditAP(&map, vt.GetIterator(),
647 CPDF_Point(0.0f, fy),
648 TRUE, 0)
649 << "ET\n";
650 } else {
651 sBody << "BT\n" << CPVT_GenerateAP::GenerateColorAP(crText, TRUE)
652 << CPVT_GenerateAP::GenerateEditAP(&map, vt.GetIterator(),
653 CPDF_Point(0.0f, fy),
654 TRUE, 0)
655 << "ET\n";
656 }
657 fy -= fItemHeight;
658 }
659 }
660 }
661 if (sBody.GetSize() > 0) {
662 sAppStream << "/Tx BMC\n"
663 << "q\n";
664 sAppStream << rcBody.left << " " << rcBody.bottom << " "
665 << rcBody.Width() << " " << rcBody.Height() << " re\nW\nn\n";
666 sAppStream << sBody.GetByteString() << "Q\nEMC\n";
667 }
668 } break;
669 }
670 if (pNormalStream) {
671 pNormalStream->SetData((uint8_t*)sAppStream.GetBuffer(),
672 sAppStream.GetSize(), FALSE, FALSE);
673 pStreamDict = pNormalStream->GetDict();
674 if (pStreamDict) {
675 pStreamDict->SetAtMatrix("Matrix", matrix);
676 pStreamDict->SetAtRect("BBox", rcBBox);
677 CPDF_Dictionary* pStreamResList = pStreamDict->GetDict("Resources");
678 if (pStreamResList) {
679 CPDF_Dictionary* pStreamResFontList = pStreamResList->GetDict("Font");
680 if (!pStreamResFontList) {
681 pStreamResFontList = new CPDF_Dictionary;
682 pStreamResList->SetAt("Font", pStreamResFontList);
683 }
684 if (!pStreamResFontList->KeyExist(sFontName)) {
685 pStreamResFontList->SetAtReference(sFontName, pDoc, pFontDict);
686 }
687 } else {
688 pStreamDict->SetAt("Resources", pFormDict->GetDict("DR")->Clone());
689 pStreamResList = pStreamDict->GetDict("Resources");
690 }
691 }
692 }
693 return TRUE;
694 }
GenerateTextFieldAP(CPDF_Document * pDoc,CPDF_Dictionary * pAnnotDict)695 FX_BOOL CPVT_GenerateAP::GenerateTextFieldAP(CPDF_Document* pDoc,
696 CPDF_Dictionary* pAnnotDict) {
697 return GenerateWidgetAP(pDoc, pAnnotDict, 0);
698 }
GenerateComboBoxAP(CPDF_Document * pDoc,CPDF_Dictionary * pAnnotDict)699 FX_BOOL CPVT_GenerateAP::GenerateComboBoxAP(CPDF_Document* pDoc,
700 CPDF_Dictionary* pAnnotDict) {
701 return GenerateWidgetAP(pDoc, pAnnotDict, 1);
702 }
GenerateListBoxAP(CPDF_Document * pDoc,CPDF_Dictionary * pAnnotDict)703 FX_BOOL CPVT_GenerateAP::GenerateListBoxAP(CPDF_Document* pDoc,
704 CPDF_Dictionary* pAnnotDict) {
705 return GenerateWidgetAP(pDoc, pAnnotDict, 2);
706 }
GenerateEditAP(IPVT_FontMap * pFontMap,IPDF_VariableText_Iterator * pIterator,const CPDF_Point & ptOffset,FX_BOOL bContinuous,FX_WORD SubWord,const CPVT_WordRange * pVisible)707 CFX_ByteString CPVT_GenerateAP::GenerateEditAP(
708 IPVT_FontMap* pFontMap,
709 IPDF_VariableText_Iterator* pIterator,
710 const CPDF_Point& ptOffset,
711 FX_BOOL bContinuous,
712 FX_WORD SubWord,
713 const CPVT_WordRange* pVisible) {
714 CFX_ByteTextBuf sEditStream, sLineStream, sWords;
715 CPDF_Point ptOld(0.0f, 0.0f), ptNew(0.0f, 0.0f);
716 int32_t nCurFontIndex = -1;
717 if (pIterator) {
718 if (pVisible) {
719 pIterator->SetAt(pVisible->BeginPos);
720 } else {
721 pIterator->SetAt(0);
722 }
723 CPVT_WordPlace oldplace;
724 while (pIterator->NextWord()) {
725 CPVT_WordPlace place = pIterator->GetAt();
726 if (pVisible && place.WordCmp(pVisible->EndPos) > 0) {
727 break;
728 }
729 if (bContinuous) {
730 if (place.LineCmp(oldplace) != 0) {
731 if (sWords.GetSize() > 0) {
732 sLineStream << GetWordRenderString(sWords.GetByteString());
733 sEditStream << sLineStream;
734 sLineStream.Clear();
735 sWords.Clear();
736 }
737 CPVT_Word word;
738 if (pIterator->GetWord(word)) {
739 ptNew = CPDF_Point(word.ptWord.x + ptOffset.x,
740 word.ptWord.y + ptOffset.y);
741 } else {
742 CPVT_Line line;
743 pIterator->GetLine(line);
744 ptNew = CPDF_Point(line.ptLine.x + ptOffset.x,
745 line.ptLine.y + ptOffset.y);
746 }
747 if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) {
748 sLineStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y
749 << " Td\n";
750 ptOld = ptNew;
751 }
752 }
753 CPVT_Word word;
754 if (pIterator->GetWord(word)) {
755 if (word.nFontIndex != nCurFontIndex) {
756 if (sWords.GetSize() > 0) {
757 sLineStream << GetWordRenderString(sWords.GetByteString());
758 sWords.Clear();
759 }
760 sLineStream << GetFontSetString(pFontMap, word.nFontIndex,
761 word.fFontSize);
762 nCurFontIndex = word.nFontIndex;
763 }
764 sWords << GetPDFWordString(pFontMap, nCurFontIndex, word.Word,
765 SubWord);
766 }
767 oldplace = place;
768 } else {
769 CPVT_Word word;
770 if (pIterator->GetWord(word)) {
771 ptNew = CPDF_Point(word.ptWord.x + ptOffset.x,
772 word.ptWord.y + ptOffset.y);
773 if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) {
774 sEditStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y
775 << " Td\n";
776 ptOld = ptNew;
777 }
778 if (word.nFontIndex != nCurFontIndex) {
779 sEditStream << GetFontSetString(pFontMap, word.nFontIndex,
780 word.fFontSize);
781 nCurFontIndex = word.nFontIndex;
782 }
783 sEditStream << GetWordRenderString(
784 GetPDFWordString(pFontMap, nCurFontIndex, word.Word, SubWord));
785 }
786 }
787 }
788 if (sWords.GetSize() > 0) {
789 sLineStream << GetWordRenderString(sWords.GetByteString());
790 sEditStream << sLineStream;
791 sWords.Clear();
792 }
793 }
794 return sEditStream.GetByteString();
795 }
GenerateBorderAP(const CPDF_Rect & rect,FX_FLOAT fWidth,const CPVT_Color & color,const CPVT_Color & crLeftTop,const CPVT_Color & crRightBottom,int32_t nStyle,const CPVT_Dash & dash)796 CFX_ByteString CPVT_GenerateAP::GenerateBorderAP(
797 const CPDF_Rect& rect,
798 FX_FLOAT fWidth,
799 const CPVT_Color& color,
800 const CPVT_Color& crLeftTop,
801 const CPVT_Color& crRightBottom,
802 int32_t nStyle,
803 const CPVT_Dash& dash) {
804 CFX_ByteTextBuf sAppStream;
805 CFX_ByteString sColor;
806 FX_FLOAT fLeft = rect.left;
807 FX_FLOAT fRight = rect.right;
808 FX_FLOAT fTop = rect.top;
809 FX_FLOAT fBottom = rect.bottom;
810 if (fWidth > 0.0f) {
811 FX_FLOAT fHalfWidth = fWidth / 2.0f;
812 switch (nStyle) {
813 default:
814 case PBS_SOLID:
815 sColor = GenerateColorAP(color, TRUE);
816 if (sColor.GetLength() > 0) {
817 sAppStream << sColor;
818 sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " "
819 << fTop - fBottom << " re\n";
820 sAppStream << fLeft + fWidth << " " << fBottom + fWidth << " "
821 << fRight - fLeft - fWidth * 2 << " "
822 << fTop - fBottom - fWidth * 2 << " re\n";
823 sAppStream << "f*\n";
824 }
825 break;
826 case PBS_DASH:
827 sColor = GenerateColorAP(color, FALSE);
828 if (sColor.GetLength() > 0) {
829 sAppStream << sColor;
830 sAppStream << fWidth << " w"
831 << " [" << dash.nDash << " " << dash.nGap << "] "
832 << dash.nPhase << " d\n";
833 sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2
834 << " m\n";
835 sAppStream << fLeft + fWidth / 2 << " " << fTop - fWidth / 2
836 << " l\n";
837 sAppStream << fRight - fWidth / 2 << " " << fTop - fWidth / 2
838 << " l\n";
839 sAppStream << fRight - fWidth / 2 << " " << fBottom + fWidth / 2
840 << " l\n";
841 sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2
842 << " l S\n";
843 }
844 break;
845 case PBS_BEVELED:
846 case PBS_INSET:
847 sColor = GenerateColorAP(crLeftTop, TRUE);
848 if (sColor.GetLength() > 0) {
849 sAppStream << sColor;
850 sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth
851 << " m\n";
852 sAppStream << fLeft + fHalfWidth << " " << fTop - fHalfWidth
853 << " l\n";
854 sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth
855 << " l\n";
856 sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2
857 << " l\n";
858 sAppStream << fLeft + fHalfWidth * 2 << " " << fTop - fHalfWidth * 2
859 << " l\n";
860 sAppStream << fLeft + fHalfWidth * 2 << " "
861 << fBottom + fHalfWidth * 2 << " l f\n";
862 }
863 sColor = GenerateColorAP(crRightBottom, TRUE);
864 if (sColor.GetLength() > 0) {
865 sAppStream << sColor;
866 sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth
867 << " m\n";
868 sAppStream << fRight - fHalfWidth << " " << fBottom + fHalfWidth
869 << " l\n";
870 sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth
871 << " l\n";
872 sAppStream << fLeft + fHalfWidth * 2 << " "
873 << fBottom + fHalfWidth * 2 << " l\n";
874 sAppStream << fRight - fHalfWidth * 2 << " "
875 << fBottom + fHalfWidth * 2 << " l\n";
876 sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2
877 << " l f\n";
878 }
879 sColor = GenerateColorAP(color, TRUE);
880 if (sColor.GetLength() > 0) {
881 sAppStream << sColor;
882 sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " "
883 << fTop - fBottom << " re\n";
884 sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth << " "
885 << fRight - fLeft - fHalfWidth * 2 << " "
886 << fTop - fBottom - fHalfWidth * 2 << " re f*\n";
887 }
888 break;
889 case PBS_UNDERLINED:
890 sColor = GenerateColorAP(color, FALSE);
891 if (sColor.GetLength() > 0) {
892 sAppStream << sColor;
893 sAppStream << fWidth << " w\n";
894 sAppStream << fLeft << " " << fBottom + fWidth / 2 << " m\n";
895 sAppStream << fRight << " " << fBottom + fWidth / 2 << " l S\n";
896 }
897 break;
898 }
899 }
900 return sAppStream.GetByteString();
901 }
GenerateColorAP(const CPVT_Color & color,const FX_BOOL & bFillOrStroke)902 CFX_ByteString CPVT_GenerateAP::GenerateColorAP(const CPVT_Color& color,
903 const FX_BOOL& bFillOrStroke) {
904 CFX_ByteTextBuf sColorStream;
905 switch (color.nColorType) {
906 case CT_RGB:
907 sColorStream << color.fColor1 << " " << color.fColor2 << " "
908 << color.fColor3 << " " << (bFillOrStroke ? "rg" : "RG")
909 << "\n";
910 break;
911 case CT_GRAY:
912 sColorStream << color.fColor1 << " " << (bFillOrStroke ? "g" : "G")
913 << "\n";
914 break;
915 case CT_CMYK:
916 sColorStream << color.fColor1 << " " << color.fColor2 << " "
917 << color.fColor3 << " " << color.fColor4 << " "
918 << (bFillOrStroke ? "k" : "K") << "\n";
919 break;
920 }
921 return sColorStream.GetByteString();
922 }
923