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 "core/include/fxge/fx_ge.h" | |
8 | |
9 CFX_RenderDevice::CFX_RenderDevice() { | |
10 m_pDeviceDriver = NULL; | |
11 m_pBitmap = NULL; | |
12 } | |
13 CFX_RenderDevice::~CFX_RenderDevice() { | |
14 delete m_pDeviceDriver; | |
15 } | |
16 void CFX_RenderDevice::SetDeviceDriver(IFX_RenderDeviceDriver* pDriver) { | |
17 delete m_pDeviceDriver; | |
18 m_pDeviceDriver = pDriver; | |
19 InitDeviceInfo(); | |
20 } | |
21 void CFX_RenderDevice::InitDeviceInfo() { | |
22 m_Width = m_pDeviceDriver->GetDeviceCaps(FXDC_PIXEL_WIDTH); | |
23 m_Height = m_pDeviceDriver->GetDeviceCaps(FXDC_PIXEL_HEIGHT); | |
24 m_bpp = m_pDeviceDriver->GetDeviceCaps(FXDC_BITS_PIXEL); | |
25 m_RenderCaps = m_pDeviceDriver->GetDeviceCaps(FXDC_RENDER_CAPS); | |
26 m_DeviceClass = m_pDeviceDriver->GetDeviceCaps(FXDC_DEVICE_CLASS); | |
27 if (!m_pDeviceDriver->GetClipBox(&m_ClipBox)) { | |
28 m_ClipBox.left = 0; | |
29 m_ClipBox.top = 0; | |
30 m_ClipBox.right = m_Width; | |
31 m_ClipBox.bottom = m_Height; | |
32 } | |
33 } | |
34 FX_BOOL CFX_RenderDevice::StartRendering() { | |
35 return m_pDeviceDriver->StartRendering(); | |
36 } | |
37 void CFX_RenderDevice::EndRendering() { | |
38 m_pDeviceDriver->EndRendering(); | |
39 } | |
40 void CFX_RenderDevice::SaveState() { | |
41 m_pDeviceDriver->SaveState(); | |
42 } | |
43 void CFX_RenderDevice::RestoreState(FX_BOOL bKeepSaved) { | |
44 m_pDeviceDriver->RestoreState(bKeepSaved); | |
45 UpdateClipBox(); | |
46 } | |
47 int CFX_RenderDevice::GetDeviceCaps(int caps_id) const { | |
48 return m_pDeviceDriver->GetDeviceCaps(caps_id); | |
49 } | |
50 CFX_Matrix CFX_RenderDevice::GetCTM() const { | |
51 return m_pDeviceDriver->GetCTM(); | |
52 } | |
53 FX_BOOL CFX_RenderDevice::CreateCompatibleBitmap(CFX_DIBitmap* pDIB, | |
54 int width, | |
55 int height) const { | |
56 if (m_RenderCaps & FXRC_CMYK_OUTPUT) { | |
57 return pDIB->Create(width, height, m_RenderCaps & FXRC_ALPHA_OUTPUT | |
58 ? FXDIB_Cmyka | |
59 : FXDIB_Cmyk); | |
60 } | |
61 if (m_RenderCaps & FXRC_BYTEMASK_OUTPUT) { | |
62 return pDIB->Create(width, height, FXDIB_8bppMask); | |
63 } | |
64 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ | |
65 return pDIB->Create(width, height, m_RenderCaps & FXRC_ALPHA_OUTPUT | |
66 ? FXDIB_Argb | |
67 : FXDIB_Rgb32); | |
68 #else | |
69 return pDIB->Create( | |
70 width, height, m_RenderCaps & FXRC_ALPHA_OUTPUT ? FXDIB_Argb : FXDIB_Rgb); | |
71 #endif | |
72 } | |
73 FX_BOOL CFX_RenderDevice::SetClip_PathFill(const CFX_PathData* pPathData, | |
74 const CFX_Matrix* pObject2Device, | |
75 int fill_mode) { | |
76 if (!m_pDeviceDriver->SetClip_PathFill(pPathData, pObject2Device, | |
77 fill_mode)) { | |
78 return FALSE; | |
79 } | |
80 UpdateClipBox(); | |
81 return TRUE; | |
82 } | |
83 FX_BOOL CFX_RenderDevice::SetClip_PathStroke( | |
84 const CFX_PathData* pPathData, | |
85 const CFX_Matrix* pObject2Device, | |
86 const CFX_GraphStateData* pGraphState) { | |
87 if (!m_pDeviceDriver->SetClip_PathStroke(pPathData, pObject2Device, | |
88 pGraphState)) { | |
89 return FALSE; | |
90 } | |
91 UpdateClipBox(); | |
92 return TRUE; | |
93 } | |
94 FX_BOOL CFX_RenderDevice::SetClip_Rect(const FX_RECT& rect) { | |
95 CFX_PathData path; | |
96 path.AppendRect(rect.left, rect.bottom, rect.right, rect.top); | |
97 if (!SetClip_PathFill(&path, nullptr, FXFILL_WINDING)) | |
98 return FALSE; | |
99 | |
100 UpdateClipBox(); | |
101 return TRUE; | |
102 } | |
103 void CFX_RenderDevice::UpdateClipBox() { | |
104 if (m_pDeviceDriver->GetClipBox(&m_ClipBox)) { | |
105 return; | |
106 } | |
107 m_ClipBox.left = 0; | |
108 m_ClipBox.top = 0; | |
109 m_ClipBox.right = m_Width; | |
110 m_ClipBox.bottom = m_Height; | |
111 } | |
112 FX_BOOL CFX_RenderDevice::DrawPath(const CFX_PathData* pPathData, | |
113 const CFX_Matrix* pObject2Device, | |
114 const CFX_GraphStateData* pGraphState, | |
115 FX_DWORD fill_color, | |
116 FX_DWORD stroke_color, | |
117 int fill_mode, | |
118 int alpha_flag, | |
119 void* pIccTransform, | |
120 int blend_type) { | |
121 uint8_t fill_alpha, stroke_alpha; | |
122 if (FXGETFLAG_COLORTYPE(alpha_flag)) { | |
123 fill_alpha = FXGETFLAG_ALPHA_FILL(alpha_flag); | |
124 stroke_alpha = FXGETFLAG_ALPHA_STROKE(alpha_flag); | |
125 } else { | |
126 fill_alpha = FXARGB_A(fill_color); | |
127 stroke_alpha = FXARGB_A(stroke_color); | |
128 } | |
129 if ((fill_mode & 3) == 0) { | |
130 fill_alpha = 0; | |
131 } | |
132 if (!pGraphState) { | |
133 stroke_alpha = 0; | |
134 } | |
135 if (stroke_alpha == 0 && pPathData->GetPointCount() == 2) { | |
136 FX_PATHPOINT* pPoints = pPathData->GetPoints(); | |
137 FX_FLOAT x1, x2, y1, y2; | |
138 if (pObject2Device) { | |
139 pObject2Device->Transform(pPoints[0].m_PointX, pPoints[0].m_PointY, x1, | |
140 y1); | |
141 pObject2Device->Transform(pPoints[1].m_PointX, pPoints[1].m_PointY, x2, | |
142 y2); | |
143 } else { | |
144 x1 = pPoints[0].m_PointX; | |
145 y1 = pPoints[0].m_PointY; | |
146 x2 = pPoints[1].m_PointX; | |
147 y2 = pPoints[1].m_PointY; | |
148 } | |
149 DrawCosmeticLine(x1, y1, x2, y2, fill_color, fill_mode, alpha_flag, | |
150 pIccTransform, blend_type); | |
151 return TRUE; | |
152 } | |
153 if ((pPathData->GetPointCount() == 5 || pPathData->GetPointCount() == 4) && | |
154 stroke_alpha == 0) { | |
155 CFX_FloatRect rect_f; | |
156 if (!(fill_mode & FXFILL_RECT_AA) && | |
157 pPathData->IsRect(pObject2Device, &rect_f)) { | |
158 FX_RECT rect_i = rect_f.GetOutterRect(); | |
159 int width = (int)FXSYS_ceil(rect_f.right - rect_f.left); | |
160 if (width < 1) { | |
161 width = 1; | |
162 if (rect_i.left == rect_i.right) { | |
163 rect_i.right++; | |
164 } | |
165 } | |
166 int height = (int)FXSYS_ceil(rect_f.top - rect_f.bottom); | |
167 if (height < 1) { | |
168 height = 1; | |
169 if (rect_i.bottom == rect_i.top) { | |
170 rect_i.bottom++; | |
171 } | |
172 } | |
173 if (rect_i.Width() >= width + 1) { | |
174 if (rect_f.left - (FX_FLOAT)(rect_i.left) > | |
175 (FX_FLOAT)(rect_i.right) - rect_f.right) { | |
176 rect_i.left++; | |
177 } else { | |
178 rect_i.right--; | |
179 } | |
180 } | |
181 if (rect_i.Height() >= height + 1) { | |
182 if (rect_f.top - (FX_FLOAT)(rect_i.top) > | |
183 (FX_FLOAT)(rect_i.bottom) - rect_f.bottom) { | |
184 rect_i.top++; | |
185 } else { | |
186 rect_i.bottom--; | |
187 } | |
188 } | |
189 if (FillRect(&rect_i, fill_color, alpha_flag, pIccTransform, | |
190 blend_type)) { | |
191 return TRUE; | |
192 } | |
193 } | |
194 } | |
195 if ((fill_mode & 3) && stroke_alpha == 0 && !(fill_mode & FX_FILL_STROKE) && | |
196 !(fill_mode & FX_FILL_TEXT_MODE)) { | |
197 CFX_PathData newPath; | |
198 FX_BOOL bThin = FALSE; | |
199 if (pPathData->GetZeroAreaPath(newPath, (CFX_Matrix*)pObject2Device, bThin, | |
200 m_pDeviceDriver->GetDriverType())) { | |
201 CFX_GraphStateData graphState; | |
202 graphState.m_LineWidth = 0.0f; | |
203 FX_DWORD strokecolor = fill_color; | |
204 if (bThin) { | |
205 if (FXGETFLAG_COLORTYPE(alpha_flag)) { | |
206 FXSETFLAG_ALPHA_STROKE(alpha_flag, fill_alpha >> 2); | |
207 } else { | |
208 strokecolor = | |
209 (((fill_alpha >> 2) << 24) | (strokecolor & 0x00ffffff)); | |
210 } | |
211 } | |
212 CFX_Matrix* pMatrix = NULL; | |
213 if (pObject2Device && !pObject2Device->IsIdentity()) { | |
214 pMatrix = (CFX_Matrix*)pObject2Device; | |
215 } | |
216 int smooth_path = FX_ZEROAREA_FILL; | |
217 if (fill_mode & FXFILL_NOPATHSMOOTH) { | |
218 smooth_path |= FXFILL_NOPATHSMOOTH; | |
219 } | |
220 m_pDeviceDriver->DrawPath(&newPath, pMatrix, &graphState, 0, strokecolor, | |
221 smooth_path, alpha_flag, pIccTransform, | |
222 blend_type); | |
223 } | |
224 } | |
225 if ((fill_mode & 3) && fill_alpha && stroke_alpha < 0xff && | |
226 (fill_mode & FX_FILL_STROKE)) { | |
227 if (!(m_RenderCaps & FXRC_GET_BITS)) { | |
228 return FALSE; | |
229 } | |
230 CFX_FloatRect bbox; | |
231 if (pGraphState) { | |
232 bbox = pPathData->GetBoundingBox(pGraphState->m_LineWidth, | |
233 pGraphState->m_MiterLimit); | |
234 } else { | |
235 bbox = pPathData->GetBoundingBox(); | |
236 } | |
237 if (pObject2Device) { | |
238 bbox.Transform(pObject2Device); | |
239 } | |
240 CFX_Matrix ctm = GetCTM(); | |
241 FX_FLOAT fScaleX = FXSYS_fabs(ctm.a); | |
242 FX_FLOAT fScaleY = FXSYS_fabs(ctm.d); | |
243 FX_RECT rect = bbox.GetOutterRect(); | |
244 CFX_DIBitmap bitmap, Backdrop; | |
245 if (!CreateCompatibleBitmap(&bitmap, FXSYS_round(rect.Width() * fScaleX), | |
246 FXSYS_round(rect.Height() * fScaleY))) { | |
247 return FALSE; | |
248 } | |
249 if (bitmap.HasAlpha()) { | |
250 bitmap.Clear(0); | |
251 Backdrop.Copy(&bitmap); | |
252 } else { | |
253 if (!m_pDeviceDriver->GetDIBits(&bitmap, rect.left, rect.top, NULL)) { | |
254 return FALSE; | |
255 } | |
256 Backdrop.Copy(&bitmap); | |
257 } | |
258 CFX_FxgeDevice bitmap_device; | |
259 bitmap_device.Attach(&bitmap, 0, FALSE, &Backdrop, TRUE); | |
260 CFX_Matrix matrix; | |
261 if (pObject2Device) { | |
262 matrix = *pObject2Device; | |
263 } | |
264 matrix.TranslateI(-rect.left, -rect.top); | |
265 matrix.Concat(fScaleX, 0, 0, fScaleY, 0, 0); | |
266 if (!bitmap_device.GetDeviceDriver()->DrawPath( | |
267 pPathData, &matrix, pGraphState, fill_color, stroke_color, | |
268 fill_mode, alpha_flag, pIccTransform, blend_type)) { | |
269 return FALSE; | |
270 } | |
271 FX_RECT src_rect(0, 0, FXSYS_round(rect.Width() * fScaleX), | |
272 FXSYS_round(rect.Height() * fScaleY)); | |
273 return m_pDeviceDriver->SetDIBits(&bitmap, 0, &src_rect, rect.left, | |
274 rect.top, FXDIB_BLEND_NORMAL); | |
275 } | |
276 return m_pDeviceDriver->DrawPath(pPathData, pObject2Device, pGraphState, | |
277 fill_color, stroke_color, fill_mode, | |
278 alpha_flag, pIccTransform, blend_type); | |
279 } | |
280 FX_BOOL CFX_RenderDevice::SetPixel(int x, | |
281 int y, | |
282 FX_DWORD color, | |
283 int alpha_flag, | |
284 void* pIccTransform) { | |
285 if (m_pDeviceDriver->SetPixel(x, y, color, alpha_flag, pIccTransform)) { | |
286 return TRUE; | |
287 } | |
288 FX_RECT rect(x, y, x + 1, y + 1); | |
289 return FillRect(&rect, color, alpha_flag, pIccTransform); | |
290 } | |
291 FX_BOOL CFX_RenderDevice::FillRect(const FX_RECT* pRect, | |
292 FX_DWORD fill_color, | |
293 int alpha_flag, | |
294 void* pIccTransform, | |
295 int blend_type) { | |
296 if (m_pDeviceDriver->FillRect(pRect, fill_color, alpha_flag, pIccTransform, | |
297 blend_type)) { | |
298 return TRUE; | |
299 } | |
300 if (!(m_RenderCaps & FXRC_GET_BITS)) { | |
301 return FALSE; | |
302 } | |
303 CFX_DIBitmap bitmap; | |
304 if (!CreateCompatibleBitmap(&bitmap, pRect->Width(), pRect->Height())) { | |
305 return FALSE; | |
306 } | |
307 if (!m_pDeviceDriver->GetDIBits(&bitmap, pRect->left, pRect->top)) { | |
308 return FALSE; | |
309 } | |
310 if (!bitmap.CompositeRect(0, 0, pRect->Width(), pRect->Height(), fill_color, | |
311 alpha_flag, pIccTransform)) { | |
312 return FALSE; | |
313 } | |
314 FX_RECT src_rect(0, 0, pRect->Width(), pRect->Height()); | |
315 m_pDeviceDriver->SetDIBits(&bitmap, 0, &src_rect, pRect->left, pRect->top, | |
316 FXDIB_BLEND_NORMAL); | |
317 return TRUE; | |
318 } | |
319 FX_BOOL CFX_RenderDevice::DrawCosmeticLine(FX_FLOAT x1, | |
320 FX_FLOAT y1, | |
321 FX_FLOAT x2, | |
322 FX_FLOAT y2, | |
323 FX_DWORD color, | |
324 int fill_mode, | |
325 int alpha_flag, | |
326 void* pIccTransform, | |
327 int blend_type) { | |
328 if (((m_RenderCaps & FXRC_ALPHA_PATH) && | |
329 (FXGETFLAG_COLORTYPE(alpha_flag) && | |
330 FXGETFLAG_ALPHA_FILL(alpha_flag) == 0xff)) || | |
331 color >= 0xff000000) { | |
332 if (m_pDeviceDriver->DrawCosmeticLine(x1, y1, x2, y2, color, alpha_flag, | |
333 pIccTransform, blend_type)) { | |
334 return TRUE; | |
335 } | |
336 } | |
337 CFX_GraphStateData graph_state; | |
338 CFX_PathData path; | |
339 path.SetPointCount(2); | |
340 path.SetPoint(0, x1, y1, FXPT_MOVETO); | |
341 path.SetPoint(1, x2, y2, FXPT_LINETO); | |
342 return m_pDeviceDriver->DrawPath(&path, NULL, &graph_state, 0, color, | |
343 fill_mode, alpha_flag, pIccTransform, | |
344 blend_type); | |
345 } | |
346 FX_BOOL CFX_RenderDevice::GetDIBits(CFX_DIBitmap* pBitmap, | |
347 int left, | |
348 int top, | |
349 void* pIccTransform) { | |
350 if (!(m_RenderCaps & FXRC_GET_BITS)) { | |
351 return FALSE; | |
352 } | |
353 return m_pDeviceDriver->GetDIBits(pBitmap, left, top, pIccTransform); | |
354 } | |
355 CFX_DIBitmap* CFX_RenderDevice::GetBackDrop() { | |
356 return m_pDeviceDriver->GetBackDrop(); | |
357 } | |
358 FX_BOOL CFX_RenderDevice::SetDIBits(const CFX_DIBSource* pBitmap, | |
359 int left, | |
360 int top, | |
361 int blend_mode, | |
362 void* pIccTransform) { | |
363 ASSERT(!pBitmap->IsAlphaMask()); | |
364 CFX_Matrix ctm = GetCTM(); | |
365 FX_FLOAT fScaleX = FXSYS_fabs(ctm.a); | |
366 FX_FLOAT fScaleY = FXSYS_fabs(ctm.d); | |
367 FX_RECT dest_rect(left, top, | |
368 FXSYS_round(left + pBitmap->GetWidth() / fScaleX), | |
369 FXSYS_round(top + pBitmap->GetHeight() / fScaleY)); | |
370 dest_rect.Intersect(m_ClipBox); | |
371 if (dest_rect.IsEmpty()) { | |
372 return TRUE; | |
373 } | |
374 FX_RECT src_rect(dest_rect.left - left, dest_rect.top - top, | |
375 dest_rect.left - left + dest_rect.Width(), | |
376 dest_rect.top - top + dest_rect.Height()); | |
377 src_rect.left = FXSYS_round(src_rect.left * fScaleX); | |
378 src_rect.top = FXSYS_round(src_rect.top * fScaleY); | |
379 src_rect.right = FXSYS_round(src_rect.right * fScaleX); | |
380 src_rect.bottom = FXSYS_round(src_rect.bottom * fScaleY); | |
381 if ((blend_mode != FXDIB_BLEND_NORMAL && !(m_RenderCaps & FXRC_BLEND_MODE)) || | |
382 (pBitmap->HasAlpha() && !(m_RenderCaps & FXRC_ALPHA_IMAGE))) { | |
383 if (!(m_RenderCaps & FXRC_GET_BITS)) { | |
384 return FALSE; | |
385 } | |
386 int bg_pixel_width = FXSYS_round(dest_rect.Width() * fScaleX); | |
387 int bg_pixel_height = FXSYS_round(dest_rect.Height() * fScaleY); | |
388 CFX_DIBitmap background; | |
389 if (!background.Create( | |
390 bg_pixel_width, bg_pixel_height, | |
391 (m_RenderCaps & FXRC_CMYK_OUTPUT) ? FXDIB_Cmyk : FXDIB_Rgb32)) { | |
392 return FALSE; | |
393 } | |
394 if (!m_pDeviceDriver->GetDIBits(&background, dest_rect.left, | |
395 dest_rect.top)) { | |
396 return FALSE; | |
397 } | |
398 if (!background.CompositeBitmap(0, 0, bg_pixel_width, bg_pixel_height, | |
399 pBitmap, src_rect.left, src_rect.top, | |
400 blend_mode, NULL, FALSE, pIccTransform)) { | |
401 return FALSE; | |
402 } | |
403 FX_RECT src_rect(0, 0, bg_pixel_width, bg_pixel_height); | |
404 return m_pDeviceDriver->SetDIBits(&background, 0, &src_rect, dest_rect.left, | |
405 dest_rect.top, FXDIB_BLEND_NORMAL); | |
406 } | |
407 return m_pDeviceDriver->SetDIBits(pBitmap, 0, &src_rect, dest_rect.left, | |
408 dest_rect.top, blend_mode, 0, | |
409 pIccTransform); | |
410 } | |
411 FX_BOOL CFX_RenderDevice::StretchDIBits(const CFX_DIBSource* pBitmap, | |
412 int left, | |
413 int top, | |
414 int dest_width, | |
415 int dest_height, | |
416 FX_DWORD flags, | |
417 void* pIccTransform, | |
418 int blend_mode) { | |
419 FX_RECT dest_rect(left, top, left + dest_width, top + dest_height); | |
420 FX_RECT clip_box = m_ClipBox; | |
421 clip_box.Intersect(dest_rect); | |
422 if (clip_box.IsEmpty()) { | |
423 return TRUE; | |
424 } | |
425 return m_pDeviceDriver->StretchDIBits(pBitmap, 0, left, top, dest_width, | |
426 dest_height, &clip_box, flags, 0, | |
427 pIccTransform, blend_mode); | |
428 } | |
429 FX_BOOL CFX_RenderDevice::SetBitMask(const CFX_DIBSource* pBitmap, | |
430 int left, | |
431 int top, | |
432 FX_DWORD argb, | |
433 int alpha_flag, | |
434 void* pIccTransform) { | |
435 FX_RECT src_rect(0, 0, pBitmap->GetWidth(), pBitmap->GetHeight()); | |
436 return m_pDeviceDriver->SetDIBits(pBitmap, argb, &src_rect, left, top, | |
437 FXDIB_BLEND_NORMAL, alpha_flag, | |
438 pIccTransform); | |
439 } | |
440 FX_BOOL CFX_RenderDevice::StretchBitMask(const CFX_DIBSource* pBitmap, | |
441 int left, | |
442 int top, | |
443 int dest_width, | |
444 int dest_height, | |
445 FX_DWORD argb, | |
446 FX_DWORD flags, | |
447 int alpha_flag, | |
448 void* pIccTransform) { | |
449 FX_RECT dest_rect(left, top, left + dest_width, top + dest_height); | |
450 FX_RECT clip_box = m_ClipBox; | |
451 clip_box.Intersect(dest_rect); | |
452 return m_pDeviceDriver->StretchDIBits(pBitmap, argb, left, top, dest_width, | |
453 dest_height, &clip_box, flags, | |
454 alpha_flag, pIccTransform); | |
455 } | |
456 FX_BOOL CFX_RenderDevice::StartDIBits(const CFX_DIBSource* pBitmap, | |
457 int bitmap_alpha, | |
458 FX_DWORD argb, | |
459 const CFX_Matrix* pMatrix, | |
460 FX_DWORD flags, | |
461 void*& handle, | |
462 int alpha_flag, | |
463 void* pIccTransform, | |
464 int blend_mode) { | |
465 return m_pDeviceDriver->StartDIBits(pBitmap, bitmap_alpha, argb, pMatrix, | |
466 flags, handle, alpha_flag, pIccTransform, | |
467 blend_mode); | |
468 } | |
469 FX_BOOL CFX_RenderDevice::ContinueDIBits(void* handle, IFX_Pause* pPause) { | |
470 return m_pDeviceDriver->ContinueDIBits(handle, pPause); | |
471 } | |
472 void CFX_RenderDevice::CancelDIBits(void* handle) { | |
473 m_pDeviceDriver->CancelDIBits(handle); | |
474 } | |
OLD | NEW |