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