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 || 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")? FPDF_GetFieldAttr(pAnnotDict, "Ff")->GetInteger() : 0;
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;
257 if (CPDF_Object* pDAObj = FPDF_GetFieldAttr(pAnnotDict, "DA")) {
258 DA = pDAObj->GetString();
259 }
260 if (DA.IsEmpty()) {
261 DA = pFormDict->GetString("DA");
262 }
263 if (DA.IsEmpty()) {
264 return FALSE;
265 }
266 CPDF_SimpleParser syntax(DA);
267 syntax.FindTagParam("Tf", 2);
268 CFX_ByteString sFontName = syntax.GetWord();
269 sFontName = PDF_NameDecode(sFontName);
270 if (sFontName.IsEmpty()) {
271 return FALSE;
272 }
273 FX_FLOAT fFontSize = FX_atof(syntax.GetWord());
274 CPVT_Color crText = ParseColor(DA);
275 FX_BOOL bUseFormRes = FALSE;
276 CPDF_Dictionary * pFontDict = NULL;
277 CPDF_Dictionary* pDRDict = pAnnotDict->GetDict(FX_BSTRC("DR"));
278 if (pDRDict == NULL) {
279 pDRDict = pFormDict->GetDict(FX_BSTRC("DR"));
280 bUseFormRes = TRUE;
281 }
282 CPDF_Dictionary * pDRFontDict = NULL;
283 if (pDRDict && (pDRFontDict = pDRDict->GetDict("Font"))) {
284 pFontDict = pDRFontDict->GetDict(sFontName.Mid(1));
285 if (!pFontDict && !bUseFormRes) {
286 pDRDict = pFormDict->GetDict(FX_BSTRC("DR"));
287 pDRFontDict = pDRDict->GetDict("Font");
288 if (pDRFontDict) {
289 pFontDict = pDRFontDict->GetDict(sFontName.Mid(1));
290 }
291 }
292 }
293 if (!pDRFontDict) {
294 return FALSE;
295 }
296 if (!pFontDict) {
297 pFontDict = CPDF_Dictionary::Create();
298 if (pFontDict == NULL) {
299 return FALSE;
300 }
301 pFontDict->SetAtName(FX_BSTRC("Type"), "Font");
302 pFontDict->SetAtName(FX_BSTRC("Subtype"), "Type1");
303 pFontDict->SetAtName(FX_BSTRC("BaseFont"), "Helvetica");
304 pFontDict->SetAtName(FX_BSTRC("Encoding"), "WinAnsiEncoding");
305 pDoc->AddIndirectObject(pFontDict);
306 pDRFontDict->SetAtReference(sFontName.Mid(1), pDoc, pFontDict);
307 }
308 CPDF_Font* pDefFont = pDoc->LoadFont(pFontDict);
309 if (!pDefFont) {
310 return FALSE;
311 }
312 CPDF_Rect rcAnnot = pAnnotDict->GetRect("Rect");
313 FX_INT32 nRotate = 0;
314 if (CPDF_Dictionary * pMKDict = pAnnotDict->GetDict("MK")) {
315 nRotate = pMKDict->GetInteger("R");
316 }
317 CPDF_Rect rcBBox;
318 CPDF_Matrix matrix;
319 switch (nRotate % 360) {
320 case 0:
321 rcBBox = CPDF_Rect(0, 0, rcAnnot.right - rcAnnot.left, rcAnnot.top - rcAnnot.bottom);
322 break;
323 case 90:
324 matrix = CPDF_Matrix(0, 1, -1, 0, rcAnnot.right - rcAnnot.left, 0);
325 rcBBox = CPDF_Rect(0, 0, rcAnnot.top - rcAnnot.bottom, rcAnnot.right - rcAnnot.left);
326 break;
327 case 180:
328 matrix = CPDF_Matrix(-1, 0, 0, -1, rcAnnot.right - rcAnnot.left, rcAnnot.top - rcAnnot.bottom);
329 rcBBox = CPDF_Rect(0, 0, rcAnnot.right - rcAnnot.left, rcAnnot.top - rcAnnot.bottom);
330 break;
331 case 270:
332 matrix = CPDF_Matrix(0, -1, 1, 0, 0, rcAnnot.top - rcAnnot.bottom);
333 rcBBox = CPDF_Rect(0, 0, rcAnnot.top - rcAnnot.bottom, rcAnnot.right - rcAnnot.left);
334 break;
335 }
336 FX_INT32 nBorderStyle = PBS_SOLID;
337 FX_FLOAT fBorderWidth = 1;
338 CPVT_Dash dsBorder(3, 0, 0);
339 CPVT_Color crLeftTop, crRightBottom;
340 if (CPDF_Dictionary * pBSDict = pAnnotDict->GetDict("BS")) {
341 if (pBSDict->KeyExist("W")) {
342 fBorderWidth = pBSDict->GetNumber("W");
343 }
344 if (CPDF_Array * pArray = pBSDict->GetArray("D")) {
345 dsBorder = CPVT_Dash(pArray->GetInteger(0), pArray->GetInteger(1), pArray->GetInteger(2));
346 }
347 switch (pBSDict->GetString("S").GetAt(0)) {
348 case 'S':
349 nBorderStyle = PBS_SOLID;
350 break;
351 case 'D':
352 nBorderStyle = PBS_DASH;
353 break;
354 case 'B':
355 nBorderStyle = PBS_BEVELED;
356 fBorderWidth *= 2;
357 crLeftTop = CPVT_Color(CT_GRAY, 1);
358 crRightBottom = CPVT_Color(CT_GRAY, 0.5);
359 break;
360 case 'I':
361 nBorderStyle = PBS_INSET;
362 fBorderWidth *= 2;
363 crLeftTop = CPVT_Color(CT_GRAY, 0.5);
364 crRightBottom = CPVT_Color(CT_GRAY, 0.75);
365 break;
366 case 'U':
367 nBorderStyle = PBS_UNDERLINED;
368 break;
369 }
370 }
371 CPVT_Color crBorder, crBG;
372 if (CPDF_Dictionary * pMKDict = pAnnotDict->GetDict("MK")) {
373 if (CPDF_Array * pArray = pMKDict->GetArray("BC")) {
374 crBorder = ParseColor(*pArray);
375 }
376 if (CPDF_Array * pArray = pMKDict->GetArray("BG")) {
377 crBG = ParseColor(*pArray);
378 }
379 }
380 CFX_ByteTextBuf sAppStream;
381 CFX_ByteString sBG = CPVT_GenerateAP::GenerateColorAP(crBG, TRUE);
382 if (sBG.GetLength() > 0) {
383 sAppStream << "q\n" << sBG << rcBBox.left << " " << rcBBox.bottom << " "
384 << rcBBox.Width() << " " << rcBBox.Height() << " re f\n" << "Q\n";
385 }
386 CFX_ByteString sBorderStream = CPVT_GenerateAP::GenerateBorderAP(rcBBox, fBorderWidth,
387 crBorder, crLeftTop, crRightBottom, nBorderStyle, dsBorder);
388 if (sBorderStream.GetLength() > 0) {
389 sAppStream << "q\n" << sBorderStream << "Q\n";
390 }
391 CPDF_Rect rcBody = CPDF_Rect(rcBBox.left + fBorderWidth, rcBBox.bottom + fBorderWidth,
392 rcBBox.right - fBorderWidth, rcBBox.top - fBorderWidth);
393 rcBody.Normalize();
394 CPDF_Dictionary* pAPDict = pAnnotDict->GetDict("AP");
395 if (pAPDict == NULL) {
396 pAPDict = CPDF_Dictionary::Create();
397 if (pAPDict == NULL) {
398 return FALSE;
399 }
400 pAnnotDict->SetAt("AP", pAPDict);
401 }
402 CPDF_Stream* pNormalStream = pAPDict->GetStream("N");
403 if (pNormalStream == NULL) {
404 pNormalStream = CPDF_Stream::Create(NULL, 0, NULL);
405 if (pNormalStream == NULL) {
406 return FALSE;
407 }
408 FX_INT32 objnum = pDoc->AddIndirectObject(pNormalStream);
409 pAnnotDict->GetDict("AP")->SetAtReference("N", pDoc, objnum);
410 }
411 CPDF_Dictionary * pStreamDict = pNormalStream->GetDict();
412 if (pStreamDict) {
413 pStreamDict->SetAtMatrix("Matrix", matrix);
414 pStreamDict->SetAtRect("BBox", rcBBox);
415 CPDF_Dictionary* pStreamResList = pStreamDict->GetDict("Resources");
416 if (pStreamResList) {
417 CPDF_Dictionary* pStreamResFontList = pStreamResList->GetDict("Font");
418 if (!pStreamResFontList) {
419 pStreamResFontList = CPDF_Dictionary::Create();
420 if (pStreamResFontList == NULL) {
421 return FALSE;
422 }
423 pStreamResList->SetAt("Font", pStreamResFontList);
424 }
425 if (!pStreamResFontList->KeyExist(sFontName)) {
426 pStreamResFontList->SetAtReference(sFontName, pDoc, pFontDict);
427 }
428 } else {
429 pStreamDict->SetAt("Resources", pFormDict->GetDict("DR")->Clone());
430 pStreamResList = pStreamDict->GetDict("Resources");
431 }
432 }
433 switch (nWidgetType) {
434 case 0: {
435 CFX_WideString swValue = FPDF_GetFieldAttr(pAnnotDict, "V")? FPDF_GetFieldAttr(pAnnotDict, "V")->GetUnicodeText() : CFX_WideString();
436 FX_INT32 nAlign = FPDF_GetFieldAttr(pAnnotDict, "Q")? FPDF_GetFieldAttr(pAnnotDict, "Q")->GetInteger() : 0;
437 FX_DWORD dwFlags = FPDF_GetFieldAttr(pAnnotDict, "Ff")? FPDF_GetFieldAttr(pAnnotDict, "Ff")->GetInteger() : 0;
438 FX_DWORD dwMaxLen = FPDF_GetFieldAttr(pAnnotDict, "MaxLen") ? FPDF_GetFieldAttr(pAnnotDict, "MaxLen")->GetInteger() : 0;
439 CPVT_FontMap map(pDoc, pStreamDict ? pStreamDict->GetDict("Resources") : NULL , pDefFont, sFontName.Right(sFontName.GetLength() - 1));
440 CPVT_Provider prd(&map);
441 CPDF_VariableText vt;
442 vt.SetProvider(&prd);
443 vt.SetPlateRect(rcBody);
444 vt.SetAlignment(nAlign);
445 if (IsFloatZero(fFontSize)) {
446 vt.SetAutoFontSize(TRUE);
447 } else {
448 vt.SetFontSize(fFontSize);
449 }
450 FX_BOOL bMultiLine = (dwFlags >> 12) & 1;
451 if (bMultiLine) {
452 vt.SetMultiLine(TRUE);
453 vt.SetAutoReturn(TRUE);
454 }
455 FX_WORD subWord = 0;
456 if ((dwFlags >> 13) & 1) {
457 subWord = '*';
458 vt.SetPasswordChar(subWord);
459 }
460 FX_BOOL bCharArray = (dwFlags >> 24) & 1;
461 if (bCharArray) {
462 vt.SetCharArray(dwMaxLen);
463 } else {
464 vt.SetLimitChar(dwMaxLen);
465 }
466 vt.Initialize();
467 vt.SetText(swValue.c_str());
468 vt.RearrangeAll();
469 CPDF_Rect rcContent = vt.GetContentRect();
470 CPDF_Point ptOffset(0.0f, 0.0f);
471 if (!bMultiLine) {
472 ptOffset = CPDF_Point(0.0f, (rcContent.Height() - rcBody.Height()) / 2.0f);
473 }
474 CFX_ByteString sBody = CPVT_GenerateAP::GenerateEditAP(&map, vt.GetIterator(), ptOffset, !bCharArray, subWord);
475 if (sBody.GetLength() > 0) {
476 sAppStream << "/Tx BMC\n" << "q\n";
477 if (rcContent.Width() > rcBody.Width() ||
478 rcContent.Height() > rcBody.Height()) {
479 sAppStream << rcBody.left << " " << rcBody.bottom << " "
480 << rcBody.Width() << " " << rcBody.Height() << " re\nW\nn\n";
481 }
482 sAppStream << "BT\n" << CPVT_GenerateAP::GenerateColorAP(crText, TRUE) << sBody << "ET\n" << "Q\nEMC\n";
483 }
484 }
485 break;
486 case 1: {
487 CFX_WideString swValue = FPDF_GetFieldAttr(pAnnotDict, "V") ? FPDF_GetFieldAttr(pAnnotDict, "V")->GetUnicodeText() : CFX_WideString();
488 CPVT_FontMap map(pDoc, pStreamDict ? pStreamDict->GetDict("Resources"):NULL, pDefFont, sFontName.Right(sFontName.GetLength() - 1));
489 CPVT_Provider prd(&map);
490 CPDF_VariableText vt;
491 vt.SetProvider(&prd);
492 CPDF_Rect rcButton = rcBody;
493 rcButton.left = rcButton.right - 13;
494 rcButton.Normalize();
495 CPDF_Rect rcEdit = rcBody;
496 rcEdit.right = rcButton.left;
497 rcEdit.Normalize();
498 vt.SetPlateRect(rcEdit);
499 if (IsFloatZero(fFontSize)) {
500 vt.SetAutoFontSize(TRUE);
501 } else {
502 vt.SetFontSize(fFontSize);
503 }
504 vt.Initialize();
505 vt.SetText(swValue.c_str());
506 vt.RearrangeAll();
507 CPDF_Rect rcContent = vt.GetContentRect();
508 CPDF_Point ptOffset = CPDF_Point(0.0f, (rcContent.Height() - rcEdit.Height()) / 2.0f);
509 CFX_ByteString sEdit = CPVT_GenerateAP::GenerateEditAP(&map, vt.GetIterator(), ptOffset, TRUE, 0);
510 if (sEdit.GetLength() > 0) {
511 sAppStream << "/Tx BMC\n" << "q\n";
512 sAppStream << rcEdit.left << " " << rcEdit.bottom << " "
513 << rcEdit.Width() << " " << rcEdit.Height() << " re\nW\nn\n";
514 sAppStream << "BT\n" << CPVT_GenerateAP::GenerateColorAP(crText, TRUE) << sEdit << "ET\n" << "Q\nEMC\n";
515 }
516 CFX_ByteString sButton = CPVT_GenerateAP::GenerateColorAP(CPVT_Color(CT_RGB, 220.0f / 255.0f, 220.0f / 255.0f, 220.0f / 255.0f), TRUE);
517 if (sButton.GetLength() > 0 && !rcButton.IsEmpty()) {
518 sAppStream << "q\n" << sButton;
519 sAppStream << rcButton.left << " " << rcButton.bottom << " "
520 << rcButton.Width() << " " << rcButton.Height() << " re f\n";
521 sAppStream << "Q\n";
522 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));
523 if (sButtonBorder.GetLength() > 0) {
524 sAppStream << "q\n" << sButtonBorder << "Q\n";
525 }
526 CPDF_Point ptCenter = CPDF_Point((rcButton.left + rcButton.right) / 2, (rcButton.top + rcButton.bottom) / 2);
527 if (IsFloatBigger(rcButton.Width(), 6) && IsFloatBigger(rcButton.Height(), 6)) {
528 sAppStream << "q\n" << " 0 g\n";
529 sAppStream << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " m\n";
530 sAppStream << ptCenter.x + 3 << " " << ptCenter.y + 1.5f << " l\n";
531 sAppStream << ptCenter.x << " " << ptCenter.y - 1.5f << " l\n";
532 sAppStream << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " l f\n";
533 sAppStream << sButton << "Q\n";
534 }
535 }
536 }
537 break;
538 case 2: {
539 CPVT_FontMap map(pDoc, pStreamDict ? pStreamDict->GetDict("Resources"):NULL, pDefFont, sFontName.Right(sFontName.GetLength() - 1));
540 CPVT_Provider prd(&map);
541 CPDF_Array * pOpts = FPDF_GetFieldAttr(pAnnotDict, "Opt") ? FPDF_GetFieldAttr(pAnnotDict, "Opt")->GetArray() : NULL;
542 CPDF_Array * pSels = FPDF_GetFieldAttr(pAnnotDict, "I") ? FPDF_GetFieldAttr(pAnnotDict, "I")->GetArray() : NULL;
543 FX_INT32 nTop = FPDF_GetFieldAttr(pAnnotDict, "TI") ? FPDF_GetFieldAttr(pAnnotDict, "TI")->GetInteger() : 0;
544 CFX_ByteTextBuf sBody;
545 if (pOpts) {
546 FX_FLOAT fy = rcBody.top;
547 for (FX_INT32 i = nTop, sz = pOpts->GetCount(); i < sz; i++) {
548 if (IsFloatSmaller(fy, rcBody.bottom)) {
549 break;
550 }
551 if (CPDF_Object* pOpt = pOpts->GetElementValue(i)) {
552 CFX_WideString swItem;
553 if (pOpt->GetType() == PDFOBJ_STRING) {
554 swItem = pOpt->GetUnicodeText();
555 } else if (pOpt->GetType() == PDFOBJ_ARRAY) {
556 swItem = ((CPDF_Array*)pOpt)->GetElementValue(1)->GetUnicodeText();
557 }
558 FX_BOOL bSelected = FALSE;
559 if (pSels) {
560 for (FX_DWORD s = 0, ssz = pSels->GetCount(); s < ssz; s++) {
561 if (i == pSels->GetInteger(s)) {
562 bSelected = TRUE;
563 break;
564 }
565 }
566 }
567 CPDF_VariableText vt;
568 vt.SetProvider(&prd);
569 vt.SetPlateRect(CPDF_Rect(rcBody.left, 0.0f, rcBody.right, 0.0f));
570 if (IsFloatZero(fFontSize)) {
571 vt.SetFontSize(12.0f);
572 } else {
573 vt.SetFontSize(fFontSize);
574 }
575 vt.Initialize();
576 vt.SetText(swItem.c_str());
577 vt.RearrangeAll();
578 FX_FLOAT fItemHeight = vt.GetContentRect().Height();
579 if (bSelected) {
580 CPDF_Rect rcItem = CPDF_Rect(rcBody.left, fy - fItemHeight, rcBody.right, fy);
581 sBody << "q\n" << CPVT_GenerateAP::GenerateColorAP(CPVT_Color(CT_RGB, 0, 51.0f / 255.0f, 113.0f / 255.0f), TRUE)
582 << rcItem.left << " " << rcItem.bottom << " " << rcItem.Width() << " " << rcItem.Height() << " re f\n" << "Q\n";
583 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";
584 } else {
585 sBody << "BT\n" << CPVT_GenerateAP::GenerateColorAP(crText, TRUE) << CPVT_GenerateAP::GenerateEditAP(&map, vt.GetIterator(), CPDF_Point(0.0f, fy), TRUE, 0) << "ET\n";
586 }
587 fy -= fItemHeight;
588 }
589 }
590 }
591 if (sBody.GetSize() > 0) {
592 sAppStream << "/Tx BMC\n" << "q\n";
593 sAppStream << rcBody.left << " " << rcBody.bottom << " "
594 << rcBody.Width() << " " << rcBody.Height() << " re\nW\nn\n";
595 sAppStream << sBody.GetByteString() << "Q\nEMC\n";
596 }
597 }
598 break;
599 }
600 if (pNormalStream) {
601 pNormalStream->SetData((FX_BYTE*)sAppStream.GetBuffer(), sAppStream.GetSize(), FALSE, FALSE);
602 pStreamDict = pNormalStream->GetDict();
603 if (pStreamDict) {
604 pStreamDict->SetAtMatrix("Matrix", matrix);
605 pStreamDict->SetAtRect("BBox", rcBBox);
606 CPDF_Dictionary* pStreamResList = pStreamDict->GetDict("Resources");
607 if (pStreamResList) {
608 CPDF_Dictionary* pStreamResFontList = pStreamResList->GetDict("Font");
609 if (!pStreamResFontList) {
610 pStreamResFontList = CPDF_Dictionary::Create();
611 if (pStreamResFontList == NULL) {
612 return FALSE;
613 }
614 pStreamResList->SetAt("Font", pStreamResFontList);
615 }
616 if (!pStreamResFontList->KeyExist(sFontName)) {
617 pStreamResFontList->SetAtReference(sFontName, pDoc, pFontDict);
618 }
619 } else {
620 pStreamDict->SetAt("Resources", pFormDict->GetDict("DR")->Clone());
621 pStreamResList = pStreamDict->GetDict("Resources");
622 }
623 }
624 }
625 return TRUE;
626 }
GenerateTextFieldAP(CPDF_Document * pDoc,CPDF_Dictionary * pAnnotDict)627 FX_BOOL CPVT_GenerateAP::GenerateTextFieldAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict)
628 {
629 return GenerateWidgetAP(pDoc, pAnnotDict, 0);
630 }
GenerateComboBoxAP(CPDF_Document * pDoc,CPDF_Dictionary * pAnnotDict)631 FX_BOOL CPVT_GenerateAP::GenerateComboBoxAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict)
632 {
633 return GenerateWidgetAP(pDoc, pAnnotDict, 1);
634 }
GenerateListBoxAP(CPDF_Document * pDoc,CPDF_Dictionary * pAnnotDict)635 FX_BOOL CPVT_GenerateAP::GenerateListBoxAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict)
636 {
637 return GenerateWidgetAP(pDoc, pAnnotDict, 2);
638 }
GenerateEditAP(IPVT_FontMap * pFontMap,IPDF_VariableText_Iterator * pIterator,const CPDF_Point & ptOffset,FX_BOOL bContinuous,FX_WORD SubWord,const CPVT_WordRange * pVisible)639 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)
640 {
641 CFX_ByteTextBuf sEditStream, sLineStream, sWords;
642 CPDF_Point ptOld(0.0f, 0.0f), ptNew(0.0f, 0.0f);
643 FX_INT32 nCurFontIndex = -1;
644 if (pIterator) {
645 if (pVisible) {
646 pIterator->SetAt(pVisible->BeginPos);
647 } else {
648 pIterator->SetAt(0);
649 }
650 CPVT_WordPlace oldplace;
651 while (pIterator->NextWord()) {
652 CPVT_WordPlace place = pIterator->GetAt();
653 if (pVisible && place.WordCmp(pVisible->EndPos) > 0) {
654 break;
655 }
656 if (bContinuous) {
657 if (place.LineCmp(oldplace) != 0) {
658 if (sWords.GetSize() > 0) {
659 sLineStream << GetWordRenderString(sWords.GetByteString());
660 sEditStream << sLineStream;
661 sLineStream.Clear();
662 sWords.Clear();
663 }
664 CPVT_Word word;
665 if (pIterator->GetWord(word)) {
666 ptNew = CPDF_Point(word.ptWord.x + ptOffset.x, word.ptWord.y + ptOffset.y);
667 } else {
668 CPVT_Line line;
669 pIterator->GetLine(line);
670 ptNew = CPDF_Point(line.ptLine.x + ptOffset.x, line.ptLine.y + ptOffset.y);
671 }
672 if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) {
673 sLineStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y << " Td\n";
674 ptOld = ptNew;
675 }
676 }
677 CPVT_Word word;
678 if (pIterator->GetWord(word)) {
679 if (word.nFontIndex != nCurFontIndex) {
680 if (sWords.GetSize() > 0) {
681 sLineStream << GetWordRenderString(sWords.GetByteString());
682 sWords.Clear();
683 }
684 sLineStream << GetFontSetString(pFontMap, word.nFontIndex, word.fFontSize);
685 nCurFontIndex = word.nFontIndex;
686 }
687 sWords << GetPDFWordString(pFontMap, nCurFontIndex, word.Word, SubWord);
688 }
689 oldplace = place;
690 } else {
691 CPVT_Word word;
692 if (pIterator->GetWord(word)) {
693 ptNew = CPDF_Point(word.ptWord.x + ptOffset.x, word.ptWord.y + ptOffset.y);
694 if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) {
695 sEditStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y << " Td\n";
696 ptOld = ptNew;
697 }
698 if (word.nFontIndex != nCurFontIndex) {
699 sEditStream << GetFontSetString(pFontMap, word.nFontIndex, word.fFontSize);
700 nCurFontIndex = word.nFontIndex;
701 }
702 sEditStream << GetWordRenderString(GetPDFWordString(pFontMap, nCurFontIndex, word.Word, SubWord));
703 }
704 }
705 }
706 if (sWords.GetSize() > 0) {
707 sLineStream << GetWordRenderString(sWords.GetByteString());
708 sEditStream << sLineStream;
709 sWords.Clear();
710 }
711 }
712 return sEditStream.GetByteString();
713 }
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)714 CFX_ByteString CPVT_GenerateAP::GenerateBorderAP(const CPDF_Rect & rect, FX_FLOAT fWidth,
715 const CPVT_Color & color, const CPVT_Color & crLeftTop, const CPVT_Color & crRightBottom,
716 FX_INT32 nStyle, const CPVT_Dash & dash)
717 {
718 CFX_ByteTextBuf sAppStream;
719 CFX_ByteString sColor;
720 FX_FLOAT fLeft = rect.left;
721 FX_FLOAT fRight = rect.right;
722 FX_FLOAT fTop = rect.top;
723 FX_FLOAT fBottom = rect.bottom;
724 if (fWidth > 0.0f) {
725 FX_FLOAT fHalfWidth = fWidth / 2.0f;
726 switch (nStyle) {
727 default:
728 case PBS_SOLID:
729 sColor = GenerateColorAP(color, TRUE);
730 if (sColor.GetLength() > 0) {
731 sAppStream << sColor;
732 sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " " << fTop - fBottom << " re\n";
733 sAppStream << fLeft + fWidth << " " << fBottom + fWidth << " "
734 << fRight - fLeft - fWidth * 2 << " " << fTop - fBottom - fWidth * 2 << " re\n";
735 sAppStream << "f*\n";
736 }
737 break;
738 case PBS_DASH:
739 sColor = GenerateColorAP(color, FALSE);
740 if (sColor.GetLength() > 0) {
741 sAppStream << sColor;
742 sAppStream << fWidth << " w" << " [" << dash.nDash << " " << dash.nGap << "] " << dash.nPhase << " d\n";
743 sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2 << " m\n";
744 sAppStream << fLeft + fWidth / 2 << " " << fTop - fWidth / 2 << " l\n";
745 sAppStream << fRight - fWidth / 2 << " " << fTop - fWidth / 2 << " l\n";
746 sAppStream << fRight - fWidth / 2 << " " << fBottom + fWidth / 2 << " l\n";
747 sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2 << " l S\n";
748 }
749 break;
750 case PBS_BEVELED:
751 case PBS_INSET:
752 sColor = GenerateColorAP(crLeftTop, TRUE);
753 if (sColor.GetLength() > 0) {
754 sAppStream << sColor;
755 sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth << " m\n";
756 sAppStream << fLeft + fHalfWidth << " " << fTop - fHalfWidth << " l\n";
757 sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth << " l\n";
758 sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 << " l\n";
759 sAppStream << fLeft + fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 << " l\n";
760 sAppStream << fLeft + fHalfWidth * 2 << " " << fBottom + fHalfWidth * 2 << " l f\n";
761 }
762 sColor = GenerateColorAP(crRightBottom, TRUE);
763 if (sColor.GetLength() > 0) {
764 sAppStream << sColor;
765 sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth << " m\n";
766 sAppStream << fRight - fHalfWidth << " " << fBottom + fHalfWidth << " l\n";
767 sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth << " l\n";
768 sAppStream << fLeft + fHalfWidth * 2 << " " << fBottom + fHalfWidth * 2 << " l\n";
769 sAppStream << fRight - fHalfWidth * 2 << " " << fBottom + fHalfWidth * 2 << " l\n";
770 sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 << " l f\n";
771 }
772 sColor = GenerateColorAP(color, TRUE);
773 if (sColor.GetLength() > 0) {
774 sAppStream << sColor;
775 sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " " << fTop - fBottom << " re\n";
776 sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth << " "
777 << fRight - fLeft - fHalfWidth * 2 << " " << fTop - fBottom - fHalfWidth * 2 << " re f*\n";
778 }
779 break;
780 case PBS_UNDERLINED:
781 sColor = GenerateColorAP(color, FALSE);
782 if (sColor.GetLength() > 0) {
783 sAppStream << sColor;
784 sAppStream << fWidth << " w\n";
785 sAppStream << fLeft << " " << fBottom + fWidth / 2 << " m\n";
786 sAppStream << fRight << " " << fBottom + fWidth / 2 << " l S\n";
787 }
788 break;
789 }
790 }
791 return sAppStream.GetByteString();
792 }
GenerateColorAP(const CPVT_Color & color,const FX_BOOL & bFillOrStroke)793 CFX_ByteString CPVT_GenerateAP::GenerateColorAP(const CPVT_Color & color, const FX_BOOL & bFillOrStroke)
794 {
795 CFX_ByteTextBuf sColorStream;
796 switch (color.nColorType) {
797 case CT_RGB:
798 sColorStream << color.fColor1 << " " << color.fColor2 << " " << color.fColor3 << " "
799 << (bFillOrStroke ? "rg" : "RG") << "\n";
800 break;
801 case CT_GRAY:
802 sColorStream << color.fColor1 << " " << (bFillOrStroke ? "g" : "G") << "\n";
803 break;
804 case CT_CMYK:
805 sColorStream << color.fColor1 << " " << color.fColor2 << " " << color.fColor3 << " " << color.fColor4 << " "
806 << (bFillOrStroke ? "k" : "K") << "\n";
807 break;
808 }
809 return sColorStream.GetByteString();
810 }
811