OLD | NEW |
| (Empty) |
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 "xfa/src/fxfa/app/xfa_ffwidget.h" | |
8 | |
9 #include <algorithm> | |
10 | |
11 #include "core/include/fpdfapi/fpdf_page.h" | |
12 #include "core/include/fxcodec/fx_codec.h" | |
13 #include "xfa/include/fxgraphics/fx_graphics.h" | |
14 #include "xfa/src/fxfa/app/xfa_ffapp.h" | |
15 #include "xfa/src/fxfa/app/xfa_ffdoc.h" | |
16 #include "xfa/src/fxfa/app/xfa_ffdocview.h" | |
17 #include "xfa/src/fxfa/app/xfa_ffpageview.h" | |
18 #include "xfa/src/fxfa/app/xfa_textlayout.h" | |
19 | |
20 CXFA_FFWidget::CXFA_FFWidget(CXFA_FFPageView* pPageView, | |
21 CXFA_WidgetAcc* pDataAcc) | |
22 : CXFA_ContentLayoutItem(pDataAcc->GetNode()), | |
23 m_pPageView(pPageView), | |
24 m_pDataAcc(pDataAcc) { | |
25 m_rtWidget.Set(0, 0, 0, 0); | |
26 } | |
27 CXFA_FFWidget::~CXFA_FFWidget() {} | |
28 IXFA_PageView* CXFA_FFWidget::GetPageView() { | |
29 return m_pPageView; | |
30 } | |
31 void CXFA_FFWidget::SetPageView(IXFA_PageView* pPageView) { | |
32 m_pPageView = static_cast<CXFA_FFPageView*>(pPageView); | |
33 } | |
34 void CXFA_FFWidget::GetWidgetRect(CFX_RectF& rtWidget) { | |
35 if ((m_dwStatus & XFA_WIDGETSTATUS_RectCached) == 0) { | |
36 m_dwStatus |= XFA_WIDGETSTATUS_RectCached; | |
37 GetRect(m_rtWidget); | |
38 } | |
39 rtWidget = m_rtWidget; | |
40 } | |
41 CFX_RectF CXFA_FFWidget::ReCacheWidgetRect() { | |
42 m_dwStatus |= XFA_WIDGETSTATUS_RectCached; | |
43 GetRect(m_rtWidget); | |
44 return m_rtWidget; | |
45 } | |
46 void CXFA_FFWidget::GetRectWithoutRotate(CFX_RectF& rtWidget) { | |
47 GetWidgetRect(rtWidget); | |
48 FX_FLOAT fValue = 0; | |
49 switch (m_pDataAcc->GetRotate()) { | |
50 case 90: | |
51 rtWidget.top = rtWidget.bottom(); | |
52 fValue = rtWidget.width; | |
53 rtWidget.width = rtWidget.height; | |
54 rtWidget.height = fValue; | |
55 break; | |
56 case 180: | |
57 rtWidget.left = rtWidget.right(); | |
58 rtWidget.top = rtWidget.bottom(); | |
59 break; | |
60 case 270: | |
61 rtWidget.left = rtWidget.right(); | |
62 fValue = rtWidget.width; | |
63 rtWidget.width = rtWidget.height; | |
64 rtWidget.height = fValue; | |
65 break; | |
66 } | |
67 } | |
68 FX_DWORD CXFA_FFWidget::GetStatus() { | |
69 return m_dwStatus; | |
70 } | |
71 | |
72 void CXFA_FFWidget::ModifyStatus(FX_DWORD dwAdded, FX_DWORD dwRemoved) { | |
73 m_dwStatus = (m_dwStatus & ~dwRemoved) | dwAdded; | |
74 } | |
75 | |
76 FX_BOOL CXFA_FFWidget::GetBBox(CFX_RectF& rtBox, | |
77 FX_DWORD dwStatus, | |
78 FX_BOOL bDrawFocus) { | |
79 if (bDrawFocus) | |
80 return FALSE; | |
81 if (m_pPageView) | |
82 m_pPageView->GetPageViewRect(rtBox); | |
83 return TRUE; | |
84 } | |
85 | |
86 CXFA_WidgetAcc* CXFA_FFWidget::GetDataAcc() { | |
87 return m_pDataAcc; | |
88 } | |
89 FX_BOOL CXFA_FFWidget::GetToolTip(CFX_WideString& wsToolTip) { | |
90 if (CXFA_Assist assist = m_pDataAcc->GetAssist()) { | |
91 if (CXFA_ToolTip toolTip = assist.GetToolTip()) { | |
92 return toolTip.GetTip(wsToolTip); | |
93 } | |
94 } | |
95 return GetCaptionText(wsToolTip); | |
96 } | |
97 void CXFA_FFWidget::RenderWidget(CFX_Graphics* pGS, | |
98 CFX_Matrix* pMatrix, | |
99 FX_DWORD dwStatus, | |
100 int32_t iRotate) { | |
101 if (!IsMatchVisibleStatus(dwStatus)) { | |
102 return; | |
103 } | |
104 CXFA_Border border = m_pDataAcc->GetBorder(); | |
105 if (border) { | |
106 CFX_RectF rtBorder; | |
107 GetRectWithoutRotate(rtBorder); | |
108 CXFA_Margin margin = border.GetMargin(); | |
109 if (margin) { | |
110 XFA_RectWidthoutMargin(rtBorder, margin); | |
111 } | |
112 rtBorder.Normalize(); | |
113 DrawBorder(pGS, border, rtBorder, pMatrix); | |
114 } | |
115 } | |
116 FX_BOOL CXFA_FFWidget::IsLoaded() { | |
117 return m_pPageView != NULL; | |
118 } | |
119 FX_BOOL CXFA_FFWidget::LoadWidget() { | |
120 PerformLayout(); | |
121 return TRUE; | |
122 } | |
123 void CXFA_FFWidget::UnloadWidget() {} | |
124 FX_BOOL CXFA_FFWidget::PerformLayout() { | |
125 ReCacheWidgetRect(); | |
126 return TRUE; | |
127 } | |
128 FX_BOOL CXFA_FFWidget::UpdateFWLData() { | |
129 return FALSE; | |
130 } | |
131 void CXFA_FFWidget::UpdateWidgetProperty() {} | |
132 void CXFA_FFWidget::DrawBorder(CFX_Graphics* pGS, | |
133 CXFA_Box box, | |
134 const CFX_RectF& rtBorder, | |
135 CFX_Matrix* pMatrix, | |
136 FX_DWORD dwFlags) { | |
137 XFA_DrawBox(box, pGS, rtBorder, pMatrix, dwFlags); | |
138 } | |
139 void CXFA_FFWidget::InvalidateWidget(const CFX_RectF* pRect) { | |
140 if (!pRect) { | |
141 CFX_RectF rtWidget; | |
142 GetBBox(rtWidget, XFA_WIDGETSTATUS_Focused); | |
143 rtWidget.Inflate(2, 2); | |
144 GetDoc()->GetDocProvider()->InvalidateRect(m_pPageView, rtWidget, | |
145 XFA_INVALIDATE_CurrentPage); | |
146 } else { | |
147 GetDoc()->GetDocProvider()->InvalidateRect(m_pPageView, *pRect, | |
148 XFA_INVALIDATE_CurrentPage); | |
149 } | |
150 } | |
151 void CXFA_FFWidget::AddInvalidateRect(const CFX_RectF* pRect) { | |
152 CFX_RectF rtWidget; | |
153 if (pRect) { | |
154 rtWidget = *pRect; | |
155 } else { | |
156 GetBBox(rtWidget, XFA_WIDGETSTATUS_Focused); | |
157 rtWidget.Inflate(2, 2); | |
158 } | |
159 m_pDocView->AddInvalidateRect(m_pPageView, rtWidget); | |
160 } | |
161 FX_BOOL CXFA_FFWidget::GetCaptionText(CFX_WideString& wsCap) { | |
162 CXFA_TextLayout* pCapTextlayout = m_pDataAcc->GetCaptionTextLayout(); | |
163 if (!pCapTextlayout) { | |
164 return FALSE; | |
165 } | |
166 pCapTextlayout->GetText(wsCap); | |
167 return TRUE; | |
168 } | |
169 FX_BOOL CXFA_FFWidget::IsFocused() { | |
170 return m_dwStatus & XFA_WIDGETSTATUS_Focused; | |
171 } | |
172 FX_BOOL CXFA_FFWidget::OnMouseEnter() { | |
173 return FALSE; | |
174 } | |
175 FX_BOOL CXFA_FFWidget::OnMouseExit() { | |
176 return FALSE; | |
177 } | |
178 FX_BOOL CXFA_FFWidget::OnLButtonDown(FX_DWORD dwFlags, | |
179 FX_FLOAT fx, | |
180 FX_FLOAT fy) { | |
181 return FALSE; | |
182 } | |
183 FX_BOOL CXFA_FFWidget::OnLButtonUp(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) { | |
184 return FALSE; | |
185 } | |
186 FX_BOOL CXFA_FFWidget::OnLButtonDblClk(FX_DWORD dwFlags, | |
187 FX_FLOAT fx, | |
188 FX_FLOAT fy) { | |
189 return FALSE; | |
190 } | |
191 FX_BOOL CXFA_FFWidget::OnMouseMove(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) { | |
192 return FALSE; | |
193 } | |
194 FX_BOOL CXFA_FFWidget::OnMouseWheel(FX_DWORD dwFlags, | |
195 int16_t zDelta, | |
196 FX_FLOAT fx, | |
197 FX_FLOAT fy) { | |
198 return FALSE; | |
199 } | |
200 FX_BOOL CXFA_FFWidget::OnRButtonDown(FX_DWORD dwFlags, | |
201 FX_FLOAT fx, | |
202 FX_FLOAT fy) { | |
203 return FALSE; | |
204 } | |
205 FX_BOOL CXFA_FFWidget::OnRButtonUp(FX_DWORD dwFlags, FX_FLOAT fx, FX_FLOAT fy) { | |
206 return FALSE; | |
207 } | |
208 FX_BOOL CXFA_FFWidget::OnRButtonDblClk(FX_DWORD dwFlags, | |
209 FX_FLOAT fx, | |
210 FX_FLOAT fy) { | |
211 return FALSE; | |
212 } | |
213 | |
214 FX_BOOL CXFA_FFWidget::OnSetFocus(CXFA_FFWidget* pOldWidget) { | |
215 CXFA_FFWidget* pParent = GetParent(); | |
216 if (pParent && !pParent->IsAncestorOf(pOldWidget)) { | |
217 pParent->OnSetFocus(pOldWidget); | |
218 } | |
219 m_dwStatus |= XFA_WIDGETSTATUS_Focused; | |
220 CXFA_EventParam eParam; | |
221 eParam.m_eType = XFA_EVENT_Enter; | |
222 eParam.m_pTarget = m_pDataAcc; | |
223 m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Enter, &eParam); | |
224 return TRUE; | |
225 } | |
226 FX_BOOL CXFA_FFWidget::OnKillFocus(CXFA_FFWidget* pNewWidget) { | |
227 m_dwStatus &= ~XFA_WIDGETSTATUS_Focused; | |
228 EventKillFocus(); | |
229 if (pNewWidget) { | |
230 CXFA_FFWidget* pParent = GetParent(); | |
231 if (pParent && !pParent->IsAncestorOf(pNewWidget)) { | |
232 pParent->OnKillFocus(pNewWidget); | |
233 } | |
234 } | |
235 return TRUE; | |
236 } | |
237 FX_BOOL CXFA_FFWidget::OnKeyDown(FX_DWORD dwKeyCode, FX_DWORD dwFlags) { | |
238 return FALSE; | |
239 } | |
240 FX_BOOL CXFA_FFWidget::OnKeyUp(FX_DWORD dwKeyCode, FX_DWORD dwFlags) { | |
241 return FALSE; | |
242 } | |
243 FX_BOOL CXFA_FFWidget::OnChar(FX_DWORD dwChar, FX_DWORD dwFlags) { | |
244 return FALSE; | |
245 } | |
246 FX_DWORD CXFA_FFWidget::OnHitTest(FX_FLOAT fx, FX_FLOAT fy) { | |
247 return FALSE; | |
248 } | |
249 FX_BOOL CXFA_FFWidget::OnSetCursor(FX_FLOAT fx, FX_FLOAT fy) { | |
250 return FALSE; | |
251 } | |
252 void CXFA_FFWidget::Rotate2Normal(FX_FLOAT& fx, FX_FLOAT& fy) { | |
253 CFX_Matrix mt; | |
254 GetRotateMatrix(mt); | |
255 if (mt.IsIdentity()) { | |
256 return; | |
257 } | |
258 CFX_Matrix mtReverse; | |
259 mtReverse.SetReverse(mt); | |
260 mtReverse.TransformPoint(fx, fy); | |
261 } | |
262 static void XFA_GetMatrix(CFX_Matrix& m, | |
263 int32_t iRotate, | |
264 int32_t at, | |
265 const CFX_RectF& rt) { | |
266 if (!iRotate) { | |
267 return; | |
268 } | |
269 FX_FLOAT fAnchorX, fAnchorY; | |
270 switch (at) { | |
271 case XFA_ATTRIBUTEENUM_TopLeft: | |
272 fAnchorX = rt.left, fAnchorY = rt.top; | |
273 break; | |
274 case XFA_ATTRIBUTEENUM_TopCenter: | |
275 fAnchorX = (rt.left + rt.right()) / 2, fAnchorY = rt.top; | |
276 break; | |
277 case XFA_ATTRIBUTEENUM_TopRight: | |
278 fAnchorX = rt.right(), fAnchorY = rt.top; | |
279 break; | |
280 case XFA_ATTRIBUTEENUM_MiddleLeft: | |
281 fAnchorX = rt.left, fAnchorY = (rt.top + rt.bottom()) / 2; | |
282 break; | |
283 case XFA_ATTRIBUTEENUM_MiddleCenter: | |
284 fAnchorX = (rt.left + rt.right()) / 2, | |
285 fAnchorY = (rt.top + rt.bottom()) / 2; | |
286 break; | |
287 case XFA_ATTRIBUTEENUM_MiddleRight: | |
288 fAnchorX = rt.right(), fAnchorY = (rt.top + rt.bottom()) / 2; | |
289 break; | |
290 case XFA_ATTRIBUTEENUM_BottomLeft: | |
291 fAnchorX = rt.left, fAnchorY = rt.bottom(); | |
292 break; | |
293 case XFA_ATTRIBUTEENUM_BottomCenter: | |
294 fAnchorX = (rt.left + rt.right()) / 2, fAnchorY = rt.bottom(); | |
295 break; | |
296 case XFA_ATTRIBUTEENUM_BottomRight: | |
297 fAnchorX = rt.right(), fAnchorY = rt.bottom(); | |
298 break; | |
299 } | |
300 switch (iRotate) { | |
301 case 90: | |
302 m.a = 0, m.b = -1, m.c = 1, m.d = 0, m.e = fAnchorX - fAnchorY, | |
303 m.f = fAnchorX + fAnchorY; | |
304 break; | |
305 case 180: | |
306 m.a = -1, m.b = 0, m.c = 0, m.d = -1, m.e = fAnchorX * 2, | |
307 m.f = fAnchorY * 2; | |
308 break; | |
309 case 270: | |
310 m.a = 0, m.b = 1, m.c = -1, m.d = 0, m.e = fAnchorX + fAnchorY, | |
311 m.f = fAnchorY - fAnchorX; | |
312 break; | |
313 } | |
314 } | |
315 void CXFA_FFWidget::GetRotateMatrix(CFX_Matrix& mt) { | |
316 mt.Set(1, 0, 0, 1, 0, 0); | |
317 int32_t iRotate = m_pDataAcc->GetRotate(); | |
318 if (!iRotate) { | |
319 return; | |
320 } | |
321 CFX_RectF rcWidget; | |
322 GetRectWithoutRotate(rcWidget); | |
323 XFA_ATTRIBUTEENUM at = XFA_ATTRIBUTEENUM_TopLeft; | |
324 XFA_GetMatrix(mt, iRotate, at, rcWidget); | |
325 } | |
326 FX_BOOL CXFA_FFWidget::IsLayoutRectEmpty() { | |
327 CFX_RectF rtLayout; | |
328 GetRectWithoutRotate(rtLayout); | |
329 return rtLayout.width < 0.1f && rtLayout.height < 0.1f; | |
330 } | |
331 CXFA_FFWidget* CXFA_FFWidget::GetParent() { | |
332 CXFA_Node* pParentNode = | |
333 m_pDataAcc->GetNode()->GetNodeItem(XFA_NODEITEM_Parent); | |
334 if (pParentNode) { | |
335 CXFA_WidgetAcc* pParentWidgetAcc = | |
336 (CXFA_WidgetAcc*)pParentNode->GetWidgetData(); | |
337 if (pParentWidgetAcc) { | |
338 return pParentWidgetAcc->GetNextWidget(NULL); | |
339 } | |
340 } | |
341 return NULL; | |
342 } | |
343 FX_BOOL CXFA_FFWidget::IsAncestorOf(CXFA_FFWidget* pWidget) { | |
344 if (!pWidget) { | |
345 return FALSE; | |
346 } | |
347 CXFA_Node* pNode = m_pDataAcc->GetNode(); | |
348 CXFA_Node* pChildNode = pWidget->GetDataAcc()->GetNode(); | |
349 while (pChildNode) { | |
350 if (pChildNode == pNode) { | |
351 return TRUE; | |
352 } | |
353 pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_Parent); | |
354 } | |
355 return FALSE; | |
356 } | |
357 FX_BOOL CXFA_FFWidget::PtInActiveRect(FX_FLOAT fx, FX_FLOAT fy) { | |
358 CFX_RectF rtWidget; | |
359 GetWidgetRect(rtWidget); | |
360 if (rtWidget.Contains(fx, fy)) { | |
361 return TRUE; | |
362 } | |
363 return FALSE; | |
364 } | |
365 CXFA_FFDocView* CXFA_FFWidget::GetDocView() { | |
366 return m_pDocView; | |
367 } | |
368 CXFA_FFDoc* CXFA_FFWidget::GetDoc() { | |
369 return (CXFA_FFDoc*)m_pDocView->GetDoc(); | |
370 } | |
371 CXFA_FFApp* CXFA_FFWidget::GetApp() { | |
372 return GetDoc()->GetApp(); | |
373 } | |
374 IXFA_AppProvider* CXFA_FFWidget::GetAppProvider() { | |
375 return GetApp()->GetAppProvider(); | |
376 } | |
377 void CXFA_FFWidget::GetMinMaxWidth(FX_FLOAT fMinWidth, FX_FLOAT fMaxWidth) { | |
378 fMinWidth = fMaxWidth = 0; | |
379 FX_FLOAT fWidth = 0; | |
380 if (m_pDataAcc->GetWidth(fWidth)) { | |
381 fMinWidth = fMaxWidth = fWidth; | |
382 } else { | |
383 m_pDataAcc->GetMinWidth(fMinWidth); | |
384 m_pDataAcc->GetMaxWidth(fMaxWidth); | |
385 } | |
386 } | |
387 void CXFA_FFWidget::GetMinMaxHeight(FX_FLOAT fMinHeight, FX_FLOAT fMaxHeight) { | |
388 fMinHeight = fMaxHeight = 0; | |
389 FX_FLOAT fHeight = 0; | |
390 if (m_pDataAcc->GetHeight(fHeight)) { | |
391 fMinHeight = fMaxHeight = fHeight; | |
392 } else { | |
393 m_pDataAcc->GetMinHeight(fMinHeight); | |
394 m_pDataAcc->GetMaxHeight(fMaxHeight); | |
395 } | |
396 } | |
397 FX_BOOL CXFA_FFWidget::IsMatchVisibleStatus(FX_DWORD dwStatus) { | |
398 return m_dwStatus & XFA_WIDGETSTATUS_Visible; | |
399 } | |
400 void CXFA_FFWidget::EventKillFocus() { | |
401 if (m_dwStatus & XFA_WIDGETSTATUS_Access) { | |
402 m_dwStatus &= ~XFA_WIDGETSTATUS_Access; | |
403 return; | |
404 } | |
405 CXFA_EventParam eParam; | |
406 eParam.m_eType = XFA_EVENT_Exit; | |
407 eParam.m_pTarget = m_pDataAcc; | |
408 m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Exit, &eParam); | |
409 } | |
410 FX_BOOL CXFA_FFWidget::IsButtonDown() { | |
411 return (m_dwStatus & XFA_WIDGETSTATUS_ButtonDown) != 0; | |
412 } | |
413 void CXFA_FFWidget::SetButtonDown(FX_BOOL bSet) { | |
414 bSet ? m_dwStatus |= XFA_WIDGETSTATUS_ButtonDown | |
415 : m_dwStatus &= ~XFA_WIDGETSTATUS_ButtonDown; | |
416 } | |
417 int32_t XFA_StrokeTypeSetLineDash(CFX_Graphics* pGraphics, | |
418 int32_t iStrokeType, | |
419 int32_t iCapType) { | |
420 switch (iStrokeType) { | |
421 case XFA_ATTRIBUTEENUM_DashDot: { | |
422 FX_FLOAT dashArray[] = {4, 1, 2, 1}; | |
423 if (iCapType != XFA_ATTRIBUTEENUM_Butt) { | |
424 dashArray[1] = 2; | |
425 dashArray[3] = 2; | |
426 } | |
427 pGraphics->SetLineDash(0, dashArray, 4); | |
428 return FX_DASHSTYLE_DashDot; | |
429 } | |
430 case XFA_ATTRIBUTEENUM_DashDotDot: { | |
431 FX_FLOAT dashArray[] = {4, 1, 2, 1, 2, 1}; | |
432 if (iCapType != XFA_ATTRIBUTEENUM_Butt) { | |
433 dashArray[1] = 2; | |
434 dashArray[3] = 2; | |
435 dashArray[5] = 2; | |
436 } | |
437 pGraphics->SetLineDash(0, dashArray, 6); | |
438 return FX_DASHSTYLE_DashDotDot; | |
439 } | |
440 case XFA_ATTRIBUTEENUM_Dashed: { | |
441 FX_FLOAT dashArray[] = {5, 1}; | |
442 if (iCapType != XFA_ATTRIBUTEENUM_Butt) { | |
443 dashArray[1] = 2; | |
444 } | |
445 pGraphics->SetLineDash(0, dashArray, 2); | |
446 return FX_DASHSTYLE_Dash; | |
447 } | |
448 case XFA_ATTRIBUTEENUM_Dotted: { | |
449 FX_FLOAT dashArray[] = {2, 1}; | |
450 if (iCapType != XFA_ATTRIBUTEENUM_Butt) { | |
451 dashArray[1] = 2; | |
452 } | |
453 pGraphics->SetLineDash(0, dashArray, 2); | |
454 return FX_DASHSTYLE_Dot; | |
455 } | |
456 default: | |
457 break; | |
458 } | |
459 pGraphics->SetLineDash(FX_DASHSTYLE_Solid); | |
460 return FX_DASHSTYLE_Solid; | |
461 } | |
462 CFX_GraphStateData::LineCap XFA_LineCapToFXGE(int32_t iLineCap) { | |
463 switch (iLineCap) { | |
464 case XFA_ATTRIBUTEENUM_Round: | |
465 return CFX_GraphStateData::LineCapRound; | |
466 case XFA_ATTRIBUTEENUM_Butt: | |
467 return CFX_GraphStateData::LineCapButt; | |
468 default: | |
469 break; | |
470 } | |
471 return CFX_GraphStateData::LineCapSquare; | |
472 } | |
473 class CXFA_ImageRenderer { | |
474 public: | |
475 CXFA_ImageRenderer(); | |
476 ~CXFA_ImageRenderer(); | |
477 FX_BOOL Start(CFX_RenderDevice* pDevice, | |
478 CFX_DIBSource* pDIBSource, | |
479 FX_ARGB bitmap_argb, | |
480 int bitmap_alpha, | |
481 const CFX_Matrix* pImage2Device, | |
482 FX_DWORD flags, | |
483 int blendType = FXDIB_BLEND_NORMAL); | |
484 FX_BOOL Continue(IFX_Pause* pPause); | |
485 | |
486 protected: | |
487 CFX_RenderDevice* m_pDevice; | |
488 int m_Status; | |
489 CFX_Matrix m_ImageMatrix; | |
490 CFX_DIBSource* m_pDIBSource; | |
491 CFX_DIBitmap* m_pCloneConvert; | |
492 int m_BitmapAlpha; | |
493 FX_ARGB m_FillArgb; | |
494 FX_DWORD m_Flags; | |
495 CFX_ImageTransformer* m_pTransformer; | |
496 void* m_DeviceHandle; | |
497 int32_t m_BlendType; | |
498 FX_BOOL m_Result; | |
499 FX_BOOL m_bPrint; | |
500 FX_BOOL StartDIBSource(); | |
501 void CompositeDIBitmap(CFX_DIBitmap* pDIBitmap, | |
502 int left, | |
503 int top, | |
504 FX_ARGB mask_argb, | |
505 int bitmap_alpha, | |
506 int blend_mode, | |
507 int Transparency); | |
508 }; | |
509 CXFA_ImageRenderer::CXFA_ImageRenderer() { | |
510 m_pDevice = NULL; | |
511 m_Status = 0; | |
512 m_pDIBSource = NULL; | |
513 m_pCloneConvert = NULL; | |
514 m_BitmapAlpha = 255; | |
515 m_FillArgb = 0; | |
516 m_Flags = 0; | |
517 m_pTransformer = NULL; | |
518 m_DeviceHandle = NULL; | |
519 m_BlendType = FXDIB_BLEND_NORMAL; | |
520 m_Result = TRUE; | |
521 m_bPrint = FALSE; | |
522 } | |
523 CXFA_ImageRenderer::~CXFA_ImageRenderer() { | |
524 if (m_pCloneConvert) { | |
525 delete m_pCloneConvert; | |
526 } | |
527 if (m_pTransformer) { | |
528 delete m_pTransformer; | |
529 } | |
530 if (m_DeviceHandle) { | |
531 m_pDevice->CancelDIBits(m_DeviceHandle); | |
532 } | |
533 } | |
534 FX_BOOL CXFA_ImageRenderer::Start(CFX_RenderDevice* pDevice, | |
535 CFX_DIBSource* pDIBSource, | |
536 FX_ARGB bitmap_argb, | |
537 int bitmap_alpha, | |
538 const CFX_Matrix* pImage2Device, | |
539 FX_DWORD flags, | |
540 int blendType) { | |
541 m_pDevice = pDevice; | |
542 m_pDIBSource = pDIBSource; | |
543 m_FillArgb = bitmap_argb; | |
544 m_BitmapAlpha = bitmap_alpha; | |
545 m_ImageMatrix = *pImage2Device; | |
546 m_Flags = flags; | |
547 m_BlendType = blendType; | |
548 return StartDIBSource(); | |
549 } | |
550 FX_BOOL CXFA_ImageRenderer::StartDIBSource() { | |
551 if (m_pDevice->StartDIBits(m_pDIBSource, m_BitmapAlpha, m_FillArgb, | |
552 &m_ImageMatrix, m_Flags, m_DeviceHandle, 0, NULL, | |
553 m_BlendType)) { | |
554 if (m_DeviceHandle) { | |
555 m_Status = 3; | |
556 return TRUE; | |
557 } | |
558 return FALSE; | |
559 } | |
560 CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect(); | |
561 FX_RECT image_rect = image_rect_f.GetOutterRect(); | |
562 int dest_width = image_rect.Width(); | |
563 int dest_height = image_rect.Height(); | |
564 if ((FXSYS_fabs(m_ImageMatrix.b) >= 0.5f || m_ImageMatrix.a == 0) || | |
565 (FXSYS_fabs(m_ImageMatrix.c) >= 0.5f || m_ImageMatrix.d == 0)) { | |
566 if (m_bPrint && !(m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { | |
567 m_Result = FALSE; | |
568 return FALSE; | |
569 } | |
570 CFX_DIBSource* pDib = m_pDIBSource; | |
571 if (m_pDIBSource->HasAlpha() && | |
572 !(m_pDevice->GetRenderCaps() & FXRC_ALPHA_IMAGE) && | |
573 !(m_pDevice->GetRenderCaps() & FXRC_GET_BITS)) { | |
574 m_pCloneConvert = m_pDIBSource->CloneConvert(FXDIB_Rgb); | |
575 if (!m_pCloneConvert) { | |
576 m_Result = FALSE; | |
577 return FALSE; | |
578 } | |
579 pDib = m_pCloneConvert; | |
580 } | |
581 FX_RECT clip_box = m_pDevice->GetClipBox(); | |
582 clip_box.Intersect(image_rect); | |
583 m_Status = 2; | |
584 m_pTransformer = new CFX_ImageTransformer; | |
585 m_pTransformer->Start(pDib, &m_ImageMatrix, m_Flags, &clip_box); | |
586 return TRUE; | |
587 } | |
588 if (m_ImageMatrix.a < 0) { | |
589 dest_width = -dest_width; | |
590 } | |
591 if (m_ImageMatrix.d > 0) { | |
592 dest_height = -dest_height; | |
593 } | |
594 int dest_left, dest_top; | |
595 dest_left = dest_width > 0 ? image_rect.left : image_rect.right; | |
596 dest_top = dest_height > 0 ? image_rect.top : image_rect.bottom; | |
597 if (m_pDIBSource->IsOpaqueImage() && m_BitmapAlpha == 255) { | |
598 if (m_pDevice->StretchDIBits(m_pDIBSource, dest_left, dest_top, dest_width, | |
599 dest_height, m_Flags, NULL, m_BlendType)) { | |
600 return FALSE; | |
601 } | |
602 } | |
603 if (m_pDIBSource->IsAlphaMask()) { | |
604 if (m_BitmapAlpha != 255) { | |
605 m_FillArgb = FXARGB_MUL_ALPHA(m_FillArgb, m_BitmapAlpha); | |
606 } | |
607 if (m_pDevice->StretchBitMask(m_pDIBSource, dest_left, dest_top, dest_width, | |
608 dest_height, m_FillArgb, m_Flags)) { | |
609 return FALSE; | |
610 } | |
611 } | |
612 if (m_bPrint && !(m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { | |
613 m_Result = FALSE; | |
614 return TRUE; | |
615 } | |
616 FX_RECT clip_box = m_pDevice->GetClipBox(); | |
617 FX_RECT dest_rect = clip_box; | |
618 dest_rect.Intersect(image_rect); | |
619 FX_RECT dest_clip( | |
620 dest_rect.left - image_rect.left, dest_rect.top - image_rect.top, | |
621 dest_rect.right - image_rect.left, dest_rect.bottom - image_rect.top); | |
622 CFX_DIBitmap* pStretched = | |
623 m_pDIBSource->StretchTo(dest_width, dest_height, m_Flags, &dest_clip); | |
624 if (pStretched) { | |
625 CompositeDIBitmap(pStretched, dest_rect.left, dest_rect.top, m_FillArgb, | |
626 m_BitmapAlpha, m_BlendType, FALSE); | |
627 delete pStretched; | |
628 pStretched = NULL; | |
629 } | |
630 return FALSE; | |
631 } | |
632 FX_BOOL CXFA_ImageRenderer::Continue(IFX_Pause* pPause) { | |
633 if (m_Status == 2) { | |
634 if (m_pTransformer->Continue(pPause)) { | |
635 return TRUE; | |
636 } | |
637 CFX_DIBitmap* pBitmap = m_pTransformer->m_Storer.Detach(); | |
638 if (pBitmap == NULL) { | |
639 return FALSE; | |
640 } | |
641 if (pBitmap->IsAlphaMask()) { | |
642 if (m_BitmapAlpha != 255) { | |
643 m_FillArgb = FXARGB_MUL_ALPHA(m_FillArgb, m_BitmapAlpha); | |
644 } | |
645 m_Result = m_pDevice->SetBitMask(pBitmap, m_pTransformer->m_ResultLeft, | |
646 m_pTransformer->m_ResultTop, m_FillArgb); | |
647 } else { | |
648 if (m_BitmapAlpha != 255) { | |
649 pBitmap->MultiplyAlpha(m_BitmapAlpha); | |
650 } | |
651 m_Result = m_pDevice->SetDIBits(pBitmap, m_pTransformer->m_ResultLeft, | |
652 m_pTransformer->m_ResultTop, m_BlendType); | |
653 } | |
654 delete pBitmap; | |
655 return FALSE; | |
656 } else if (m_Status == 3) { | |
657 return m_pDevice->ContinueDIBits(m_DeviceHandle, pPause); | |
658 } | |
659 return FALSE; | |
660 } | |
661 void CXFA_ImageRenderer::CompositeDIBitmap(CFX_DIBitmap* pDIBitmap, | |
662 int left, | |
663 int top, | |
664 FX_ARGB mask_argb, | |
665 int bitmap_alpha, | |
666 int blend_mode, | |
667 int Transparency) { | |
668 if (pDIBitmap == NULL) { | |
669 return; | |
670 } | |
671 FX_BOOL bIsolated = Transparency & PDFTRANS_ISOLATED; | |
672 FX_BOOL bGroup = Transparency & PDFTRANS_GROUP; | |
673 if (blend_mode == FXDIB_BLEND_NORMAL) { | |
674 if (!pDIBitmap->IsAlphaMask()) { | |
675 if (bitmap_alpha < 255) { | |
676 pDIBitmap->MultiplyAlpha(bitmap_alpha); | |
677 } | |
678 if (m_pDevice->SetDIBits(pDIBitmap, left, top)) { | |
679 return; | |
680 } | |
681 } else { | |
682 FX_DWORD fill_argb = (mask_argb); | |
683 if (bitmap_alpha < 255) { | |
684 ((uint8_t*)&fill_argb)[3] = | |
685 ((uint8_t*)&fill_argb)[3] * bitmap_alpha / 255; | |
686 } | |
687 if (m_pDevice->SetBitMask(pDIBitmap, left, top, fill_argb)) { | |
688 return; | |
689 } | |
690 } | |
691 } | |
692 FX_BOOL bBackAlphaRequired = blend_mode && bIsolated; | |
693 FX_BOOL bGetBackGround = | |
694 ((m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT)) || | |
695 (!(m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT) && | |
696 (m_pDevice->GetRenderCaps() & FXRC_GET_BITS) && !bBackAlphaRequired); | |
697 if (bGetBackGround) { | |
698 if (bIsolated || !bGroup) { | |
699 if (pDIBitmap->IsAlphaMask()) { | |
700 return; | |
701 } | |
702 m_pDevice->SetDIBits(pDIBitmap, left, top, blend_mode); | |
703 } else { | |
704 FX_RECT rect(left, top, left + pDIBitmap->GetWidth(), | |
705 top + pDIBitmap->GetHeight()); | |
706 rect.Intersect(m_pDevice->GetClipBox()); | |
707 CFX_DIBitmap* pClone = NULL; | |
708 FX_BOOL bClone = FALSE; | |
709 if (m_pDevice->GetBackDrop() && m_pDevice->GetBitmap()) { | |
710 bClone = TRUE; | |
711 pClone = m_pDevice->GetBackDrop()->Clone(&rect); | |
712 CFX_DIBitmap* pForeBitmap = m_pDevice->GetBitmap(); | |
713 pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(), | |
714 pForeBitmap, rect.left, rect.top); | |
715 left = left >= 0 ? 0 : left; | |
716 top = top >= 0 ? 0 : top; | |
717 if (!pDIBitmap->IsAlphaMask()) | |
718 pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(), | |
719 pDIBitmap, left, top, blend_mode); | |
720 else | |
721 pClone->CompositeMask(0, 0, pClone->GetWidth(), pClone->GetHeight(), | |
722 pDIBitmap, mask_argb, left, top, blend_mode); | |
723 } else { | |
724 pClone = pDIBitmap; | |
725 } | |
726 if (m_pDevice->GetBackDrop()) { | |
727 m_pDevice->SetDIBits(pClone, rect.left, rect.top); | |
728 } else { | |
729 if (pDIBitmap->IsAlphaMask()) { | |
730 return; | |
731 } | |
732 m_pDevice->SetDIBits(pDIBitmap, rect.left, rect.top, blend_mode); | |
733 } | |
734 if (bClone) { | |
735 delete pClone; | |
736 } | |
737 } | |
738 return; | |
739 } | |
740 if (pDIBitmap->HasAlpha() && | |
741 !(m_pDevice->GetRenderCaps() & FXRC_ALPHA_IMAGE)) { | |
742 CFX_DIBitmap* pCloneConvert = pDIBitmap->CloneConvert(FXDIB_Rgb); | |
743 if (!pCloneConvert) { | |
744 return; | |
745 } | |
746 CXFA_ImageRenderer imageRender; | |
747 FX_BOOL bRet = imageRender.Start(m_pDevice, pCloneConvert, m_FillArgb, | |
748 m_BitmapAlpha, &m_ImageMatrix, m_Flags); | |
749 while (bRet) { | |
750 bRet = imageRender.Continue(NULL); | |
751 } | |
752 delete pCloneConvert; | |
753 return; | |
754 } | |
755 } | |
756 void XFA_DrawImage(CFX_Graphics* pGS, | |
757 const CFX_RectF& rtImage, | |
758 CFX_Matrix* pMatrix, | |
759 CFX_DIBitmap* pDIBitmap, | |
760 int32_t iAspect, | |
761 int32_t iImageXDpi, | |
762 int32_t iImageYDpi, | |
763 int32_t iHorzAlign, | |
764 int32_t iVertAlign) { | |
765 if (rtImage.IsEmpty()) { | |
766 return; | |
767 } | |
768 if (!pDIBitmap || !pDIBitmap->GetBuffer()) { | |
769 return; | |
770 } | |
771 FX_FLOAT fWidth = | |
772 XFA_UnitPx2Pt((FX_FLOAT)pDIBitmap->GetWidth(), (FX_FLOAT)iImageXDpi); | |
773 FX_FLOAT fHeight = | |
774 XFA_UnitPx2Pt((FX_FLOAT)pDIBitmap->GetHeight(), (FX_FLOAT)iImageYDpi); | |
775 CFX_RectF rtFit; | |
776 rtFit.Set(rtImage.left, rtImage.top, fWidth, fHeight); | |
777 switch (iAspect) { | |
778 case XFA_ATTRIBUTEENUM_Fit: { | |
779 FX_FLOAT f1 = rtImage.height / rtFit.height; | |
780 FX_FLOAT f2 = rtImage.width / rtFit.width; | |
781 f1 = std::min(f1, f2); | |
782 rtFit.height = rtFit.height * f1; | |
783 rtFit.width = rtFit.width * f1; | |
784 } break; | |
785 case XFA_ATTRIBUTEENUM_Actual: | |
786 break; | |
787 case XFA_ATTRIBUTEENUM_Height: { | |
788 FX_FLOAT f1 = rtImage.height / rtFit.height; | |
789 rtFit.height = rtImage.height; | |
790 rtFit.width = f1 * rtFit.width; | |
791 } break; | |
792 case XFA_ATTRIBUTEENUM_None: | |
793 rtFit.height = rtImage.height; | |
794 rtFit.width = rtImage.width; | |
795 break; | |
796 case XFA_ATTRIBUTEENUM_Width: { | |
797 FX_FLOAT f1 = rtImage.width / rtFit.width; | |
798 rtFit.width = rtImage.width; | |
799 rtFit.height = rtFit.height * f1; | |
800 } break; | |
801 } | |
802 if (iHorzAlign == XFA_ATTRIBUTEENUM_Center) { | |
803 rtFit.left += (rtImage.width - rtFit.width) / 2; | |
804 } else if (iHorzAlign == XFA_ATTRIBUTEENUM_Right) { | |
805 rtFit.left = rtImage.right() - rtFit.width; | |
806 } | |
807 if (iVertAlign == XFA_ATTRIBUTEENUM_Middle) { | |
808 rtFit.top += (rtImage.height - rtFit.height) / 2; | |
809 } else if (iVertAlign == XFA_ATTRIBUTEENUM_Bottom) { | |
810 rtFit.top = rtImage.bottom() - rtImage.height; | |
811 } | |
812 CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice(); | |
813 pRenderDevice->SaveState(); | |
814 CFX_PathData path; | |
815 path.AppendRect(rtImage.left, rtImage.bottom(), rtImage.right(), rtImage.top); | |
816 pRenderDevice->SetClip_PathFill(&path, pMatrix, FXFILL_WINDING); | |
817 CFX_Matrix mtImage(1, 0, 0, -1, 0, 1); | |
818 mtImage.Concat(rtFit.width, 0, 0, rtFit.height, rtFit.left, rtFit.top); | |
819 mtImage.Concat(*pMatrix); | |
820 CXFA_ImageRenderer imageRender; | |
821 FX_BOOL bRet = imageRender.Start(pRenderDevice, pDIBitmap, 0, 255, &mtImage, | |
822 FXDIB_INTERPOL); | |
823 while (bRet) { | |
824 bRet = imageRender.Continue(NULL); | |
825 } | |
826 pRenderDevice->RestoreState(); | |
827 } | |
828 | |
829 static const uint8_t g_inv_base64[128] = { | |
830 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | |
831 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | |
832 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, | |
833 255, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, | |
834 255, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, | |
835 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, | |
836 25, 255, 255, 255, 255, 255, 255, 26, 27, 28, 29, 30, 31, 32, 33, | |
837 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, | |
838 49, 50, 51, 255, 255, 255, 255, 255, | |
839 }; | |
840 | |
841 static uint8_t* XFA_RemoveBase64Whitespace(const uint8_t* pStr, int32_t iLen) { | |
842 uint8_t* pCP; | |
843 int32_t i = 0, j = 0; | |
844 if (iLen == 0) { | |
845 iLen = FXSYS_strlen((FX_CHAR*)pStr); | |
846 } | |
847 pCP = FX_Alloc(uint8_t, iLen + 1); | |
848 for (; i < iLen; i++) { | |
849 if ((pStr[i] & 128) == 0) { | |
850 if (g_inv_base64[pStr[i]] != 0xFF || pStr[i] == '=') { | |
851 pCP[j++] = pStr[i]; | |
852 } | |
853 } | |
854 } | |
855 pCP[j] = '\0'; | |
856 return pCP; | |
857 } | |
858 static int32_t XFA_Base64Decode(const FX_CHAR* pStr, uint8_t* pOutBuffer) { | |
859 if (pStr == NULL) { | |
860 return 0; | |
861 } | |
862 uint8_t* pBuffer = | |
863 XFA_RemoveBase64Whitespace((uint8_t*)pStr, FXSYS_strlen((FX_CHAR*)pStr)); | |
864 if (pBuffer == NULL) { | |
865 return 0; | |
866 } | |
867 int32_t iLen = FXSYS_strlen((FX_CHAR*)pBuffer); | |
868 int32_t i = 0, j = 0; | |
869 FX_DWORD dwLimb = 0; | |
870 for (; i + 3 < iLen; i += 4) { | |
871 if (pBuffer[i] == '=' || pBuffer[i + 1] == '=' || pBuffer[i + 2] == '=' || | |
872 pBuffer[i + 3] == '=') { | |
873 if (pBuffer[i] == '=' || pBuffer[i + 1] == '=') { | |
874 break; | |
875 } | |
876 if (pBuffer[i + 2] == '=') { | |
877 dwLimb = ((FX_DWORD)g_inv_base64[pBuffer[i]] << 6) | | |
878 ((FX_DWORD)g_inv_base64[pBuffer[i + 1]]); | |
879 pOutBuffer[j] = (uint8_t)(dwLimb >> 4) & 0xFF; | |
880 j++; | |
881 } else { | |
882 dwLimb = ((FX_DWORD)g_inv_base64[pBuffer[i]] << 12) | | |
883 ((FX_DWORD)g_inv_base64[pBuffer[i + 1]] << 6) | | |
884 ((FX_DWORD)g_inv_base64[pBuffer[i + 2]]); | |
885 pOutBuffer[j] = (uint8_t)(dwLimb >> 10) & 0xFF; | |
886 pOutBuffer[j + 1] = (uint8_t)(dwLimb >> 2) & 0xFF; | |
887 j += 2; | |
888 } | |
889 } else { | |
890 dwLimb = ((FX_DWORD)g_inv_base64[pBuffer[i]] << 18) | | |
891 ((FX_DWORD)g_inv_base64[pBuffer[i + 1]] << 12) | | |
892 ((FX_DWORD)g_inv_base64[pBuffer[i + 2]] << 6) | | |
893 ((FX_DWORD)g_inv_base64[pBuffer[i + 3]]); | |
894 pOutBuffer[j] = (uint8_t)(dwLimb >> 16) & 0xff; | |
895 pOutBuffer[j + 1] = (uint8_t)(dwLimb >> 8) & 0xff; | |
896 pOutBuffer[j + 2] = (uint8_t)(dwLimb)&0xff; | |
897 j += 3; | |
898 } | |
899 } | |
900 FX_Free(pBuffer); | |
901 return j; | |
902 } | |
903 static FX_CHAR g_base64_chars[] = | |
904 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |
905 FX_CHAR* XFA_Base64Encode(const uint8_t* buf, int32_t buf_len) { | |
906 FX_CHAR* out = NULL; | |
907 int i, j; | |
908 FX_DWORD limb; | |
909 out = FX_Alloc(FX_CHAR, ((buf_len * 8 + 5) / 6) + 5); | |
910 for (i = 0, j = 0, limb = 0; i + 2 < buf_len; i += 3, j += 4) { | |
911 limb = ((FX_DWORD)buf[i] << 16) | ((FX_DWORD)buf[i + 1] << 8) | | |
912 ((FX_DWORD)buf[i + 2]); | |
913 out[j] = g_base64_chars[(limb >> 18) & 63]; | |
914 out[j + 1] = g_base64_chars[(limb >> 12) & 63]; | |
915 out[j + 2] = g_base64_chars[(limb >> 6) & 63]; | |
916 out[j + 3] = g_base64_chars[(limb)&63]; | |
917 } | |
918 switch (buf_len - i) { | |
919 case 0: | |
920 break; | |
921 case 1: | |
922 limb = ((FX_DWORD)buf[i]); | |
923 out[j++] = g_base64_chars[(limb >> 2) & 63]; | |
924 out[j++] = g_base64_chars[(limb << 4) & 63]; | |
925 out[j++] = '='; | |
926 out[j++] = '='; | |
927 break; | |
928 case 2: | |
929 limb = ((FX_DWORD)buf[i] << 8) | ((FX_DWORD)buf[i + 1]); | |
930 out[j++] = g_base64_chars[(limb >> 10) & 63]; | |
931 out[j++] = g_base64_chars[(limb >> 4) & 63]; | |
932 out[j++] = g_base64_chars[(limb << 2) & 63]; | |
933 out[j++] = '='; | |
934 break; | |
935 default: | |
936 break; | |
937 } | |
938 out[j] = '\0'; | |
939 return out; | |
940 } | |
941 FXCODEC_IMAGE_TYPE XFA_GetImageType(const CFX_WideStringC& wsType) { | |
942 CFX_WideString wsContentType(wsType); | |
943 wsContentType.MakeLower(); | |
944 if (wsContentType == FX_WSTRC(L"image/jpg")) { | |
945 return FXCODEC_IMAGE_JPG; | |
946 } | |
947 if (wsContentType == FX_WSTRC(L"image/png")) { | |
948 return FXCODEC_IMAGE_PNG; | |
949 } | |
950 if (wsContentType == FX_WSTRC(L"image/gif")) { | |
951 return FXCODEC_IMAGE_GIF; | |
952 } | |
953 if (wsContentType == FX_WSTRC(L"image/bmp")) { | |
954 return FXCODEC_IMAGE_BMP; | |
955 } | |
956 if (wsContentType == FX_WSTRC(L"image/tif")) { | |
957 return FXCODEC_IMAGE_TIF; | |
958 } | |
959 return FXCODEC_IMAGE_UNKNOWN; | |
960 } | |
961 CFX_DIBitmap* XFA_LoadImageData(CXFA_FFDoc* pDoc, | |
962 CXFA_Image* pImage, | |
963 FX_BOOL& bNameImage, | |
964 int32_t& iImageXDpi, | |
965 int32_t& iImageYDpi) { | |
966 CFX_WideString wsHref; | |
967 pImage->GetHref(wsHref); | |
968 CFX_WideString wsImage; | |
969 pImage->GetContent(wsImage); | |
970 if (wsHref.IsEmpty() && wsImage.IsEmpty()) { | |
971 return NULL; | |
972 } | |
973 CFX_WideString wsContentType; | |
974 pImage->GetContentType(wsContentType); | |
975 FXCODEC_IMAGE_TYPE type = XFA_GetImageType(wsContentType); | |
976 CFX_ByteString bsContent; | |
977 uint8_t* pImageBuffer = NULL; | |
978 IFX_FileRead* pImageFileRead = NULL; | |
979 if (wsImage.GetLength() > 0) { | |
980 XFA_ATTRIBUTEENUM iEncoding = | |
981 (XFA_ATTRIBUTEENUM)pImage->GetTransferEncoding(); | |
982 if (iEncoding == XFA_ATTRIBUTEENUM_Base64) { | |
983 CFX_ByteString bsData = wsImage.UTF8Encode(); | |
984 int32_t iLength = bsData.GetLength(); | |
985 pImageBuffer = FX_Alloc(uint8_t, iLength); | |
986 int32_t iRead = XFA_Base64Decode((const FX_CHAR*)bsData, pImageBuffer); | |
987 if (iRead > 0) { | |
988 pImageFileRead = FX_CreateMemoryStream(pImageBuffer, iRead); | |
989 } | |
990 } else { | |
991 bsContent = CFX_ByteString::FromUnicode(wsImage); | |
992 pImageFileRead = FX_CreateMemoryStream( | |
993 (uint8_t*)(const uint8_t*)bsContent, bsContent.GetLength()); | |
994 } | |
995 } else { | |
996 CFX_WideString wsURL = wsHref; | |
997 if (wsURL.Left(7) != FX_WSTRC(L"http://") && | |
998 wsURL.Left(6) != FX_WSTRC(L"ftp://")) { | |
999 CFX_DIBitmap* pBitmap = | |
1000 pDoc->GetPDFNamedImage(wsURL, iImageXDpi, iImageYDpi); | |
1001 if (pBitmap) { | |
1002 bNameImage = TRUE; | |
1003 return pBitmap; | |
1004 } | |
1005 } | |
1006 pImageFileRead = pDoc->GetDocProvider()->OpenLinkedFile(pDoc, wsURL); | |
1007 } | |
1008 if (!pImageFileRead) { | |
1009 FX_Free(pImageBuffer); | |
1010 return NULL; | |
1011 } | |
1012 bNameImage = FALSE; | |
1013 CFX_DIBitmap* pBitmap = | |
1014 XFA_LoadImageFromBuffer(pImageFileRead, type, iImageXDpi, iImageYDpi); | |
1015 FX_Free(pImageBuffer); | |
1016 pImageFileRead->Release(); | |
1017 return pBitmap; | |
1018 } | |
1019 static FXDIB_Format XFA_GetDIBFormat(FXCODEC_IMAGE_TYPE type, | |
1020 int32_t iComponents, | |
1021 int32_t iBitsPerComponent) { | |
1022 FXDIB_Format dibFormat = FXDIB_Argb; | |
1023 switch (type) { | |
1024 case FXCODEC_IMAGE_BMP: | |
1025 case FXCODEC_IMAGE_JPG: | |
1026 case FXCODEC_IMAGE_TIF: { | |
1027 dibFormat = FXDIB_Rgb32; | |
1028 int32_t bpp = iComponents * iBitsPerComponent; | |
1029 if (bpp <= 24) { | |
1030 dibFormat = FXDIB_Rgb; | |
1031 } | |
1032 } break; | |
1033 case FXCODEC_IMAGE_PNG: | |
1034 default: | |
1035 break; | |
1036 } | |
1037 return dibFormat; | |
1038 } | |
1039 CFX_DIBitmap* XFA_LoadImageFromBuffer(IFX_FileRead* pImageFileRead, | |
1040 FXCODEC_IMAGE_TYPE type, | |
1041 int32_t& iImageXDpi, | |
1042 int32_t& iImageYDpi) { | |
1043 CFX_GEModule* pGeModule = CFX_GEModule::Get(); | |
1044 if (!pGeModule) { | |
1045 return NULL; | |
1046 } | |
1047 CCodec_ModuleMgr* pCodecMgr = pGeModule->GetCodecModule(); | |
1048 if (!pCodecMgr) { | |
1049 return NULL; | |
1050 } | |
1051 CFX_DIBAttribute dibAttr; | |
1052 CFX_DIBitmap* pBitmap = NULL; | |
1053 ICodec_ProgressiveDecoder* pProgressiveDecoder = | |
1054 pCodecMgr->CreateProgressiveDecoder(); | |
1055 pProgressiveDecoder->LoadImageInfo(pImageFileRead, type, &dibAttr); | |
1056 switch (dibAttr.m_wDPIUnit) { | |
1057 case FXCODEC_RESUNIT_CENTIMETER: | |
1058 dibAttr.m_nXDPI = (int32_t)(dibAttr.m_nXDPI * 2.54f); | |
1059 dibAttr.m_nYDPI = (int32_t)(dibAttr.m_nYDPI * 2.54f); | |
1060 break; | |
1061 case FXCODEC_RESUNIT_METER: | |
1062 dibAttr.m_nXDPI = (int32_t)(dibAttr.m_nXDPI / (FX_FLOAT)100 * 2.54f); | |
1063 dibAttr.m_nYDPI = (int32_t)(dibAttr.m_nYDPI / (FX_FLOAT)100 * 2.54f); | |
1064 break; | |
1065 default: | |
1066 break; | |
1067 } | |
1068 iImageXDpi = dibAttr.m_nXDPI > 1 ? dibAttr.m_nXDPI : (96); | |
1069 iImageYDpi = dibAttr.m_nYDPI > 1 ? dibAttr.m_nYDPI : (96); | |
1070 if (pProgressiveDecoder->GetWidth() > 0 && | |
1071 pProgressiveDecoder->GetHeight() > 0) { | |
1072 type = pProgressiveDecoder->GetType(); | |
1073 int32_t iComponents = pProgressiveDecoder->GetNumComponents(); | |
1074 int32_t iBpc = pProgressiveDecoder->GetBPC(); | |
1075 FXDIB_Format dibFormat = XFA_GetDIBFormat(type, iComponents, iBpc); | |
1076 pBitmap = new CFX_DIBitmap(); | |
1077 pBitmap->Create(pProgressiveDecoder->GetWidth(), | |
1078 pProgressiveDecoder->GetHeight(), dibFormat); | |
1079 pBitmap->Clear(0xffffffff); | |
1080 int32_t nFrames; | |
1081 if ((pProgressiveDecoder->GetFrames(nFrames) == | |
1082 FXCODEC_STATUS_DECODE_READY) && | |
1083 (nFrames > 0)) { | |
1084 pProgressiveDecoder->StartDecode(pBitmap, 0, 0, pBitmap->GetWidth(), | |
1085 pBitmap->GetHeight()); | |
1086 pProgressiveDecoder->ContinueDecode(); | |
1087 } | |
1088 } | |
1089 delete pProgressiveDecoder; | |
1090 return pBitmap; | |
1091 } | |
1092 void XFA_RectWidthoutMargin(CFX_RectF& rt, const CXFA_Margin& mg, FX_BOOL bUI) { | |
1093 if (!mg) { | |
1094 return; | |
1095 } | |
1096 FX_FLOAT fLeftInset, fTopInset, fRightInset, fBottomInset; | |
1097 mg.GetLeftInset(fLeftInset); | |
1098 mg.GetTopInset(fTopInset); | |
1099 mg.GetRightInset(fRightInset); | |
1100 mg.GetBottomInset(fBottomInset); | |
1101 rt.Deflate(fLeftInset, fTopInset, fRightInset, fBottomInset); | |
1102 } | |
1103 CXFA_FFWidget* XFA_GetWidgetFromLayoutItem(CXFA_LayoutItem* pLayoutItem) { | |
1104 XFA_ELEMENT iType = pLayoutItem->GetFormNode()->GetClassID(); | |
1105 if (XFA_IsCreateWidget(iType)) { | |
1106 return static_cast<CXFA_FFWidget*>(pLayoutItem); | |
1107 } | |
1108 return nullptr; | |
1109 } | |
1110 FX_BOOL XFA_IsCreateWidget(XFA_ELEMENT iType) { | |
1111 return iType == XFA_ELEMENT_Field || iType == XFA_ELEMENT_Draw || | |
1112 iType == XFA_ELEMENT_Subform || iType == XFA_ELEMENT_ExclGroup; | |
1113 } | |
1114 static void XFA_BOX_GetPath_Arc(CXFA_Box box, | |
1115 CFX_RectF rtDraw, | |
1116 CFX_Path& fillPath, | |
1117 FX_DWORD dwFlags) { | |
1118 FX_FLOAT a, b; | |
1119 a = rtDraw.width / 2.0f; | |
1120 b = rtDraw.height / 2.0f; | |
1121 if (box.IsCircular() || (dwFlags & XFA_DRAWBOX_ForceRound) != 0) { | |
1122 a = b = std::min(a, b); | |
1123 } | |
1124 CFX_PointF center = rtDraw.Center(); | |
1125 rtDraw.left = center.x - a; | |
1126 rtDraw.top = center.y - b; | |
1127 rtDraw.width = a + a; | |
1128 rtDraw.height = b + b; | |
1129 FX_FLOAT startAngle = 0, sweepAngle = 360; | |
1130 FX_BOOL bStart = box.GetStartAngle(startAngle); | |
1131 FX_BOOL bEnd = box.GetSweepAngle(sweepAngle); | |
1132 if (!bStart && !bEnd) { | |
1133 fillPath.AddEllipse(rtDraw); | |
1134 return; | |
1135 } | |
1136 startAngle = -startAngle * FX_PI / 180.0f; | |
1137 sweepAngle = -sweepAngle * FX_PI / 180.0f; | |
1138 fillPath.AddArc(rtDraw.left, rtDraw.top, rtDraw.width, rtDraw.height, | |
1139 startAngle, sweepAngle); | |
1140 } | |
1141 static void XFA_BOX_GetPath(CXFA_Box box, | |
1142 const CXFA_StrokeArray& strokes, | |
1143 CFX_RectF rtWidget, | |
1144 CFX_Path& path, | |
1145 int32_t nIndex, | |
1146 FX_BOOL bStart, | |
1147 FX_BOOL bCorner) { | |
1148 FXSYS_assert(nIndex >= 0 && nIndex < 8); | |
1149 FX_BOOL bInverted, bRound; | |
1150 FX_FLOAT fRadius1, fRadius2, sx, sy, vx, vy, nx, ny, offsetY, offsetX, | |
1151 offsetEX, offsetEY; | |
1152 CFX_PointF cpStart, cp, cp1, cp2; | |
1153 CFX_RectF rtRadius; | |
1154 int32_t n = (nIndex & 1) ? nIndex - 1 : nIndex; | |
1155 CXFA_Corner corner1(strokes[n].GetNode()); | |
1156 CXFA_Corner corner2(strokes[(n + 2) % 8].GetNode()); | |
1157 fRadius1 = bCorner ? corner1.GetRadius() : 0; | |
1158 fRadius2 = bCorner ? corner2.GetRadius() : 0; | |
1159 bInverted = corner1.IsInverted(); | |
1160 offsetY = 0.0f; | |
1161 offsetX = 0.0f; | |
1162 bRound = corner1.GetJoinType() == XFA_ATTRIBUTEENUM_Round; | |
1163 FX_FLOAT halfAfter = 0.0f; | |
1164 FX_FLOAT halfBefore = 0.0f; | |
1165 CXFA_Stroke stroke = strokes[nIndex]; | |
1166 if (stroke.IsCorner()) { | |
1167 CXFA_Stroke edgeBefore = strokes[(nIndex + 1 * 8 - 1) % 8]; | |
1168 CXFA_Stroke edgeAfter = strokes[nIndex + 1]; | |
1169 if (stroke.IsInverted()) { | |
1170 if (!stroke.SameStyles(edgeBefore)) { | |
1171 halfBefore = edgeBefore.GetThickness() / 2; | |
1172 } | |
1173 if (!stroke.SameStyles(edgeAfter)) { | |
1174 halfAfter = edgeAfter.GetThickness() / 2; | |
1175 } | |
1176 } | |
1177 } else { | |
1178 CXFA_Stroke edgeBefore = strokes[(nIndex + 8 - 2) % 8]; | |
1179 CXFA_Stroke edgeAfter = strokes[(nIndex + 2) % 8]; | |
1180 if (!bRound && !bInverted) { | |
1181 { halfBefore = edgeBefore.GetThickness() / 2; } | |
1182 { halfAfter = edgeAfter.GetThickness() / 2; } | |
1183 } | |
1184 } | |
1185 offsetEX = 0.0f; | |
1186 offsetEY = 0.0f; | |
1187 if (bRound) { | |
1188 sy = FX_PI / 2; | |
1189 } | |
1190 switch (nIndex) { | |
1191 case 0: | |
1192 case 1: | |
1193 cp1 = rtWidget.TopLeft(); | |
1194 cp2 = rtWidget.TopRight(); | |
1195 if (nIndex == 0) { | |
1196 cpStart.x = cp1.x - halfBefore; | |
1197 cpStart.y = cp1.y + fRadius1, offsetY = -halfAfter; | |
1198 } else { | |
1199 cpStart.x = cp1.x + fRadius1 - halfBefore, cpStart.y = cp1.y, | |
1200 offsetEX = halfAfter; | |
1201 } | |
1202 vx = 1, vy = 1; | |
1203 nx = -1, ny = 0; | |
1204 if (bRound) { | |
1205 sx = bInverted ? FX_PI / 2 : FX_PI; | |
1206 } else { | |
1207 sx = 1, sy = 0; | |
1208 } | |
1209 break; | |
1210 case 2: | |
1211 case 3: | |
1212 cp1 = rtWidget.TopRight(); | |
1213 cp2 = rtWidget.BottomRight(); | |
1214 if (nIndex == 2) { | |
1215 cpStart.x = cp1.x - fRadius1, cpStart.y = cp1.y - halfBefore, | |
1216 offsetX = halfAfter; | |
1217 } else { | |
1218 cpStart.x = cp1.x, cpStart.y = cp1.y + fRadius1 - halfBefore, | |
1219 offsetEY = halfAfter; | |
1220 } | |
1221 vx = -1, vy = 1; | |
1222 nx = 0, ny = -1; | |
1223 if (bRound) { | |
1224 sx = bInverted ? FX_PI : FX_PI * 3 / 2; | |
1225 } else { | |
1226 sx = 0, sy = 1; | |
1227 } | |
1228 break; | |
1229 case 4: | |
1230 case 5: | |
1231 cp1 = rtWidget.BottomRight(); | |
1232 cp2 = rtWidget.BottomLeft(); | |
1233 if (nIndex == 4) { | |
1234 cpStart.x = cp1.x + halfBefore, cpStart.y = cp1.y - fRadius1, | |
1235 offsetY = halfAfter; | |
1236 } else { | |
1237 cpStart.x = cp1.x - fRadius1 + halfBefore, cpStart.y = cp1.y, | |
1238 offsetEX = -halfAfter; | |
1239 } | |
1240 vx = -1, vy = -1; | |
1241 nx = 1, ny = 0; | |
1242 if (bRound) { | |
1243 sx = bInverted ? FX_PI * 3 / 2 : 0; | |
1244 } else { | |
1245 sx = -1, sy = 0; | |
1246 } | |
1247 break; | |
1248 case 6: | |
1249 case 7: | |
1250 cp1 = rtWidget.BottomLeft(); | |
1251 cp2 = rtWidget.TopLeft(); | |
1252 if (nIndex == 6) { | |
1253 cpStart.x = cp1.x + fRadius1, cpStart.y = cp1.y + halfBefore, | |
1254 offsetX = -halfAfter; | |
1255 } else { | |
1256 cpStart.x = cp1.x, cpStart.y = cp1.y - fRadius1 + halfBefore, | |
1257 offsetEY = -halfAfter; | |
1258 } | |
1259 vx = 1, vy = -1; | |
1260 nx = 0, ny = 1; | |
1261 if (bRound) { | |
1262 sx = bInverted ? 0 : FX_PI / 2; | |
1263 } else { | |
1264 sx = 0, sy = -1; | |
1265 } | |
1266 break; | |
1267 } | |
1268 if (bStart) { | |
1269 path.MoveTo(cpStart.x, cpStart.y); | |
1270 } | |
1271 if (nIndex & 1) { | |
1272 path.LineTo(cp2.x + fRadius2 * nx + offsetEX, | |
1273 cp2.y + fRadius2 * ny + offsetEY); | |
1274 return; | |
1275 } | |
1276 if (bRound) { | |
1277 if (fRadius1 < 0) { | |
1278 sx -= FX_PI; | |
1279 } | |
1280 if (bInverted) { | |
1281 sy *= -1; | |
1282 } | |
1283 rtRadius.Set(cp1.x + offsetX * 2, cp1.y + offsetY * 2, | |
1284 fRadius1 * 2 * vx - offsetX * 2, | |
1285 fRadius1 * 2 * vy - offsetY * 2); | |
1286 rtRadius.Normalize(); | |
1287 if (bInverted) { | |
1288 rtRadius.Offset(-fRadius1 * vx, -fRadius1 * vy); | |
1289 } | |
1290 path.ArcTo(rtRadius.left, rtRadius.top, rtRadius.width, rtRadius.height, sx, | |
1291 sy); | |
1292 } else { | |
1293 if (bInverted) { | |
1294 cp.x = cp1.x + fRadius1 * vx, cp.y = cp1.y + fRadius1 * vy; | |
1295 } else { | |
1296 cp = cp1; | |
1297 } | |
1298 path.LineTo(cp.x, cp.y); | |
1299 path.LineTo(cp1.x + fRadius1 * sx + offsetX, | |
1300 cp1.y + fRadius1 * sy + offsetY); | |
1301 } | |
1302 } | |
1303 static void XFA_BOX_GetFillPath(CXFA_Box box, | |
1304 const CXFA_StrokeArray& strokes, | |
1305 CFX_RectF rtWidget, | |
1306 CFX_Path& fillPath, | |
1307 FX_WORD dwFlags) { | |
1308 if (box.IsArc() || (dwFlags & XFA_DRAWBOX_ForceRound) != 0) { | |
1309 CXFA_Edge edge = box.GetEdge(0); | |
1310 FX_FLOAT fThickness = edge.GetThickness(); | |
1311 if (fThickness < 0) { | |
1312 fThickness = 0; | |
1313 } | |
1314 FX_FLOAT fHalf = fThickness / 2; | |
1315 int32_t iHand = box.GetHand(); | |
1316 if (iHand == XFA_ATTRIBUTEENUM_Left) { | |
1317 rtWidget.Inflate(fHalf, fHalf); | |
1318 } else if (iHand == XFA_ATTRIBUTEENUM_Right) { | |
1319 rtWidget.Deflate(fHalf, fHalf); | |
1320 } | |
1321 XFA_BOX_GetPath_Arc(box, rtWidget, fillPath, dwFlags); | |
1322 return; | |
1323 } | |
1324 FX_BOOL bSameStyles = TRUE; | |
1325 int32_t i; | |
1326 CXFA_Stroke stroke1 = strokes[0]; | |
1327 for (i = 1; i < 8; i++) { | |
1328 CXFA_Stroke stroke2 = strokes[i]; | |
1329 if (!stroke1.SameStyles(stroke2)) { | |
1330 bSameStyles = FALSE; | |
1331 break; | |
1332 } | |
1333 stroke1 = stroke2; | |
1334 } | |
1335 if (bSameStyles) { | |
1336 stroke1 = strokes[0]; | |
1337 for (i = 2; i < 8; i += 2) { | |
1338 CXFA_Stroke stroke2 = strokes[i]; | |
1339 if (!stroke1.SameStyles(stroke2, XFA_STROKE_SAMESTYLE_NoPresence | | |
1340 XFA_STROKE_SAMESTYLE_Corner)) { | |
1341 bSameStyles = FALSE; | |
1342 break; | |
1343 } | |
1344 stroke1 = stroke2; | |
1345 } | |
1346 if (bSameStyles) { | |
1347 stroke1 = strokes[0]; | |
1348 if (stroke1.IsInverted()) { | |
1349 bSameStyles = FALSE; | |
1350 } | |
1351 if (stroke1.GetJoinType() != XFA_ATTRIBUTEENUM_Square) { | |
1352 bSameStyles = FALSE; | |
1353 } | |
1354 } | |
1355 } | |
1356 if (bSameStyles) { | |
1357 fillPath.AddRectangle(rtWidget.left, rtWidget.top, rtWidget.width, | |
1358 rtWidget.height); | |
1359 return; | |
1360 } | |
1361 FX_BOOL bInverted, bRound; | |
1362 FX_FLOAT fRadius1, fRadius2, sx, sy, vx, vy, nx, ny; | |
1363 CFX_PointF cp, cp1, cp2; | |
1364 CFX_RectF rtRadius; | |
1365 for (int32_t i = 0; i < 8; i += 2) { | |
1366 CXFA_Corner corner1(strokes[i].GetNode()); | |
1367 CXFA_Corner corner2(strokes[(i + 2) % 8].GetNode()); | |
1368 fRadius1 = corner1.GetRadius(); | |
1369 fRadius2 = corner2.GetRadius(); | |
1370 bInverted = corner1.IsInverted(); | |
1371 bRound = corner1.GetJoinType() == XFA_ATTRIBUTEENUM_Round; | |
1372 if (bRound) { | |
1373 sy = FX_PI / 2; | |
1374 } | |
1375 switch (i) { | |
1376 case 0: | |
1377 cp1 = rtWidget.TopLeft(); | |
1378 cp2 = rtWidget.TopRight(); | |
1379 vx = 1, vy = 1; | |
1380 nx = -1, ny = 0; | |
1381 if (bRound) { | |
1382 sx = bInverted ? FX_PI / 2 : FX_PI; | |
1383 } else { | |
1384 sx = 1, sy = 0; | |
1385 } | |
1386 break; | |
1387 case 2: | |
1388 cp1 = rtWidget.TopRight(); | |
1389 cp2 = rtWidget.BottomRight(); | |
1390 vx = -1, vy = 1; | |
1391 nx = 0, ny = -1; | |
1392 if (bRound) { | |
1393 sx = bInverted ? FX_PI : FX_PI * 3 / 2; | |
1394 } else { | |
1395 sx = 0, sy = 1; | |
1396 } | |
1397 break; | |
1398 case 4: | |
1399 cp1 = rtWidget.BottomRight(); | |
1400 cp2 = rtWidget.BottomLeft(); | |
1401 vx = -1, vy = -1; | |
1402 nx = 1, ny = 0; | |
1403 if (bRound) { | |
1404 sx = bInverted ? FX_PI * 3 / 2 : 0; | |
1405 } else { | |
1406 sx = -1, sy = 0; | |
1407 } | |
1408 break; | |
1409 case 6: | |
1410 cp1 = rtWidget.BottomLeft(); | |
1411 cp2 = rtWidget.TopLeft(); | |
1412 vx = 1, vy = -1; | |
1413 nx = 0, ny = 1; | |
1414 if (bRound) { | |
1415 sx = bInverted ? 0 : FX_PI / 2; | |
1416 } else { | |
1417 sx = 0, sy = -1; | |
1418 } | |
1419 break; | |
1420 } | |
1421 if (i == 0) { | |
1422 fillPath.MoveTo(cp1.x, cp1.y + fRadius1); | |
1423 } | |
1424 if (bRound) { | |
1425 if (fRadius1 < 0) { | |
1426 sx -= FX_PI; | |
1427 } | |
1428 if (bInverted) { | |
1429 sy *= -1; | |
1430 } | |
1431 rtRadius.Set(cp1.x, cp1.y, fRadius1 * 2 * vx, fRadius1 * 2 * vy); | |
1432 rtRadius.Normalize(); | |
1433 if (bInverted) { | |
1434 rtRadius.Offset(-fRadius1 * vx, -fRadius1 * vy); | |
1435 } | |
1436 fillPath.ArcTo(rtRadius.left, rtRadius.top, rtRadius.width, | |
1437 rtRadius.height, sx, sy); | |
1438 } else { | |
1439 if (bInverted) { | |
1440 cp.x = cp1.x + fRadius1 * vx, cp.y = cp1.y + fRadius1 * vy; | |
1441 } else { | |
1442 cp = cp1; | |
1443 } | |
1444 fillPath.LineTo(cp.x, cp.y); | |
1445 fillPath.LineTo(cp1.x + fRadius1 * sx, cp1.y + fRadius1 * sy); | |
1446 } | |
1447 fillPath.LineTo(cp2.x + fRadius2 * nx, cp2.y + fRadius2 * ny); | |
1448 } | |
1449 } | |
1450 static void XFA_BOX_Fill_Radial(CXFA_Box box, | |
1451 CFX_Graphics* pGS, | |
1452 CFX_Path& fillPath, | |
1453 CFX_RectF rtFill, | |
1454 CFX_Matrix* pMatrix) { | |
1455 CXFA_Fill fill = box.GetFill(); | |
1456 FX_ARGB crStart, crEnd; | |
1457 crStart = fill.GetColor(); | |
1458 int32_t iType = fill.GetRadial(crEnd); | |
1459 CFX_Shading shading; | |
1460 if (iType != XFA_ATTRIBUTEENUM_ToEdge) { | |
1461 FX_ARGB temp = crEnd; | |
1462 crEnd = crStart; | |
1463 crStart = temp; | |
1464 } | |
1465 shading.CreateRadial(rtFill.Center(), rtFill.Center(), 0, | |
1466 FXSYS_sqrt(rtFill.Width() * rtFill.Width() + | |
1467 rtFill.Height() * rtFill.Height()) / | |
1468 2, | |
1469 TRUE, TRUE, crStart, crEnd); | |
1470 CFX_Color cr(&shading); | |
1471 pGS->SetFillColor(&cr); | |
1472 pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix); | |
1473 } | |
1474 static void XFA_BOX_Fill_Pattern(CXFA_Box box, | |
1475 CFX_Graphics* pGS, | |
1476 CFX_Path& fillPath, | |
1477 CFX_RectF rtFill, | |
1478 CFX_Matrix* pMatrix) { | |
1479 CXFA_Fill fill = box.GetFill(); | |
1480 FX_ARGB crStart, crEnd; | |
1481 crStart = fill.GetColor(); | |
1482 int32_t iType = fill.GetPattern(crEnd); | |
1483 int32_t iHatch = FX_HATCHSTYLE_Cross; | |
1484 switch (iType) { | |
1485 case XFA_ATTRIBUTEENUM_CrossDiagonal: | |
1486 iHatch = FX_HATCHSTYLE_DiagonalCross; | |
1487 break; | |
1488 case XFA_ATTRIBUTEENUM_DiagonalLeft: | |
1489 iHatch = FX_HATCHSTYLE_ForwardDiagonal; | |
1490 break; | |
1491 case XFA_ATTRIBUTEENUM_DiagonalRight: | |
1492 iHatch = FX_HATCHSTYLE_BackwardDiagonal; | |
1493 break; | |
1494 case XFA_ATTRIBUTEENUM_Horizontal: | |
1495 iHatch = FX_HATCHSTYLE_Horizontal; | |
1496 break; | |
1497 case XFA_ATTRIBUTEENUM_Vertical: | |
1498 iHatch = FX_HATCHSTYLE_Vertical; | |
1499 break; | |
1500 default: | |
1501 break; | |
1502 } | |
1503 CFX_Pattern pattern; | |
1504 pattern.Create(iHatch, crEnd, crStart); | |
1505 CFX_Color cr(&pattern); | |
1506 pGS->SetFillColor(&cr); | |
1507 pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix); | |
1508 } | |
1509 static void XFA_BOX_Fill_Linear(CXFA_Box box, | |
1510 CFX_Graphics* pGS, | |
1511 CFX_Path& fillPath, | |
1512 CFX_RectF rtFill, | |
1513 CFX_Matrix* pMatrix) { | |
1514 CXFA_Fill fill = box.GetFill(); | |
1515 FX_ARGB crStart = fill.GetColor(); | |
1516 FX_ARGB crEnd; | |
1517 int32_t iType = fill.GetLinear(crEnd); | |
1518 CFX_PointF ptStart; | |
1519 CFX_PointF ptEnd; | |
1520 switch (iType) { | |
1521 case XFA_ATTRIBUTEENUM_ToRight: | |
1522 ptStart = CFX_PointF(rtFill.left, rtFill.top); | |
1523 ptEnd = CFX_PointF(rtFill.right(), rtFill.top); | |
1524 break; | |
1525 case XFA_ATTRIBUTEENUM_ToBottom: | |
1526 ptStart = CFX_PointF(rtFill.left, rtFill.top); | |
1527 ptEnd = CFX_PointF(rtFill.left, rtFill.bottom()); | |
1528 break; | |
1529 case XFA_ATTRIBUTEENUM_ToLeft: | |
1530 ptStart = CFX_PointF(rtFill.right(), rtFill.top); | |
1531 ptEnd = CFX_PointF(rtFill.left, rtFill.top); | |
1532 break; | |
1533 case XFA_ATTRIBUTEENUM_ToTop: | |
1534 ptStart = CFX_PointF(rtFill.left, rtFill.bottom()); | |
1535 ptEnd = CFX_PointF(rtFill.left, rtFill.top); | |
1536 break; | |
1537 default: | |
1538 break; | |
1539 } | |
1540 CFX_Shading shading; | |
1541 shading.CreateAxial(ptStart, ptEnd, FALSE, FALSE, crStart, crEnd); | |
1542 CFX_Color cr(&shading); | |
1543 pGS->SetFillColor(&cr); | |
1544 pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix); | |
1545 } | |
1546 static void XFA_BOX_Fill(CXFA_Box box, | |
1547 const CXFA_StrokeArray& strokes, | |
1548 CFX_Graphics* pGS, | |
1549 const CFX_RectF& rtWidget, | |
1550 CFX_Matrix* pMatrix, | |
1551 FX_DWORD dwFlags) { | |
1552 CXFA_Fill fill = box.GetFill(); | |
1553 if (!fill || fill.GetPresence() != XFA_ATTRIBUTEENUM_Visible) { | |
1554 return; | |
1555 } | |
1556 pGS->SaveGraphState(); | |
1557 CFX_Path fillPath; | |
1558 fillPath.Create(); | |
1559 XFA_BOX_GetFillPath(box, strokes, rtWidget, fillPath, | |
1560 (dwFlags & XFA_DRAWBOX_ForceRound) != 0); | |
1561 fillPath.Close(); | |
1562 int32_t eType = fill.GetFillType(); | |
1563 switch (eType) { | |
1564 case XFA_ELEMENT_Radial: | |
1565 XFA_BOX_Fill_Radial(box, pGS, fillPath, rtWidget, pMatrix); | |
1566 break; | |
1567 case XFA_ELEMENT_Pattern: | |
1568 XFA_BOX_Fill_Pattern(box, pGS, fillPath, rtWidget, pMatrix); | |
1569 break; | |
1570 case XFA_ELEMENT_Linear: | |
1571 XFA_BOX_Fill_Linear(box, pGS, fillPath, rtWidget, pMatrix); | |
1572 break; | |
1573 default: { | |
1574 FX_ARGB cr; | |
1575 if (eType == XFA_ELEMENT_Stipple) { | |
1576 int32_t iRate = fill.GetStipple(cr); | |
1577 if (iRate == 0) { | |
1578 iRate = 100; | |
1579 } | |
1580 int32_t a = 0; | |
1581 FX_COLORREF rgb; | |
1582 ArgbDecode(cr, a, rgb); | |
1583 cr = ArgbEncode(iRate * a / 100, rgb); | |
1584 } else { | |
1585 cr = fill.GetColor(); | |
1586 } | |
1587 CFX_Color fillColor(cr); | |
1588 pGS->SetFillColor(&fillColor); | |
1589 pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix); | |
1590 } break; | |
1591 } | |
1592 pGS->RestoreGraphState(); | |
1593 } | |
1594 static void XFA_BOX_StrokePath(CXFA_Stroke stroke, | |
1595 CFX_Path* pPath, | |
1596 CFX_Graphics* pGS, | |
1597 CFX_Matrix* pMatrix) { | |
1598 if (!stroke || !stroke.IsVisible()) { | |
1599 return; | |
1600 } | |
1601 FX_FLOAT fThickness = stroke.GetThickness(); | |
1602 if (fThickness < 0.001f) { | |
1603 return; | |
1604 } | |
1605 pGS->SaveGraphState(); | |
1606 if (stroke.IsCorner() && fThickness > 2 * stroke.GetRadius()) { | |
1607 fThickness = 2 * stroke.GetRadius(); | |
1608 } | |
1609 pGS->SetLineWidth(fThickness, TRUE); | |
1610 pGS->SetLineCap(CFX_GraphStateData::LineCapButt); | |
1611 XFA_StrokeTypeSetLineDash(pGS, stroke.GetStrokeType(), | |
1612 XFA_ATTRIBUTEENUM_Butt); | |
1613 CFX_Color fxColor(stroke.GetColor()); | |
1614 pGS->SetStrokeColor(&fxColor); | |
1615 pGS->StrokePath(pPath, pMatrix); | |
1616 pGS->RestoreGraphState(); | |
1617 } | |
1618 static void XFA_BOX_StrokeArc(CXFA_Box box, | |
1619 CFX_Graphics* pGS, | |
1620 CFX_RectF rtWidget, | |
1621 CFX_Matrix* pMatrix, | |
1622 FX_DWORD dwFlags) { | |
1623 CXFA_Edge edge = box.GetEdge(0); | |
1624 if (!edge || !edge.IsVisible()) { | |
1625 return; | |
1626 } | |
1627 FX_BOOL bVisible = FALSE; | |
1628 FX_FLOAT fThickness = 0; | |
1629 int32_t i3DType = box.Get3DStyle(bVisible, fThickness); | |
1630 if (i3DType) { | |
1631 if (bVisible && fThickness >= 0.001f) { | |
1632 dwFlags |= XFA_DRAWBOX_Lowered3D; | |
1633 } | |
1634 } | |
1635 FX_FLOAT fHalf = edge.GetThickness() / 2; | |
1636 if (fHalf < 0) { | |
1637 fHalf = 0; | |
1638 } | |
1639 int32_t iHand = box.GetHand(); | |
1640 if (iHand == XFA_ATTRIBUTEENUM_Left) { | |
1641 rtWidget.Inflate(fHalf, fHalf); | |
1642 } else if (iHand == XFA_ATTRIBUTEENUM_Right) { | |
1643 rtWidget.Deflate(fHalf, fHalf); | |
1644 } | |
1645 if ((dwFlags & XFA_DRAWBOX_ForceRound) == 0 || | |
1646 (dwFlags & XFA_DRAWBOX_Lowered3D) == 0) { | |
1647 if (fHalf < 0.001f) { | |
1648 return; | |
1649 } | |
1650 CFX_Path arcPath; | |
1651 arcPath.Create(); | |
1652 XFA_BOX_GetPath_Arc(box, rtWidget, arcPath, dwFlags); | |
1653 XFA_BOX_StrokePath(edge, &arcPath, pGS, pMatrix); | |
1654 return; | |
1655 } | |
1656 pGS->SaveGraphState(); | |
1657 pGS->SetLineWidth(fHalf); | |
1658 FX_FLOAT a, b; | |
1659 a = rtWidget.width / 2.0f; | |
1660 b = rtWidget.height / 2.0f; | |
1661 if (dwFlags & XFA_DRAWBOX_ForceRound) { | |
1662 a = b = std::min(a, b); | |
1663 } | |
1664 CFX_PointF center = rtWidget.Center(); | |
1665 rtWidget.left = center.x - a; | |
1666 rtWidget.top = center.y - b; | |
1667 rtWidget.width = a + a; | |
1668 rtWidget.height = b + b; | |
1669 FX_FLOAT startAngle = 0, sweepAngle = 360; | |
1670 startAngle = startAngle * FX_PI / 180.0f; | |
1671 sweepAngle = -sweepAngle * FX_PI / 180.0f; | |
1672 CFX_Path arcPath; | |
1673 arcPath.Create(); | |
1674 arcPath.AddArc(rtWidget.left, rtWidget.top, rtWidget.width, rtWidget.height, | |
1675 3.0f * FX_PI / 4.0f, FX_PI); | |
1676 CFX_Color cr(0xFF808080); | |
1677 pGS->SetStrokeColor(&cr); | |
1678 pGS->StrokePath(&arcPath, pMatrix); | |
1679 arcPath.Clear(); | |
1680 arcPath.AddArc(rtWidget.left, rtWidget.top, rtWidget.width, rtWidget.height, | |
1681 -1.0f * FX_PI / 4.0f, FX_PI); | |
1682 cr.Set(0xFFFFFFFF); | |
1683 pGS->SetStrokeColor(&cr); | |
1684 pGS->StrokePath(&arcPath, pMatrix); | |
1685 rtWidget.Deflate(fHalf, fHalf); | |
1686 arcPath.Clear(); | |
1687 arcPath.AddArc(rtWidget.left, rtWidget.top, rtWidget.width, rtWidget.height, | |
1688 3.0f * FX_PI / 4.0f, FX_PI); | |
1689 cr.Set(0xFF404040); | |
1690 pGS->SetStrokeColor(&cr); | |
1691 pGS->StrokePath(&arcPath, pMatrix); | |
1692 arcPath.Clear(); | |
1693 arcPath.AddArc(rtWidget.left, rtWidget.top, rtWidget.width, rtWidget.height, | |
1694 -1.0f * FX_PI / 4.0f, FX_PI); | |
1695 cr.Set(0xFFC0C0C0); | |
1696 pGS->SetStrokeColor(&cr); | |
1697 pGS->StrokePath(&arcPath, pMatrix); | |
1698 pGS->RestoreGraphState(); | |
1699 } | |
1700 static void XFA_Draw3DRect(CFX_Graphics* pGraphic, | |
1701 const CFX_RectF& rt, | |
1702 FX_FLOAT fLineWidth, | |
1703 CFX_Matrix* pMatrix, | |
1704 FX_ARGB argbTopLeft, | |
1705 FX_ARGB argbBottomRight) { | |
1706 CFX_Color crLT(argbTopLeft); | |
1707 pGraphic->SetFillColor(&crLT); | |
1708 FX_FLOAT fBottom = rt.bottom(); | |
1709 FX_FLOAT fRight = rt.right(); | |
1710 CFX_Path pathLT; | |
1711 pathLT.Create(); | |
1712 pathLT.MoveTo(rt.left, fBottom); | |
1713 pathLT.LineTo(rt.left, rt.top); | |
1714 pathLT.LineTo(fRight, rt.top); | |
1715 pathLT.LineTo(fRight - fLineWidth, rt.top + fLineWidth); | |
1716 pathLT.LineTo(rt.left + fLineWidth, rt.top + fLineWidth); | |
1717 pathLT.LineTo(rt.left + fLineWidth, fBottom - fLineWidth); | |
1718 pathLT.LineTo(rt.left, fBottom); | |
1719 pGraphic->FillPath(&pathLT, FXFILL_WINDING, pMatrix); | |
1720 CFX_Color crRB(argbBottomRight); | |
1721 pGraphic->SetFillColor(&crRB); | |
1722 CFX_Path pathRB; | |
1723 pathRB.Create(); | |
1724 pathRB.MoveTo(fRight, rt.top); | |
1725 pathRB.LineTo(fRight, fBottom); | |
1726 pathRB.LineTo(rt.left, fBottom); | |
1727 pathRB.LineTo(rt.left + fLineWidth, fBottom - fLineWidth); | |
1728 pathRB.LineTo(fRight - fLineWidth, fBottom - fLineWidth); | |
1729 pathRB.LineTo(fRight - fLineWidth, rt.top + fLineWidth); | |
1730 pathRB.LineTo(fRight, rt.top); | |
1731 pGraphic->FillPath(&pathRB, FXFILL_WINDING, pMatrix); | |
1732 } | |
1733 static void XFA_BOX_Stroke_3DRect_Lowered(CFX_Graphics* pGS, | |
1734 CFX_RectF rt, | |
1735 FX_FLOAT fThickness, | |
1736 CFX_Matrix* pMatrix) { | |
1737 FX_FLOAT fHalfWidth = fThickness / 2.0f; | |
1738 CFX_RectF rtInner(rt); | |
1739 rtInner.Deflate(fHalfWidth, fHalfWidth); | |
1740 CFX_Color cr(0xFF000000); | |
1741 pGS->SetFillColor(&cr); | |
1742 CFX_Path path; | |
1743 path.Create(); | |
1744 path.AddRectangle(rt.left, rt.top, rt.width, rt.height); | |
1745 path.AddRectangle(rtInner.left, rtInner.top, rtInner.width, rtInner.height); | |
1746 pGS->FillPath(&path, FXFILL_ALTERNATE, pMatrix); | |
1747 XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFF808080, 0xFFC0C0C0); | |
1748 } | |
1749 static void XFA_BOX_Stroke_3DRect_Raised(CFX_Graphics* pGS, | |
1750 CFX_RectF rt, | |
1751 FX_FLOAT fThickness, | |
1752 CFX_Matrix* pMatrix) { | |
1753 FX_FLOAT fHalfWidth = fThickness / 2.0f; | |
1754 CFX_RectF rtInner(rt); | |
1755 rtInner.Deflate(fHalfWidth, fHalfWidth); | |
1756 CFX_Color cr(0xFF000000); | |
1757 pGS->SetFillColor(&cr); | |
1758 CFX_Path path; | |
1759 path.Create(); | |
1760 path.AddRectangle(rt.left, rt.top, rt.width, rt.height); | |
1761 path.AddRectangle(rtInner.left, rtInner.top, rtInner.width, rtInner.height); | |
1762 pGS->FillPath(&path, FXFILL_ALTERNATE, pMatrix); | |
1763 XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFFFFFFFF, 0xFF808080); | |
1764 } | |
1765 static void XFA_BOX_Stroke_3DRect_Etched(CFX_Graphics* pGS, | |
1766 CFX_RectF rt, | |
1767 FX_FLOAT fThickness, | |
1768 CFX_Matrix* pMatrix) { | |
1769 FX_FLOAT fHalfWidth = fThickness / 2.0f; | |
1770 XFA_Draw3DRect(pGS, rt, fThickness, pMatrix, 0xFF808080, 0xFFFFFFFF); | |
1771 CFX_RectF rtInner(rt); | |
1772 rtInner.Deflate(fHalfWidth, fHalfWidth); | |
1773 XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFFFFFFFF, 0xFF808080); | |
1774 } | |
1775 static void XFA_BOX_Stroke_3DRect_Embossed(CFX_Graphics* pGS, | |
1776 CFX_RectF rt, | |
1777 FX_FLOAT fThickness, | |
1778 CFX_Matrix* pMatrix) { | |
1779 FX_FLOAT fHalfWidth = fThickness / 2.0f; | |
1780 XFA_Draw3DRect(pGS, rt, fThickness, pMatrix, 0xFF808080, 0xFF000000); | |
1781 CFX_RectF rtInner(rt); | |
1782 rtInner.Deflate(fHalfWidth, fHalfWidth); | |
1783 XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFF000000, 0xFF808080); | |
1784 } | |
1785 static void XFA_BOX_Stroke_Rect(CXFA_Box box, | |
1786 const CXFA_StrokeArray& strokes, | |
1787 CFX_Graphics* pGS, | |
1788 CFX_RectF rtWidget, | |
1789 CFX_Matrix* pMatrix) { | |
1790 FX_BOOL bVisible = FALSE; | |
1791 FX_FLOAT fThickness = 0; | |
1792 int32_t i3DType = box.Get3DStyle(bVisible, fThickness); | |
1793 if (i3DType) { | |
1794 if (!bVisible || fThickness < 0.001f) { | |
1795 return; | |
1796 } | |
1797 switch (i3DType) { | |
1798 case XFA_ATTRIBUTEENUM_Lowered: | |
1799 XFA_BOX_Stroke_3DRect_Lowered(pGS, rtWidget, fThickness, pMatrix); | |
1800 break; | |
1801 case XFA_ATTRIBUTEENUM_Raised: | |
1802 XFA_BOX_Stroke_3DRect_Raised(pGS, rtWidget, fThickness, pMatrix); | |
1803 break; | |
1804 case XFA_ATTRIBUTEENUM_Etched: | |
1805 XFA_BOX_Stroke_3DRect_Etched(pGS, rtWidget, fThickness, pMatrix); | |
1806 break; | |
1807 case XFA_ATTRIBUTEENUM_Embossed: | |
1808 XFA_BOX_Stroke_3DRect_Embossed(pGS, rtWidget, fThickness, pMatrix); | |
1809 break; | |
1810 } | |
1811 return; | |
1812 } | |
1813 FX_BOOL bClose = FALSE; | |
1814 FX_BOOL bSameStyles = TRUE; | |
1815 int32_t i; | |
1816 CXFA_Stroke stroke1 = strokes[0]; | |
1817 for (i = 1; i < 8; i++) { | |
1818 CXFA_Stroke stroke2 = strokes[i]; | |
1819 if (!stroke1.SameStyles(stroke2)) { | |
1820 bSameStyles = FALSE; | |
1821 break; | |
1822 } | |
1823 stroke1 = stroke2; | |
1824 } | |
1825 if (bSameStyles) { | |
1826 stroke1 = strokes[0]; | |
1827 bClose = TRUE; | |
1828 for (i = 2; i < 8; i += 2) { | |
1829 CXFA_Stroke stroke2 = strokes[i]; | |
1830 if (!stroke1.SameStyles(stroke2, XFA_STROKE_SAMESTYLE_NoPresence | | |
1831 XFA_STROKE_SAMESTYLE_Corner)) { | |
1832 bSameStyles = FALSE; | |
1833 break; | |
1834 } | |
1835 stroke1 = stroke2; | |
1836 } | |
1837 if (bSameStyles) { | |
1838 stroke1 = strokes[0]; | |
1839 if (stroke1.IsInverted()) { | |
1840 bSameStyles = FALSE; | |
1841 } | |
1842 if (stroke1.GetJoinType() != XFA_ATTRIBUTEENUM_Square) { | |
1843 bSameStyles = FALSE; | |
1844 } | |
1845 } | |
1846 } | |
1847 FX_BOOL bStart = TRUE; | |
1848 CFX_Path path; | |
1849 path.Create(); | |
1850 for (i = 0; i < 8; i++) { | |
1851 CXFA_Stroke stroke1 = strokes[i]; | |
1852 if ((i % 1) == 0 && stroke1.GetRadius() < 0) { | |
1853 FX_BOOL bEmpty = path.IsEmpty(); | |
1854 if (!bEmpty) { | |
1855 XFA_BOX_StrokePath(stroke1, &path, pGS, pMatrix); | |
1856 path.Clear(); | |
1857 } | |
1858 bStart = TRUE; | |
1859 continue; | |
1860 } | |
1861 XFA_BOX_GetPath(box, strokes, rtWidget, path, i, bStart, !bSameStyles); | |
1862 CXFA_Stroke stroke2 = strokes[(i + 1) % 8]; | |
1863 bStart = !stroke1.SameStyles(stroke2); | |
1864 if (bStart) { | |
1865 XFA_BOX_StrokePath(stroke1, &path, pGS, pMatrix); | |
1866 path.Clear(); | |
1867 } | |
1868 } | |
1869 FX_BOOL bEmpty = path.IsEmpty(); | |
1870 if (!bEmpty) { | |
1871 if (bClose) { | |
1872 path.Close(); | |
1873 } | |
1874 XFA_BOX_StrokePath(strokes[7], &path, pGS, pMatrix); | |
1875 } | |
1876 } | |
1877 static void XFA_BOX_Stroke(CXFA_Box box, | |
1878 const CXFA_StrokeArray& strokes, | |
1879 CFX_Graphics* pGS, | |
1880 CFX_RectF rtWidget, | |
1881 CFX_Matrix* pMatrix, | |
1882 FX_DWORD dwFlags) { | |
1883 if (box.IsArc() || (dwFlags & XFA_DRAWBOX_ForceRound) != 0) { | |
1884 XFA_BOX_StrokeArc(box, pGS, rtWidget, pMatrix, dwFlags); | |
1885 return; | |
1886 } | |
1887 bool bVisible = false; | |
1888 for (int32_t j = 0; j < 4; j++) { | |
1889 if (strokes[j * 2 + 1].IsVisible()) { | |
1890 bVisible = true; | |
1891 break; | |
1892 } | |
1893 } | |
1894 if (!bVisible) { | |
1895 return; | |
1896 } | |
1897 for (int32_t i = 1; i < 8; i += 2) { | |
1898 CXFA_Edge edge(strokes[i].GetNode()); | |
1899 FX_FLOAT fThickness = edge.GetThickness(); | |
1900 if (fThickness < 0) { | |
1901 fThickness = 0; | |
1902 } | |
1903 FX_FLOAT fHalf = fThickness / 2; | |
1904 int32_t iHand = box.GetHand(); | |
1905 switch (i) { | |
1906 case 1: | |
1907 if (iHand == XFA_ATTRIBUTEENUM_Left) { | |
1908 rtWidget.top -= fHalf; | |
1909 rtWidget.height += fHalf; | |
1910 } else if (iHand == XFA_ATTRIBUTEENUM_Right) { | |
1911 rtWidget.top += fHalf; | |
1912 rtWidget.height -= fHalf; | |
1913 } | |
1914 break; | |
1915 case 3: | |
1916 if (iHand == XFA_ATTRIBUTEENUM_Left) { | |
1917 rtWidget.width += fHalf; | |
1918 } else if (iHand == XFA_ATTRIBUTEENUM_Right) { | |
1919 rtWidget.width -= fHalf; | |
1920 } | |
1921 break; | |
1922 case 5: | |
1923 if (iHand == XFA_ATTRIBUTEENUM_Left) { | |
1924 rtWidget.height += fHalf; | |
1925 } else if (iHand == XFA_ATTRIBUTEENUM_Right) { | |
1926 rtWidget.height -= fHalf; | |
1927 } | |
1928 break; | |
1929 case 7: | |
1930 if (iHand == XFA_ATTRIBUTEENUM_Left) { | |
1931 rtWidget.left -= fHalf; | |
1932 rtWidget.width += fHalf; | |
1933 } else if (iHand == XFA_ATTRIBUTEENUM_Right) { | |
1934 rtWidget.left += fHalf; | |
1935 rtWidget.width -= fHalf; | |
1936 } | |
1937 break; | |
1938 } | |
1939 } | |
1940 XFA_BOX_Stroke_Rect(box, strokes, pGS, rtWidget, pMatrix); | |
1941 } | |
1942 void XFA_DrawBox(CXFA_Box box, | |
1943 CFX_Graphics* pGS, | |
1944 const CFX_RectF& rtWidget, | |
1945 CFX_Matrix* pMatrix, | |
1946 FX_DWORD dwFlags) { | |
1947 if (!box || box.GetPresence() != XFA_ATTRIBUTEENUM_Visible) { | |
1948 return; | |
1949 } | |
1950 int32_t iType = box.GetClassID(); | |
1951 if (iType != XFA_ELEMENT_Arc && iType != XFA_ELEMENT_Border && | |
1952 iType != XFA_ELEMENT_Rectangle) { | |
1953 return; | |
1954 } | |
1955 CXFA_StrokeArray strokes; | |
1956 if (!(dwFlags & XFA_DRAWBOX_ForceRound) && iType != XFA_ELEMENT_Arc) { | |
1957 box.GetStrokes(strokes); | |
1958 } | |
1959 XFA_BOX_Fill(box, strokes, pGS, rtWidget, pMatrix, dwFlags); | |
1960 XFA_BOX_Stroke(box, strokes, pGS, rtWidget, pMatrix, dwFlags); | |
1961 } | |
OLD | NEW |