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