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