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