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/agg/fx_agg_driver.h"
8
9 #include <algorithm>
10 #include <utility>
11
12 #include "core/fxcodec/fx_codec.h"
13 #include "core/fxcrt/fx_memory.h"
14 #include "core/fxge/cfx_fxgedevice.h"
15 #include "core/fxge/cfx_gemodule.h"
16 #include "core/fxge/cfx_graphstatedata.h"
17 #include "core/fxge/cfx_pathdata.h"
18 #include "core/fxge/cfx_renderdevice.h"
19 #include "core/fxge/dib/dib_int.h"
20 #include "core/fxge/ge/cfx_cliprgn.h"
21 #include "core/fxge/ge/fx_text_int.h"
22 #include "core/fxge/ifx_renderdevicedriver.h"
23 #include "third_party/agg23/agg_conv_dash.h"
24 #include "third_party/agg23/agg_conv_stroke.h"
25 #include "third_party/agg23/agg_curves.h"
26 #include "third_party/agg23/agg_path_storage.h"
27 #include "third_party/agg23/agg_pixfmt_gray.h"
28 #include "third_party/agg23/agg_rasterizer_scanline_aa.h"
29 #include "third_party/agg23/agg_renderer_scanline.h"
30 #include "third_party/agg23/agg_scanline_u.h"
31 #include "third_party/base/ptr_util.h"
32
33 namespace {
34
HardClip(const CFX_PointF & pos)35 CFX_PointF HardClip(const CFX_PointF& pos) {
36 return CFX_PointF(std::max(std::min(pos.x, 50000.0f), -50000.0f),
37 std::max(std::min(pos.y, 50000.0f), -50000.0f));
38 }
39
RgbByteOrderSetPixel(CFX_DIBitmap * pBitmap,int x,int y,uint32_t argb)40 void RgbByteOrderSetPixel(CFX_DIBitmap* pBitmap, int x, int y, uint32_t argb) {
41 if (x < 0 || x >= pBitmap->GetWidth() || y < 0 || y >= pBitmap->GetHeight())
42 return;
43
44 uint8_t* pos = (uint8_t*)pBitmap->GetBuffer() + y * pBitmap->GetPitch() +
45 x * pBitmap->GetBPP() / 8;
46 if (pBitmap->GetFormat() == FXDIB_Argb) {
47 FXARGB_SETRGBORDERDIB(pos, argb);
48 return;
49 }
50
51 int alpha = FXARGB_A(argb);
52 pos[0] = (FXARGB_R(argb) * alpha + pos[0] * (255 - alpha)) / 255;
53 pos[1] = (FXARGB_G(argb) * alpha + pos[1] * (255 - alpha)) / 255;
54 pos[2] = (FXARGB_B(argb) * alpha + pos[2] * (255 - alpha)) / 255;
55 }
56
RgbByteOrderCompositeRect(CFX_DIBitmap * pBitmap,int left,int top,int width,int height,FX_ARGB argb)57 void RgbByteOrderCompositeRect(CFX_DIBitmap* pBitmap,
58 int left,
59 int top,
60 int width,
61 int height,
62 FX_ARGB argb) {
63 int src_alpha = FXARGB_A(argb);
64 if (src_alpha == 0)
65 return;
66
67 FX_RECT rect(left, top, left + width, top + height);
68 rect.Intersect(0, 0, pBitmap->GetWidth(), pBitmap->GetHeight());
69 width = rect.Width();
70 int src_r = FXARGB_R(argb);
71 int src_g = FXARGB_G(argb);
72 int src_b = FXARGB_B(argb);
73 int Bpp = pBitmap->GetBPP() / 8;
74 bool bAlpha = pBitmap->HasAlpha();
75 int dib_argb = FXARGB_TOBGRORDERDIB(argb);
76 uint8_t* pBuffer = pBitmap->GetBuffer();
77 if (src_alpha == 255) {
78 for (int row = rect.top; row < rect.bottom; row++) {
79 uint8_t* dest_scan =
80 pBuffer + row * pBitmap->GetPitch() + rect.left * Bpp;
81 if (Bpp == 4) {
82 uint32_t* scan = (uint32_t*)dest_scan;
83 for (int col = 0; col < width; col++)
84 *scan++ = dib_argb;
85 } else {
86 for (int col = 0; col < width; col++) {
87 *dest_scan++ = src_r;
88 *dest_scan++ = src_g;
89 *dest_scan++ = src_b;
90 }
91 }
92 }
93 return;
94 }
95 for (int row = rect.top; row < rect.bottom; row++) {
96 uint8_t* dest_scan = pBuffer + row * pBitmap->GetPitch() + rect.left * Bpp;
97 if (bAlpha) {
98 for (int col = 0; col < width; col++) {
99 uint8_t back_alpha = dest_scan[3];
100 if (back_alpha == 0) {
101 FXARGB_SETRGBORDERDIB(dest_scan,
102 FXARGB_MAKE(src_alpha, src_r, src_g, src_b));
103 dest_scan += 4;
104 continue;
105 }
106 uint8_t dest_alpha =
107 back_alpha + src_alpha - back_alpha * src_alpha / 255;
108 dest_scan[3] = dest_alpha;
109 int alpha_ratio = src_alpha * 255 / dest_alpha;
110 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
111 dest_scan++;
112 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
113 dest_scan++;
114 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
115 dest_scan += 2;
116 }
117 } else {
118 for (int col = 0; col < width; col++) {
119 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha);
120 dest_scan++;
121 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha);
122 dest_scan++;
123 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha);
124 dest_scan++;
125 if (Bpp == 4)
126 dest_scan++;
127 }
128 }
129 }
130 }
131
RgbByteOrderTransferBitmap(CFX_DIBitmap * pBitmap,int dest_left,int dest_top,int width,int height,const CFX_DIBSource * pSrcBitmap,int src_left,int src_top)132 void RgbByteOrderTransferBitmap(CFX_DIBitmap* pBitmap,
133 int dest_left,
134 int dest_top,
135 int width,
136 int height,
137 const CFX_DIBSource* pSrcBitmap,
138 int src_left,
139 int src_top) {
140 if (!pBitmap)
141 return;
142
143 pBitmap->GetOverlapRect(dest_left, dest_top, width, height,
144 pSrcBitmap->GetWidth(), pSrcBitmap->GetHeight(),
145 src_left, src_top, nullptr);
146 if (width == 0 || height == 0)
147 return;
148
149 int Bpp = pBitmap->GetBPP() / 8;
150 FXDIB_Format dest_format = pBitmap->GetFormat();
151 FXDIB_Format src_format = pSrcBitmap->GetFormat();
152 int pitch = pBitmap->GetPitch();
153 uint8_t* buffer = pBitmap->GetBuffer();
154 if (dest_format == src_format) {
155 for (int row = 0; row < height; row++) {
156 uint8_t* dest_scan = buffer + (dest_top + row) * pitch + dest_left * Bpp;
157 uint8_t* src_scan =
158 (uint8_t*)pSrcBitmap->GetScanline(src_top + row) + src_left * Bpp;
159 if (Bpp == 4) {
160 for (int col = 0; col < width; col++) {
161 FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_scan[3], src_scan[0],
162 src_scan[1], src_scan[2]));
163 dest_scan += 4;
164 src_scan += 4;
165 }
166 } else {
167 for (int col = 0; col < width; col++) {
168 *dest_scan++ = src_scan[2];
169 *dest_scan++ = src_scan[1];
170 *dest_scan++ = src_scan[0];
171 src_scan += 3;
172 }
173 }
174 }
175 return;
176 }
177
178 uint8_t* dest_buf = buffer + dest_top * pitch + dest_left * Bpp;
179 if (dest_format == FXDIB_Rgb) {
180 if (src_format == FXDIB_Rgb32) {
181 for (int row = 0; row < height; row++) {
182 uint8_t* dest_scan = dest_buf + row * pitch;
183 uint8_t* src_scan =
184 (uint8_t*)pSrcBitmap->GetScanline(src_top + row) + src_left * 4;
185 for (int col = 0; col < width; col++) {
186 *dest_scan++ = src_scan[2];
187 *dest_scan++ = src_scan[1];
188 *dest_scan++ = src_scan[0];
189 src_scan += 4;
190 }
191 }
192 } else {
193 ASSERT(false);
194 }
195 return;
196 }
197
198 if (dest_format == FXDIB_Argb || dest_format == FXDIB_Rgb32) {
199 if (src_format == FXDIB_Rgb) {
200 for (int row = 0; row < height; row++) {
201 uint8_t* dest_scan = (uint8_t*)(dest_buf + row * pitch);
202 uint8_t* src_scan =
203 (uint8_t*)pSrcBitmap->GetScanline(src_top + row) + src_left * 3;
204 for (int col = 0; col < width; col++) {
205 FXARGB_SETDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[0], src_scan[1],
206 src_scan[2]));
207 dest_scan += 4;
208 src_scan += 3;
209 }
210 }
211 } else if (src_format == FXDIB_Rgb32) {
212 ASSERT(dest_format == FXDIB_Argb);
213 for (int row = 0; row < height; row++) {
214 uint8_t* dest_scan = dest_buf + row * pitch;
215 uint8_t* src_scan =
216 (uint8_t*)(pSrcBitmap->GetScanline(src_top + row) + src_left * 4);
217 for (int col = 0; col < width; col++) {
218 FXARGB_SETDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[0], src_scan[1],
219 src_scan[2]));
220 src_scan += 4;
221 dest_scan += 4;
222 }
223 }
224 }
225 return;
226 }
227
228 ASSERT(false);
229 }
230
DefaultCMYK2ARGB(FX_CMYK cmyk,uint8_t alpha)231 FX_ARGB DefaultCMYK2ARGB(FX_CMYK cmyk, uint8_t alpha) {
232 uint8_t r, g, b;
233 AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk),
234 FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk), r, g, b);
235 return ArgbEncode(alpha, r, g, b);
236 }
237
DibSetPixel(CFX_DIBitmap * pDevice,int x,int y,uint32_t color,int alpha_flag,void * pIccTransform)238 bool DibSetPixel(CFX_DIBitmap* pDevice,
239 int x,
240 int y,
241 uint32_t color,
242 int alpha_flag,
243 void* pIccTransform) {
244 bool bObjCMYK = !!FXGETFLAG_COLORTYPE(alpha_flag);
245 int alpha = bObjCMYK ? FXGETFLAG_ALPHA_FILL(alpha_flag) : FXARGB_A(color);
246 if (pIccTransform) {
247 CCodec_IccModule* pIccModule =
248 CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
249 color = bObjCMYK ? FXCMYK_TODIB(color) : FXARGB_TODIB(color);
250 pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&color,
251 (uint8_t*)&color, 1);
252 color = bObjCMYK ? FXCMYK_TODIB(color) : FXARGB_TODIB(color);
253 if (!pDevice->IsCmykImage()) {
254 color = (color & 0xffffff) | (alpha << 24);
255 }
256 } else {
257 if (pDevice->IsCmykImage()) {
258 if (!bObjCMYK)
259 return false;
260 } else {
261 if (bObjCMYK)
262 color = DefaultCMYK2ARGB(color, alpha);
263 }
264 }
265 pDevice->SetPixel(x, y, color);
266 if (pDevice->m_pAlphaMask) {
267 pDevice->m_pAlphaMask->SetPixel(x, y, alpha << 24);
268 }
269 return true;
270 }
271
272 } // namespace
273
BuildPath(const CFX_PathData * pPathData,const CFX_Matrix * pObject2Device)274 void CAgg_PathData::BuildPath(const CFX_PathData* pPathData,
275 const CFX_Matrix* pObject2Device) {
276 const std::vector<FX_PATHPOINT>& pPoints = pPathData->GetPoints();
277 for (size_t i = 0; i < pPoints.size(); i++) {
278 CFX_PointF pos = pPoints[i].m_Point;
279 if (pObject2Device)
280 pos = pObject2Device->Transform(pos);
281
282 pos = HardClip(pos);
283 FXPT_TYPE point_type = pPoints[i].m_Type;
284 if (point_type == FXPT_TYPE::MoveTo) {
285 m_PathData.move_to(pos.x, pos.y);
286 } else if (point_type == FXPT_TYPE::LineTo) {
287 if (pPoints[i - 1].IsTypeAndOpen(FXPT_TYPE::MoveTo) &&
288 (i == pPoints.size() - 1 ||
289 pPoints[i + 1].IsTypeAndOpen(FXPT_TYPE::MoveTo)) &&
290 pPoints[i].m_Point == pPoints[i - 1].m_Point) {
291 pos.x += 1;
292 }
293 m_PathData.line_to(pos.x, pos.y);
294 } else if (point_type == FXPT_TYPE::BezierTo) {
295 CFX_PointF pos0 = pPoints[i - 1].m_Point;
296 CFX_PointF pos2 = pPoints[i + 1].m_Point;
297 CFX_PointF pos3 = pPoints[i + 2].m_Point;
298 if (pObject2Device) {
299 pos0 = pObject2Device->Transform(pos0);
300 pos2 = pObject2Device->Transform(pos2);
301 pos3 = pObject2Device->Transform(pos3);
302 }
303 pos0 = HardClip(pos0);
304 pos2 = HardClip(pos2);
305 pos3 = HardClip(pos3);
306 agg::curve4 curve(pos0.x, pos0.y, pos.x, pos.y, pos2.x, pos2.y, pos3.x,
307 pos3.y);
308 i += 2;
309 m_PathData.add_path_curve(curve);
310 }
311 if (pPoints[i].m_CloseFigure)
312 m_PathData.end_poly();
313 }
314 }
315
316 namespace agg {
317
318 template <class BaseRenderer>
319 class renderer_scanline_aa_offset {
320 public:
321 typedef BaseRenderer base_ren_type;
322 typedef typename base_ren_type::color_type color_type;
renderer_scanline_aa_offset(base_ren_type & ren,unsigned left,unsigned top)323 renderer_scanline_aa_offset(base_ren_type& ren, unsigned left, unsigned top)
324 : m_ren(&ren), m_left(left), m_top(top) {}
color(const color_type & c)325 void color(const color_type& c) { m_color = c; }
color() const326 const color_type& color() const { return m_color; }
prepare(unsigned)327 void prepare(unsigned) {}
328 template <class Scanline>
render(const Scanline & sl)329 void render(const Scanline& sl) {
330 int y = sl.y();
331 unsigned num_spans = sl.num_spans();
332 typename Scanline::const_iterator span = sl.begin();
333 for (;;) {
334 int x = span->x;
335 if (span->len > 0) {
336 m_ren->blend_solid_hspan(x - m_left, y - m_top, (unsigned)span->len,
337 m_color, span->covers);
338 } else {
339 m_ren->blend_hline(x - m_left, y - m_top, (unsigned)(x - span->len - 1),
340 m_color, *(span->covers));
341 }
342 if (--num_spans == 0) {
343 break;
344 }
345 ++span;
346 }
347 }
348
349 private:
350 base_ren_type* m_ren;
351 color_type m_color;
352 unsigned m_left, m_top;
353 };
354
355 } // namespace agg
356
RasterizeStroke(agg::rasterizer_scanline_aa & rasterizer,agg::path_storage & path_data,const CFX_Matrix * pObject2Device,const CFX_GraphStateData * pGraphState,FX_FLOAT scale=1.0f,bool bStrokeAdjust=false,bool bTextMode=false)357 static void RasterizeStroke(agg::rasterizer_scanline_aa& rasterizer,
358 agg::path_storage& path_data,
359 const CFX_Matrix* pObject2Device,
360 const CFX_GraphStateData* pGraphState,
361 FX_FLOAT scale = 1.0f,
362 bool bStrokeAdjust = false,
363 bool bTextMode = false) {
364 agg::line_cap_e cap;
365 switch (pGraphState->m_LineCap) {
366 case CFX_GraphStateData::LineCapRound:
367 cap = agg::round_cap;
368 break;
369 case CFX_GraphStateData::LineCapSquare:
370 cap = agg::square_cap;
371 break;
372 default:
373 cap = agg::butt_cap;
374 break;
375 }
376 agg::line_join_e join;
377 switch (pGraphState->m_LineJoin) {
378 case CFX_GraphStateData::LineJoinRound:
379 join = agg::round_join;
380 break;
381 case CFX_GraphStateData::LineJoinBevel:
382 join = agg::bevel_join;
383 break;
384 default:
385 join = agg::miter_join_revert;
386 break;
387 }
388 FX_FLOAT width = pGraphState->m_LineWidth * scale;
389 FX_FLOAT unit = 1.f;
390 if (pObject2Device) {
391 unit =
392 1.0f / ((pObject2Device->GetXUnit() + pObject2Device->GetYUnit()) / 2);
393 }
394 if (width < unit) {
395 width = unit;
396 }
397 if (pGraphState->m_DashArray) {
398 typedef agg::conv_dash<agg::path_storage> dash_converter;
399 dash_converter dash(path_data);
400 for (int i = 0; i < (pGraphState->m_DashCount + 1) / 2; i++) {
401 FX_FLOAT on = pGraphState->m_DashArray[i * 2];
402 if (on <= 0.000001f) {
403 on = 1.0f / 10;
404 }
405 FX_FLOAT off = i * 2 + 1 == pGraphState->m_DashCount
406 ? on
407 : pGraphState->m_DashArray[i * 2 + 1];
408 if (off < 0) {
409 off = 0;
410 }
411 dash.add_dash(on * scale, off * scale);
412 }
413 dash.dash_start(pGraphState->m_DashPhase * scale);
414 typedef agg::conv_stroke<dash_converter> dash_stroke;
415 dash_stroke stroke(dash);
416 stroke.line_join(join);
417 stroke.line_cap(cap);
418 stroke.miter_limit(pGraphState->m_MiterLimit);
419 stroke.width(width);
420 rasterizer.add_path_transformed(stroke, pObject2Device);
421 } else {
422 agg::conv_stroke<agg::path_storage> stroke(path_data);
423 stroke.line_join(join);
424 stroke.line_cap(cap);
425 stroke.miter_limit(pGraphState->m_MiterLimit);
426 stroke.width(width);
427 rasterizer.add_path_transformed(stroke, pObject2Device);
428 }
429 }
430
CFX_AggDeviceDriver(CFX_DIBitmap * pBitmap,bool bRgbByteOrder,CFX_DIBitmap * pOriDevice,bool bGroupKnockout)431 CFX_AggDeviceDriver::CFX_AggDeviceDriver(CFX_DIBitmap* pBitmap,
432 bool bRgbByteOrder,
433 CFX_DIBitmap* pOriDevice,
434 bool bGroupKnockout)
435 : m_pBitmap(pBitmap),
436 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
437 m_pPlatformGraphics(nullptr),
438 #endif
439 m_FillFlags(0),
440 m_bRgbByteOrder(bRgbByteOrder),
441 m_pOriDevice(pOriDevice),
442 m_bGroupKnockout(bGroupKnockout) {
443 InitPlatform();
444 }
445
~CFX_AggDeviceDriver()446 CFX_AggDeviceDriver::~CFX_AggDeviceDriver() {
447 DestroyPlatform();
448 }
449
GetBuffer() const450 uint8_t* CFX_AggDeviceDriver::GetBuffer() const {
451 return m_pBitmap->GetBuffer();
452 }
453
454 #if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_
InitPlatform()455 void CFX_AggDeviceDriver::InitPlatform() {}
456
DestroyPlatform()457 void CFX_AggDeviceDriver::DestroyPlatform() {}
458
DrawDeviceText(int nChars,const FXTEXT_CHARPOS * pCharPos,CFX_Font * pFont,const CFX_Matrix * pObject2Device,FX_FLOAT font_size,uint32_t color)459 bool CFX_AggDeviceDriver::DrawDeviceText(int nChars,
460 const FXTEXT_CHARPOS* pCharPos,
461 CFX_Font* pFont,
462 const CFX_Matrix* pObject2Device,
463 FX_FLOAT font_size,
464 uint32_t color) {
465 return false;
466 }
467 #endif // _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_
468
GetDeviceCaps(int caps_id) const469 int CFX_AggDeviceDriver::GetDeviceCaps(int caps_id) const {
470 switch (caps_id) {
471 case FXDC_DEVICE_CLASS:
472 return FXDC_DISPLAY;
473 case FXDC_PIXEL_WIDTH:
474 return m_pBitmap->GetWidth();
475 case FXDC_PIXEL_HEIGHT:
476 return m_pBitmap->GetHeight();
477 case FXDC_BITS_PIXEL:
478 return m_pBitmap->GetBPP();
479 case FXDC_HORZ_SIZE:
480 case FXDC_VERT_SIZE:
481 return 0;
482 case FXDC_RENDER_CAPS: {
483 int flags = FXRC_GET_BITS | FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE |
484 FXRC_BLEND_MODE | FXRC_SOFT_CLIP;
485 if (m_pBitmap->HasAlpha()) {
486 flags |= FXRC_ALPHA_OUTPUT;
487 } else if (m_pBitmap->IsAlphaMask()) {
488 if (m_pBitmap->GetBPP() == 1) {
489 flags |= FXRC_BITMASK_OUTPUT;
490 } else {
491 flags |= FXRC_BYTEMASK_OUTPUT;
492 }
493 }
494 if (m_pBitmap->IsCmykImage()) {
495 flags |= FXRC_CMYK_OUTPUT;
496 }
497 return flags;
498 }
499 }
500 return 0;
501 }
502
SaveState()503 void CFX_AggDeviceDriver::SaveState() {
504 std::unique_ptr<CFX_ClipRgn> pClip;
505 if (m_pClipRgn)
506 pClip = pdfium::MakeUnique<CFX_ClipRgn>(*m_pClipRgn);
507 m_StateStack.push_back(std::move(pClip));
508 }
509
RestoreState(bool bKeepSaved)510 void CFX_AggDeviceDriver::RestoreState(bool bKeepSaved) {
511 m_pClipRgn.reset();
512
513 if (m_StateStack.empty())
514 return;
515
516 if (bKeepSaved) {
517 if (m_StateStack.back())
518 m_pClipRgn = pdfium::MakeUnique<CFX_ClipRgn>(*m_StateStack.back());
519 } else {
520 m_pClipRgn = std::move(m_StateStack.back());
521 m_StateStack.pop_back();
522 }
523 }
524
SetClipMask(agg::rasterizer_scanline_aa & rasterizer)525 void CFX_AggDeviceDriver::SetClipMask(agg::rasterizer_scanline_aa& rasterizer) {
526 FX_RECT path_rect(rasterizer.min_x(), rasterizer.min_y(),
527 rasterizer.max_x() + 1, rasterizer.max_y() + 1);
528 path_rect.Intersect(m_pClipRgn->GetBox());
529 CFX_DIBitmapRef mask;
530 CFX_DIBitmap* pThisLayer = mask.Emplace();
531 pThisLayer->Create(path_rect.Width(), path_rect.Height(), FXDIB_8bppMask);
532 pThisLayer->Clear(0);
533 agg::rendering_buffer raw_buf(pThisLayer->GetBuffer(), pThisLayer->GetWidth(),
534 pThisLayer->GetHeight(),
535 pThisLayer->GetPitch());
536 agg::pixfmt_gray8 pixel_buf(raw_buf);
537 agg::renderer_base<agg::pixfmt_gray8> base_buf(pixel_buf);
538 agg::renderer_scanline_aa_offset<agg::renderer_base<agg::pixfmt_gray8> >
539 final_render(base_buf, path_rect.left, path_rect.top);
540 final_render.color(agg::gray8(255));
541 agg::scanline_u8 scanline;
542 agg::render_scanlines(rasterizer, scanline, final_render,
543 (m_FillFlags & FXFILL_NOPATHSMOOTH) != 0);
544 m_pClipRgn->IntersectMaskF(path_rect.left, path_rect.top, mask);
545 }
546
SetClip_PathFill(const CFX_PathData * pPathData,const CFX_Matrix * pObject2Device,int fill_mode)547 bool CFX_AggDeviceDriver::SetClip_PathFill(const CFX_PathData* pPathData,
548 const CFX_Matrix* pObject2Device,
549 int fill_mode) {
550 m_FillFlags = fill_mode;
551 if (!m_pClipRgn) {
552 m_pClipRgn = pdfium::MakeUnique<CFX_ClipRgn>(
553 GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT));
554 }
555 size_t size = pPathData->GetPoints().size();
556 if (size == 5 || size == 4) {
557 CFX_FloatRect rectf;
558 if (pPathData->IsRect(pObject2Device, &rectf)) {
559 rectf.Intersect(
560 CFX_FloatRect(0, 0, (FX_FLOAT)GetDeviceCaps(FXDC_PIXEL_WIDTH),
561 (FX_FLOAT)GetDeviceCaps(FXDC_PIXEL_HEIGHT)));
562 FX_RECT rect = rectf.GetOuterRect();
563 m_pClipRgn->IntersectRect(rect);
564 return true;
565 }
566 }
567 CAgg_PathData path_data;
568 path_data.BuildPath(pPathData, pObject2Device);
569 path_data.m_PathData.end_poly();
570 agg::rasterizer_scanline_aa rasterizer;
571 rasterizer.clip_box(0.0f, 0.0f, (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_WIDTH)),
572 (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_HEIGHT)));
573 rasterizer.add_path(path_data.m_PathData);
574 rasterizer.filling_rule((fill_mode & 3) == FXFILL_WINDING
575 ? agg::fill_non_zero
576 : agg::fill_even_odd);
577 SetClipMask(rasterizer);
578 return true;
579 }
580
SetClip_PathStroke(const CFX_PathData * pPathData,const CFX_Matrix * pObject2Device,const CFX_GraphStateData * pGraphState)581 bool CFX_AggDeviceDriver::SetClip_PathStroke(
582 const CFX_PathData* pPathData,
583 const CFX_Matrix* pObject2Device,
584 const CFX_GraphStateData* pGraphState) {
585 if (!m_pClipRgn) {
586 m_pClipRgn = pdfium::MakeUnique<CFX_ClipRgn>(
587 GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT));
588 }
589 CAgg_PathData path_data;
590 path_data.BuildPath(pPathData, nullptr);
591 agg::rasterizer_scanline_aa rasterizer;
592 rasterizer.clip_box(0.0f, 0.0f, (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_WIDTH)),
593 (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_HEIGHT)));
594 RasterizeStroke(rasterizer, path_data.m_PathData, pObject2Device,
595 pGraphState);
596 rasterizer.filling_rule(agg::fill_non_zero);
597 SetClipMask(rasterizer);
598 return true;
599 }
600
601 class CFX_Renderer {
602 private:
603 int m_Alpha, m_Red, m_Green, m_Blue, m_Gray;
604 uint32_t m_Color;
605 bool m_bFullCover;
606 bool m_bRgbByteOrder;
607 CFX_DIBitmap* m_pOriDevice;
608 FX_RECT m_ClipBox;
609 const CFX_DIBitmap* m_pClipMask;
610 CFX_DIBitmap* m_pDevice;
611 const CFX_ClipRgn* m_pClipRgn;
612 void (CFX_Renderer::*composite_span)(uint8_t*,
613 int,
614 int,
615 int,
616 uint8_t*,
617 int,
618 int,
619 uint8_t*,
620 uint8_t*);
621
622 public:
prepare(unsigned)623 void prepare(unsigned) {}
624
CompositeSpan(uint8_t * dest_scan,uint8_t * ori_scan,int Bpp,bool bDestAlpha,int span_left,int span_len,uint8_t * cover_scan,int clip_left,int clip_right,uint8_t * clip_scan)625 void CompositeSpan(uint8_t* dest_scan,
626 uint8_t* ori_scan,
627 int Bpp,
628 bool bDestAlpha,
629 int span_left,
630 int span_len,
631 uint8_t* cover_scan,
632 int clip_left,
633 int clip_right,
634 uint8_t* clip_scan) {
635 ASSERT(!m_pDevice->IsCmykImage());
636 int col_start = span_left < clip_left ? clip_left - span_left : 0;
637 int col_end = (span_left + span_len) < clip_right
638 ? span_len
639 : (clip_right - span_left);
640 if (Bpp) {
641 dest_scan += col_start * Bpp;
642 ori_scan += col_start * Bpp;
643 } else {
644 dest_scan += col_start / 8;
645 ori_scan += col_start / 8;
646 }
647 if (m_bRgbByteOrder) {
648 if (Bpp == 4 && bDestAlpha) {
649 for (int col = col_start; col < col_end; col++) {
650 int src_alpha;
651 if (clip_scan) {
652 src_alpha = m_Alpha * clip_scan[col] / 255;
653 } else {
654 src_alpha = m_Alpha;
655 }
656 uint8_t dest_alpha =
657 ori_scan[3] + src_alpha - ori_scan[3] * src_alpha / 255;
658 dest_scan[3] = dest_alpha;
659 int alpha_ratio = src_alpha * 255 / dest_alpha;
660 if (m_bFullCover) {
661 *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, alpha_ratio);
662 *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, alpha_ratio);
663 *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, alpha_ratio);
664 dest_scan++;
665 ori_scan++;
666 } else {
667 int r = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, alpha_ratio);
668 int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, alpha_ratio);
669 int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, alpha_ratio);
670 ori_scan++;
671 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]);
672 dest_scan++;
673 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]);
674 dest_scan++;
675 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]);
676 dest_scan += 2;
677 }
678 }
679 return;
680 }
681 if (Bpp == 3 || Bpp == 4) {
682 for (int col = col_start; col < col_end; col++) {
683 int src_alpha;
684 if (clip_scan) {
685 src_alpha = m_Alpha * clip_scan[col] / 255;
686 } else {
687 src_alpha = m_Alpha;
688 }
689 int r = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, src_alpha);
690 int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha);
691 int b = FXDIB_ALPHA_MERGE(*ori_scan, m_Blue, src_alpha);
692 ori_scan += Bpp - 2;
693 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]);
694 dest_scan++;
695 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]);
696 dest_scan++;
697 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]);
698 dest_scan += Bpp - 2;
699 }
700 }
701 return;
702 }
703 if (Bpp == 4 && bDestAlpha) {
704 for (int col = col_start; col < col_end; col++) {
705 int src_alpha;
706 if (clip_scan) {
707 src_alpha = m_Alpha * clip_scan[col] / 255;
708 } else {
709 src_alpha = m_Alpha;
710 }
711 int src_alpha_covered = src_alpha * cover_scan[col] / 255;
712 if (src_alpha_covered == 0) {
713 dest_scan += 4;
714 continue;
715 }
716 if (cover_scan[col] == 255) {
717 dest_scan[3] = src_alpha_covered;
718 *dest_scan++ = m_Blue;
719 *dest_scan++ = m_Green;
720 *dest_scan = m_Red;
721 dest_scan += 2;
722 continue;
723 } else {
724 if (dest_scan[3] == 0) {
725 dest_scan[3] = src_alpha_covered;
726 *dest_scan++ = m_Blue;
727 *dest_scan++ = m_Green;
728 *dest_scan = m_Red;
729 dest_scan += 2;
730 continue;
731 }
732 uint8_t cover = cover_scan[col];
733 dest_scan[3] = FXDIB_ALPHA_MERGE(dest_scan[3], src_alpha, cover);
734 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, cover);
735 dest_scan++;
736 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, cover);
737 dest_scan++;
738 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, cover);
739 dest_scan += 2;
740 }
741 }
742 return;
743 }
744 if (Bpp == 3 || Bpp == 4) {
745 for (int col = col_start; col < col_end; col++) {
746 int src_alpha;
747 if (clip_scan) {
748 src_alpha = m_Alpha * clip_scan[col] / 255;
749 } else {
750 src_alpha = m_Alpha;
751 }
752 if (m_bFullCover) {
753 *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha);
754 *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha);
755 *dest_scan = FXDIB_ALPHA_MERGE(*ori_scan, m_Red, src_alpha);
756 dest_scan += Bpp - 2;
757 ori_scan += Bpp - 2;
758 continue;
759 }
760 int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha);
761 int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha);
762 int r = FXDIB_ALPHA_MERGE(*ori_scan, m_Red, src_alpha);
763 ori_scan += Bpp - 2;
764 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]);
765 dest_scan++;
766 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]);
767 dest_scan++;
768 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]);
769 dest_scan += Bpp - 2;
770 continue;
771 }
772 return;
773 }
774 if (Bpp == 1) {
775 for (int col = col_start; col < col_end; col++) {
776 int src_alpha;
777 if (clip_scan) {
778 src_alpha = m_Alpha * clip_scan[col] / 255;
779 } else {
780 src_alpha = m_Alpha;
781 }
782 if (m_bFullCover) {
783 *dest_scan = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha);
784 } else {
785 int gray = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha);
786 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, cover_scan[col]);
787 dest_scan++;
788 }
789 }
790 } else {
791 int index = 0;
792 if (m_pDevice->GetPalette()) {
793 for (int i = 0; i < 2; i++) {
794 if (FXARGB_TODIB(m_pDevice->GetPalette()[i]) == m_Color) {
795 index = i;
796 }
797 }
798 } else {
799 index = ((uint8_t)m_Color == 0xff) ? 1 : 0;
800 }
801 uint8_t* dest_scan1 = dest_scan;
802 for (int col = col_start; col < col_end; col++) {
803 int src_alpha;
804 if (clip_scan) {
805 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
806 } else {
807 src_alpha = m_Alpha * cover_scan[col] / 255;
808 }
809 if (src_alpha) {
810 if (!index) {
811 *dest_scan1 &= ~(1 << (7 - (col + span_left) % 8));
812 } else {
813 *dest_scan1 |= 1 << (7 - (col + span_left) % 8);
814 }
815 }
816 dest_scan1 = dest_scan + (span_left % 8 + col - col_start + 1) / 8;
817 }
818 }
819 }
820
CompositeSpan1bpp(uint8_t * dest_scan,int Bpp,int span_left,int span_len,uint8_t * cover_scan,int clip_left,int clip_right,uint8_t * clip_scan,uint8_t * dest_extra_alpha_scan)821 void CompositeSpan1bpp(uint8_t* dest_scan,
822 int Bpp,
823 int span_left,
824 int span_len,
825 uint8_t* cover_scan,
826 int clip_left,
827 int clip_right,
828 uint8_t* clip_scan,
829 uint8_t* dest_extra_alpha_scan) {
830 ASSERT(!m_bRgbByteOrder);
831 ASSERT(!m_pDevice->IsCmykImage());
832 int col_start = span_left < clip_left ? clip_left - span_left : 0;
833 int col_end = (span_left + span_len) < clip_right
834 ? span_len
835 : (clip_right - span_left);
836 dest_scan += col_start / 8;
837 int index = 0;
838 if (m_pDevice->GetPalette()) {
839 for (int i = 0; i < 2; i++) {
840 if (FXARGB_TODIB(m_pDevice->GetPalette()[i]) == m_Color) {
841 index = i;
842 }
843 }
844 } else {
845 index = ((uint8_t)m_Color == 0xff) ? 1 : 0;
846 }
847 uint8_t* dest_scan1 = dest_scan;
848 for (int col = col_start; col < col_end; col++) {
849 int src_alpha;
850 if (clip_scan) {
851 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
852 } else {
853 src_alpha = m_Alpha * cover_scan[col] / 255;
854 }
855 if (src_alpha) {
856 if (!index) {
857 *dest_scan1 &= ~(1 << (7 - (col + span_left) % 8));
858 } else {
859 *dest_scan1 |= 1 << (7 - (col + span_left) % 8);
860 }
861 }
862 dest_scan1 = dest_scan + (span_left % 8 + col - col_start + 1) / 8;
863 }
864 }
865
CompositeSpanGray(uint8_t * dest_scan,int Bpp,int span_left,int span_len,uint8_t * cover_scan,int clip_left,int clip_right,uint8_t * clip_scan,uint8_t * dest_extra_alpha_scan)866 void CompositeSpanGray(uint8_t* dest_scan,
867 int Bpp,
868 int span_left,
869 int span_len,
870 uint8_t* cover_scan,
871 int clip_left,
872 int clip_right,
873 uint8_t* clip_scan,
874 uint8_t* dest_extra_alpha_scan) {
875 ASSERT(!m_bRgbByteOrder);
876 int col_start = span_left < clip_left ? clip_left - span_left : 0;
877 int col_end = (span_left + span_len) < clip_right
878 ? span_len
879 : (clip_right - span_left);
880 dest_scan += col_start;
881 if (dest_extra_alpha_scan) {
882 for (int col = col_start; col < col_end; col++) {
883 int src_alpha;
884 if (m_bFullCover) {
885 if (clip_scan) {
886 src_alpha = m_Alpha * clip_scan[col] / 255;
887 } else {
888 src_alpha = m_Alpha;
889 }
890 } else {
891 if (clip_scan) {
892 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
893 } else {
894 src_alpha = m_Alpha * cover_scan[col] / 255;
895 }
896 }
897 if (src_alpha) {
898 if (src_alpha == 255) {
899 *dest_scan = m_Gray;
900 *dest_extra_alpha_scan = m_Alpha;
901 } else {
902 uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha -
903 (*dest_extra_alpha_scan) * src_alpha / 255;
904 *dest_extra_alpha_scan++ = dest_alpha;
905 int alpha_ratio = src_alpha * 255 / dest_alpha;
906 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, alpha_ratio);
907 dest_scan++;
908 continue;
909 }
910 }
911 dest_extra_alpha_scan++;
912 dest_scan++;
913 }
914 } else {
915 for (int col = col_start; col < col_end; col++) {
916 int src_alpha;
917 if (clip_scan) {
918 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
919 } else {
920 src_alpha = m_Alpha * cover_scan[col] / 255;
921 }
922 if (src_alpha) {
923 if (src_alpha == 255) {
924 *dest_scan = m_Gray;
925 } else {
926 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha);
927 }
928 }
929 dest_scan++;
930 }
931 }
932 }
933
CompositeSpanARGB(uint8_t * dest_scan,int Bpp,int span_left,int span_len,uint8_t * cover_scan,int clip_left,int clip_right,uint8_t * clip_scan,uint8_t * dest_extra_alpha_scan)934 void CompositeSpanARGB(uint8_t* dest_scan,
935 int Bpp,
936 int span_left,
937 int span_len,
938 uint8_t* cover_scan,
939 int clip_left,
940 int clip_right,
941 uint8_t* clip_scan,
942 uint8_t* dest_extra_alpha_scan) {
943 int col_start = span_left < clip_left ? clip_left - span_left : 0;
944 int col_end = (span_left + span_len) < clip_right
945 ? span_len
946 : (clip_right - span_left);
947 dest_scan += col_start * Bpp;
948 if (m_bRgbByteOrder) {
949 for (int col = col_start; col < col_end; col++) {
950 int src_alpha;
951 if (m_bFullCover) {
952 if (clip_scan) {
953 src_alpha = m_Alpha * clip_scan[col] / 255;
954 } else {
955 src_alpha = m_Alpha;
956 }
957 } else {
958 if (clip_scan) {
959 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
960 } else {
961 src_alpha = m_Alpha * cover_scan[col] / 255;
962 }
963 }
964 if (src_alpha) {
965 if (src_alpha == 255) {
966 *(uint32_t*)dest_scan = m_Color;
967 } else {
968 uint8_t dest_alpha =
969 dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255;
970 dest_scan[3] = dest_alpha;
971 int alpha_ratio = src_alpha * 255 / dest_alpha;
972 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
973 dest_scan++;
974 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
975 dest_scan++;
976 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
977 dest_scan += 2;
978 continue;
979 }
980 }
981 dest_scan += 4;
982 }
983 return;
984 }
985 for (int col = col_start; col < col_end; col++) {
986 int src_alpha;
987 if (m_bFullCover) {
988 if (clip_scan) {
989 src_alpha = m_Alpha * clip_scan[col] / 255;
990 } else {
991 src_alpha = m_Alpha;
992 }
993 } else {
994 if (clip_scan) {
995 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
996 } else {
997 src_alpha = m_Alpha * cover_scan[col] / 255;
998 }
999 }
1000 if (src_alpha) {
1001 if (src_alpha == 255) {
1002 *(uint32_t*)dest_scan = m_Color;
1003 } else {
1004 if (dest_scan[3] == 0) {
1005 dest_scan[3] = src_alpha;
1006 *dest_scan++ = m_Blue;
1007 *dest_scan++ = m_Green;
1008 *dest_scan = m_Red;
1009 dest_scan += 2;
1010 continue;
1011 }
1012 uint8_t dest_alpha =
1013 dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255;
1014 dest_scan[3] = dest_alpha;
1015 int alpha_ratio = src_alpha * 255 / dest_alpha;
1016 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
1017 dest_scan++;
1018 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
1019 dest_scan++;
1020 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
1021 dest_scan += 2;
1022 continue;
1023 }
1024 }
1025 dest_scan += Bpp;
1026 }
1027 }
1028
CompositeSpanRGB(uint8_t * dest_scan,int Bpp,int span_left,int span_len,uint8_t * cover_scan,int clip_left,int clip_right,uint8_t * clip_scan,uint8_t * dest_extra_alpha_scan)1029 void CompositeSpanRGB(uint8_t* dest_scan,
1030 int Bpp,
1031 int span_left,
1032 int span_len,
1033 uint8_t* cover_scan,
1034 int clip_left,
1035 int clip_right,
1036 uint8_t* clip_scan,
1037 uint8_t* dest_extra_alpha_scan) {
1038 int col_start = span_left < clip_left ? clip_left - span_left : 0;
1039 int col_end = (span_left + span_len) < clip_right
1040 ? span_len
1041 : (clip_right - span_left);
1042 dest_scan += col_start * Bpp;
1043 if (m_bRgbByteOrder) {
1044 for (int col = col_start; col < col_end; col++) {
1045 int src_alpha;
1046 if (clip_scan) {
1047 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
1048 } else {
1049 src_alpha = m_Alpha * cover_scan[col] / 255;
1050 }
1051 if (src_alpha) {
1052 if (src_alpha == 255) {
1053 if (Bpp == 4) {
1054 *(uint32_t*)dest_scan = m_Color;
1055 } else if (Bpp == 3) {
1056 *dest_scan++ = m_Red;
1057 *dest_scan++ = m_Green;
1058 *dest_scan++ = m_Blue;
1059 continue;
1060 }
1061 } else {
1062 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha);
1063 dest_scan++;
1064 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha);
1065 dest_scan++;
1066 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha);
1067 dest_scan += Bpp - 2;
1068 continue;
1069 }
1070 }
1071 dest_scan += Bpp;
1072 }
1073 return;
1074 }
1075 if (Bpp == 3 && dest_extra_alpha_scan) {
1076 for (int col = col_start; col < col_end; col++) {
1077 int src_alpha;
1078 if (m_bFullCover) {
1079 if (clip_scan) {
1080 src_alpha = m_Alpha * clip_scan[col] / 255;
1081 } else {
1082 src_alpha = m_Alpha;
1083 }
1084 } else {
1085 if (clip_scan) {
1086 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
1087 } else {
1088 src_alpha = m_Alpha * cover_scan[col] / 255;
1089 }
1090 }
1091 if (src_alpha) {
1092 if (src_alpha == 255) {
1093 *dest_scan++ = (uint8_t)m_Blue;
1094 *dest_scan++ = (uint8_t)m_Green;
1095 *dest_scan++ = (uint8_t)m_Red;
1096 *dest_extra_alpha_scan++ = (uint8_t)m_Alpha;
1097 continue;
1098 } else {
1099 uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha -
1100 (*dest_extra_alpha_scan) * src_alpha / 255;
1101 *dest_extra_alpha_scan++ = dest_alpha;
1102 int alpha_ratio = src_alpha * 255 / dest_alpha;
1103 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
1104 dest_scan++;
1105 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
1106 dest_scan++;
1107 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
1108 dest_scan++;
1109 continue;
1110 }
1111 }
1112 dest_extra_alpha_scan++;
1113 dest_scan += Bpp;
1114 }
1115 } else {
1116 for (int col = col_start; col < col_end; col++) {
1117 int src_alpha;
1118 if (m_bFullCover) {
1119 if (clip_scan) {
1120 src_alpha = m_Alpha * clip_scan[col] / 255;
1121 } else {
1122 src_alpha = m_Alpha;
1123 }
1124 } else {
1125 if (clip_scan) {
1126 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
1127 } else {
1128 src_alpha = m_Alpha * cover_scan[col] / 255;
1129 }
1130 }
1131 if (src_alpha) {
1132 if (src_alpha == 255) {
1133 if (Bpp == 4) {
1134 *(uint32_t*)dest_scan = m_Color;
1135 } else if (Bpp == 3) {
1136 *dest_scan++ = m_Blue;
1137 *dest_scan++ = m_Green;
1138 *dest_scan++ = m_Red;
1139 continue;
1140 }
1141 } else {
1142 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha);
1143 dest_scan++;
1144 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha);
1145 dest_scan++;
1146 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha);
1147 dest_scan += Bpp - 2;
1148 continue;
1149 }
1150 }
1151 dest_scan += Bpp;
1152 }
1153 }
1154 }
1155
CompositeSpanCMYK(uint8_t * dest_scan,int Bpp,int span_left,int span_len,uint8_t * cover_scan,int clip_left,int clip_right,uint8_t * clip_scan,uint8_t * dest_extra_alpha_scan)1156 void CompositeSpanCMYK(uint8_t* dest_scan,
1157 int Bpp,
1158 int span_left,
1159 int span_len,
1160 uint8_t* cover_scan,
1161 int clip_left,
1162 int clip_right,
1163 uint8_t* clip_scan,
1164 uint8_t* dest_extra_alpha_scan) {
1165 ASSERT(!m_bRgbByteOrder);
1166 int col_start = span_left < clip_left ? clip_left - span_left : 0;
1167 int col_end = (span_left + span_len) < clip_right
1168 ? span_len
1169 : (clip_right - span_left);
1170 dest_scan += col_start * 4;
1171 if (dest_extra_alpha_scan) {
1172 for (int col = col_start; col < col_end; col++) {
1173 int src_alpha;
1174 if (m_bFullCover) {
1175 if (clip_scan) {
1176 src_alpha = m_Alpha * clip_scan[col] / 255;
1177 } else {
1178 src_alpha = m_Alpha;
1179 }
1180 } else {
1181 if (clip_scan) {
1182 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
1183 } else {
1184 src_alpha = m_Alpha * cover_scan[col] / 255;
1185 }
1186 }
1187 if (src_alpha) {
1188 if (src_alpha == 255) {
1189 *(FX_CMYK*)dest_scan = m_Color;
1190 *dest_extra_alpha_scan = (uint8_t)m_Alpha;
1191 } else {
1192 uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha -
1193 (*dest_extra_alpha_scan) * src_alpha / 255;
1194 *dest_extra_alpha_scan++ = dest_alpha;
1195 int alpha_ratio = src_alpha * 255 / dest_alpha;
1196 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
1197 dest_scan++;
1198 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
1199 dest_scan++;
1200 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
1201 dest_scan++;
1202 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, alpha_ratio);
1203 dest_scan++;
1204 continue;
1205 }
1206 }
1207 dest_extra_alpha_scan++;
1208 dest_scan += 4;
1209 }
1210 } else {
1211 for (int col = col_start; col < col_end; col++) {
1212 int src_alpha;
1213 if (clip_scan) {
1214 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
1215 } else {
1216 src_alpha = m_Alpha * cover_scan[col] / 255;
1217 }
1218 if (src_alpha) {
1219 if (src_alpha == 255) {
1220 *(FX_CMYK*)dest_scan = m_Color;
1221 } else {
1222 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha);
1223 dest_scan++;
1224 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha);
1225 dest_scan++;
1226 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha);
1227 dest_scan++;
1228 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha);
1229 dest_scan++;
1230 continue;
1231 }
1232 }
1233 dest_scan += 4;
1234 }
1235 }
1236 }
1237
1238 template <class Scanline>
render(const Scanline & sl)1239 void render(const Scanline& sl) {
1240 if (!m_pOriDevice && !composite_span) {
1241 return;
1242 }
1243 int y = sl.y();
1244 if (y < m_ClipBox.top || y >= m_ClipBox.bottom) {
1245 return;
1246 }
1247 uint8_t* dest_scan = m_pDevice->GetBuffer() + m_pDevice->GetPitch() * y;
1248 uint8_t* dest_scan_extra_alpha = nullptr;
1249 CFX_DIBitmap* pAlphaMask = m_pDevice->m_pAlphaMask;
1250 if (pAlphaMask) {
1251 dest_scan_extra_alpha =
1252 pAlphaMask->GetBuffer() + pAlphaMask->GetPitch() * y;
1253 }
1254 uint8_t* ori_scan = nullptr;
1255 if (m_pOriDevice) {
1256 ori_scan = m_pOriDevice->GetBuffer() + m_pOriDevice->GetPitch() * y;
1257 }
1258 int Bpp = m_pDevice->GetBPP() / 8;
1259 bool bDestAlpha = m_pDevice->HasAlpha() || m_pDevice->IsAlphaMask();
1260 unsigned num_spans = sl.num_spans();
1261 typename Scanline::const_iterator span = sl.begin();
1262 while (1) {
1263 int x = span->x;
1264 ASSERT(span->len > 0);
1265 uint8_t* dest_pos = nullptr;
1266 uint8_t* dest_extra_alpha_pos = nullptr;
1267 uint8_t* ori_pos = nullptr;
1268 if (Bpp) {
1269 ori_pos = ori_scan ? ori_scan + x * Bpp : nullptr;
1270 dest_pos = dest_scan + x * Bpp;
1271 dest_extra_alpha_pos =
1272 dest_scan_extra_alpha ? dest_scan_extra_alpha + x : nullptr;
1273 } else {
1274 dest_pos = dest_scan + x / 8;
1275 ori_pos = ori_scan ? ori_scan + x / 8 : nullptr;
1276 }
1277 uint8_t* clip_pos = nullptr;
1278 if (m_pClipMask) {
1279 clip_pos = m_pClipMask->GetBuffer() +
1280 (y - m_ClipBox.top) * m_pClipMask->GetPitch() + x -
1281 m_ClipBox.left;
1282 }
1283 if (ori_pos) {
1284 CompositeSpan(dest_pos, ori_pos, Bpp, bDestAlpha, x, span->len,
1285 span->covers, m_ClipBox.left, m_ClipBox.right, clip_pos);
1286 } else {
1287 (this->*composite_span)(dest_pos, Bpp, x, span->len, span->covers,
1288 m_ClipBox.left, m_ClipBox.right, clip_pos,
1289 dest_extra_alpha_pos);
1290 }
1291 if (--num_spans == 0) {
1292 break;
1293 }
1294 ++span;
1295 }
1296 }
1297
Init(CFX_DIBitmap * pDevice,CFX_DIBitmap * pOriDevice,const CFX_ClipRgn * pClipRgn,uint32_t color,bool bFullCover,bool bRgbByteOrder,int alpha_flag=0,void * pIccTransform=nullptr)1298 bool Init(CFX_DIBitmap* pDevice,
1299 CFX_DIBitmap* pOriDevice,
1300 const CFX_ClipRgn* pClipRgn,
1301 uint32_t color,
1302 bool bFullCover,
1303 bool bRgbByteOrder,
1304 int alpha_flag = 0,
1305 void* pIccTransform = nullptr) {
1306 m_pDevice = pDevice;
1307 m_pClipRgn = pClipRgn;
1308 composite_span = nullptr;
1309 m_bRgbByteOrder = bRgbByteOrder;
1310 m_pOriDevice = pOriDevice;
1311 if (m_pClipRgn) {
1312 m_ClipBox = m_pClipRgn->GetBox();
1313 } else {
1314 m_ClipBox.left = m_ClipBox.top = 0;
1315 m_ClipBox.right = m_pDevice->GetWidth();
1316 m_ClipBox.bottom = m_pDevice->GetHeight();
1317 }
1318 m_pClipMask = nullptr;
1319 if (m_pClipRgn && m_pClipRgn->GetType() == CFX_ClipRgn::MaskF) {
1320 m_pClipMask = m_pClipRgn->GetMask().GetObject();
1321 }
1322 m_bFullCover = bFullCover;
1323 bool bObjectCMYK = !!FXGETFLAG_COLORTYPE(alpha_flag);
1324 bool bDeviceCMYK = pDevice->IsCmykImage();
1325 m_Alpha = bObjectCMYK ? FXGETFLAG_ALPHA_FILL(alpha_flag) : FXARGB_A(color);
1326 CCodec_IccModule* pIccModule = nullptr;
1327 if (!CFX_GEModule::Get()->GetCodecModule() ||
1328 !CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) {
1329 pIccTransform = nullptr;
1330 } else {
1331 pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
1332 }
1333 if (m_pDevice->GetBPP() == 8) {
1334 ASSERT(!m_bRgbByteOrder);
1335 composite_span = &CFX_Renderer::CompositeSpanGray;
1336 if (m_pDevice->IsAlphaMask()) {
1337 m_Gray = 255;
1338 } else {
1339 if (pIccTransform) {
1340 uint8_t gray;
1341 color = bObjectCMYK ? FXCMYK_TODIB(color) : FXARGB_TODIB(color);
1342 pIccModule->TranslateScanline(pIccTransform, &gray,
1343 (const uint8_t*)&color, 1);
1344 m_Gray = gray;
1345 } else {
1346 if (bObjectCMYK) {
1347 uint8_t r, g, b;
1348 AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color),
1349 FXSYS_GetYValue(color), FXSYS_GetKValue(color),
1350 r, g, b);
1351 m_Gray = FXRGB2GRAY(r, g, b);
1352 } else {
1353 m_Gray =
1354 FXRGB2GRAY(FXARGB_R(color), FXARGB_G(color), FXARGB_B(color));
1355 }
1356 }
1357 }
1358 return true;
1359 }
1360 if (bDeviceCMYK) {
1361 ASSERT(!m_bRgbByteOrder);
1362 composite_span = &CFX_Renderer::CompositeSpanCMYK;
1363 if (bObjectCMYK) {
1364 m_Color = FXCMYK_TODIB(color);
1365 if (pIccTransform) {
1366 pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&m_Color,
1367 (const uint8_t*)&m_Color, 1);
1368 }
1369 } else {
1370 if (!pIccTransform) {
1371 return false;
1372 }
1373 color = FXARGB_TODIB(color);
1374 pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&m_Color,
1375 (const uint8_t*)&color, 1);
1376 }
1377 m_Red = ((uint8_t*)&m_Color)[0];
1378 m_Green = ((uint8_t*)&m_Color)[1];
1379 m_Blue = ((uint8_t*)&m_Color)[2];
1380 m_Gray = ((uint8_t*)&m_Color)[3];
1381 } else {
1382 composite_span = (pDevice->GetFormat() == FXDIB_Argb)
1383 ? &CFX_Renderer::CompositeSpanARGB
1384 : &CFX_Renderer::CompositeSpanRGB;
1385 if (pIccTransform) {
1386 color = bObjectCMYK ? FXCMYK_TODIB(color) : FXARGB_TODIB(color);
1387 pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&m_Color,
1388 (const uint8_t*)&color, 1);
1389 ((uint8_t*)&m_Color)[3] = m_Alpha;
1390 m_Red = ((uint8_t*)&m_Color)[2];
1391 m_Green = ((uint8_t*)&m_Color)[1];
1392 m_Blue = ((uint8_t*)&m_Color)[0];
1393 if (m_bRgbByteOrder) {
1394 m_Color = FXARGB_TODIB(m_Color);
1395 m_Color = FXARGB_TOBGRORDERDIB(m_Color);
1396 }
1397 } else {
1398 if (bObjectCMYK) {
1399 uint8_t r, g, b;
1400 AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color),
1401 FXSYS_GetYValue(color), FXSYS_GetKValue(color), r,
1402 g, b);
1403 m_Color = FXARGB_MAKE(m_Alpha, r, g, b);
1404 if (m_bRgbByteOrder) {
1405 m_Color = FXARGB_TOBGRORDERDIB(m_Color);
1406 } else {
1407 m_Color = FXARGB_TODIB(m_Color);
1408 }
1409 m_Red = r;
1410 m_Green = g;
1411 m_Blue = b;
1412 } else {
1413 if (m_bRgbByteOrder) {
1414 m_Color = FXARGB_TOBGRORDERDIB(color);
1415 } else {
1416 m_Color = FXARGB_TODIB(color);
1417 }
1418 ArgbDecode(color, m_Alpha, m_Red, m_Green, m_Blue);
1419 }
1420 }
1421 }
1422 if (m_pDevice->GetBPP() == 1) {
1423 composite_span = &CFX_Renderer::CompositeSpan1bpp;
1424 }
1425 return true;
1426 }
1427 };
1428
GetDriverType() const1429 int CFX_AggDeviceDriver::GetDriverType() const {
1430 return 1;
1431 }
1432
RenderRasterizer(agg::rasterizer_scanline_aa & rasterizer,uint32_t color,bool bFullCover,bool bGroupKnockout,int alpha_flag,void * pIccTransform)1433 bool CFX_AggDeviceDriver::RenderRasterizer(
1434 agg::rasterizer_scanline_aa& rasterizer,
1435 uint32_t color,
1436 bool bFullCover,
1437 bool bGroupKnockout,
1438 int alpha_flag,
1439 void* pIccTransform) {
1440 CFX_DIBitmap* pt = bGroupKnockout ? m_pOriDevice : nullptr;
1441 CFX_Renderer render;
1442 if (!render.Init(m_pBitmap, pt, m_pClipRgn.get(), color, bFullCover,
1443 m_bRgbByteOrder, alpha_flag, pIccTransform)) {
1444 return false;
1445 }
1446 agg::scanline_u8 scanline;
1447 agg::render_scanlines(rasterizer, scanline, render,
1448 (m_FillFlags & FXFILL_NOPATHSMOOTH) != 0);
1449 return true;
1450 }
1451
DrawPath(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)1452 bool CFX_AggDeviceDriver::DrawPath(const CFX_PathData* pPathData,
1453 const CFX_Matrix* pObject2Device,
1454 const CFX_GraphStateData* pGraphState,
1455 uint32_t fill_color,
1456 uint32_t stroke_color,
1457 int fill_mode,
1458 int blend_type) {
1459 if (blend_type != FXDIB_BLEND_NORMAL)
1460 return false;
1461
1462 if (!GetBuffer())
1463 return true;
1464
1465 m_FillFlags = fill_mode;
1466 if ((fill_mode & 3) && fill_color) {
1467 CAgg_PathData path_data;
1468 path_data.BuildPath(pPathData, pObject2Device);
1469 agg::rasterizer_scanline_aa rasterizer;
1470 rasterizer.clip_box(0.0f, 0.0f, (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_WIDTH)),
1471 (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_HEIGHT)));
1472 rasterizer.add_path(path_data.m_PathData);
1473 rasterizer.filling_rule((fill_mode & 3) == FXFILL_WINDING
1474 ? agg::fill_non_zero
1475 : agg::fill_even_odd);
1476 if (!RenderRasterizer(rasterizer, fill_color,
1477 !!(fill_mode & FXFILL_FULLCOVER), false, 0,
1478 nullptr)) {
1479 return false;
1480 }
1481 }
1482 int stroke_alpha = FXARGB_A(stroke_color);
1483 if (!pGraphState || !stroke_alpha)
1484 return true;
1485
1486 if (fill_mode & FX_ZEROAREA_FILL) {
1487 CAgg_PathData path_data;
1488 path_data.BuildPath(pPathData, pObject2Device);
1489 agg::rasterizer_scanline_aa rasterizer;
1490 rasterizer.clip_box(0.0f, 0.0f, (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_WIDTH)),
1491 (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_HEIGHT)));
1492 RasterizeStroke(rasterizer, path_data.m_PathData, nullptr, pGraphState, 1,
1493 false, !!(fill_mode & FX_STROKE_TEXT_MODE));
1494 return RenderRasterizer(rasterizer, stroke_color,
1495 !!(fill_mode & FXFILL_FULLCOVER), m_bGroupKnockout,
1496 0, nullptr);
1497 }
1498 CFX_Matrix matrix1;
1499 CFX_Matrix matrix2;
1500 if (pObject2Device) {
1501 matrix1.a =
1502 std::max(FXSYS_fabs(pObject2Device->a), FXSYS_fabs(pObject2Device->b));
1503 matrix1.d = matrix1.a;
1504 matrix2 = CFX_Matrix(
1505 pObject2Device->a / matrix1.a, pObject2Device->b / matrix1.a,
1506 pObject2Device->c / matrix1.d, pObject2Device->d / matrix1.d, 0, 0);
1507
1508 CFX_Matrix mtRervese;
1509 mtRervese.SetReverse(matrix2);
1510 matrix1 = *pObject2Device;
1511 matrix1.Concat(mtRervese);
1512 }
1513
1514 CAgg_PathData path_data;
1515 path_data.BuildPath(pPathData, &matrix1);
1516 agg::rasterizer_scanline_aa rasterizer;
1517 rasterizer.clip_box(0.0f, 0.0f, (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_WIDTH)),
1518 (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_HEIGHT)));
1519 RasterizeStroke(rasterizer, path_data.m_PathData, &matrix2, pGraphState,
1520 matrix1.a, false, !!(fill_mode & FX_STROKE_TEXT_MODE));
1521 return RenderRasterizer(rasterizer, stroke_color,
1522 !!(fill_mode & FXFILL_FULLCOVER), m_bGroupKnockout, 0,
1523 nullptr);
1524 }
1525
SetPixel(int x,int y,uint32_t color)1526 bool CFX_AggDeviceDriver::SetPixel(int x, int y, uint32_t color) {
1527 if (!m_pBitmap->GetBuffer())
1528 return true;
1529
1530 if (!m_pClipRgn) {
1531 if (!m_bRgbByteOrder)
1532 return DibSetPixel(m_pBitmap, x, y, color, 0, nullptr);
1533 RgbByteOrderSetPixel(m_pBitmap, x, y, color);
1534 return true;
1535 }
1536 if (!m_pClipRgn->GetBox().Contains(x, y))
1537 return true;
1538
1539 if (m_pClipRgn->GetType() == CFX_ClipRgn::RectI) {
1540 if (!m_bRgbByteOrder)
1541 return DibSetPixel(m_pBitmap, x, y, color, 0, nullptr);
1542 RgbByteOrderSetPixel(m_pBitmap, x, y, color);
1543 return true;
1544 }
1545 if (m_pClipRgn->GetType() != CFX_ClipRgn::MaskF)
1546 return true;
1547
1548 const CFX_DIBitmap* pMask = m_pClipRgn->GetMask().GetObject();
1549 int new_alpha = FXARGB_A(color) * pMask->GetScanline(y)[x] / 255;
1550 color = (color & 0xffffff) | (new_alpha << 24);
1551 if (m_bRgbByteOrder) {
1552 RgbByteOrderSetPixel(m_pBitmap, x, y, color);
1553 return true;
1554 }
1555 return DibSetPixel(m_pBitmap, x, y, color, 0, nullptr);
1556 }
1557
FillRectWithBlend(const FX_RECT * pRect,uint32_t fill_color,int blend_type)1558 bool CFX_AggDeviceDriver::FillRectWithBlend(const FX_RECT* pRect,
1559 uint32_t fill_color,
1560 int blend_type) {
1561 if (blend_type != FXDIB_BLEND_NORMAL)
1562 return false;
1563
1564 if (!m_pBitmap->GetBuffer())
1565 return true;
1566
1567 FX_RECT clip_rect;
1568 GetClipBox(&clip_rect);
1569 FX_RECT draw_rect = clip_rect;
1570 if (pRect)
1571 draw_rect.Intersect(*pRect);
1572 if (draw_rect.IsEmpty())
1573 return true;
1574
1575 if (!m_pClipRgn || m_pClipRgn->GetType() == CFX_ClipRgn::RectI) {
1576 if (m_bRgbByteOrder) {
1577 RgbByteOrderCompositeRect(m_pBitmap, draw_rect.left, draw_rect.top,
1578 draw_rect.Width(), draw_rect.Height(),
1579 fill_color);
1580 } else {
1581 m_pBitmap->CompositeRect(draw_rect.left, draw_rect.top, draw_rect.Width(),
1582 draw_rect.Height(), fill_color, 0, nullptr);
1583 }
1584 return true;
1585 }
1586 m_pBitmap->CompositeMask(
1587 draw_rect.left, draw_rect.top, draw_rect.Width(), draw_rect.Height(),
1588 m_pClipRgn->GetMask().GetObject(), fill_color,
1589 draw_rect.left - clip_rect.left, draw_rect.top - clip_rect.top,
1590 FXDIB_BLEND_NORMAL, nullptr, m_bRgbByteOrder, 0, nullptr);
1591 return true;
1592 }
1593
GetClipBox(FX_RECT * pRect)1594 bool CFX_AggDeviceDriver::GetClipBox(FX_RECT* pRect) {
1595 if (!m_pClipRgn) {
1596 pRect->left = pRect->top = 0;
1597 pRect->right = GetDeviceCaps(FXDC_PIXEL_WIDTH);
1598 pRect->bottom = GetDeviceCaps(FXDC_PIXEL_HEIGHT);
1599 return true;
1600 }
1601 *pRect = m_pClipRgn->GetBox();
1602 return true;
1603 }
1604
GetDIBits(CFX_DIBitmap * pBitmap,int left,int top)1605 bool CFX_AggDeviceDriver::GetDIBits(CFX_DIBitmap* pBitmap, int left, int top) {
1606 if (!m_pBitmap || !m_pBitmap->GetBuffer())
1607 return true;
1608
1609 FX_RECT rect(left, top, left + pBitmap->GetWidth(),
1610 top + pBitmap->GetHeight());
1611 std::unique_ptr<CFX_DIBitmap> pBack;
1612 if (m_pOriDevice) {
1613 pBack = m_pOriDevice->Clone(&rect);
1614 if (!pBack)
1615 return true;
1616
1617 pBack->CompositeBitmap(0, 0, pBack->GetWidth(), pBack->GetHeight(),
1618 m_pBitmap, 0, 0);
1619 } else {
1620 pBack = m_pBitmap->Clone(&rect);
1621 if (!pBack)
1622 return true;
1623 }
1624
1625 left = std::min(left, 0);
1626 top = std::min(top, 0);
1627 if (m_bRgbByteOrder) {
1628 RgbByteOrderTransferBitmap(pBitmap, 0, 0, rect.Width(), rect.Height(),
1629 pBack.get(), left, top);
1630 return true;
1631 }
1632 return pBitmap->TransferBitmap(0, 0, rect.Width(), rect.Height(), pBack.get(),
1633 left, top);
1634 }
1635
GetBackDrop()1636 CFX_DIBitmap* CFX_AggDeviceDriver::GetBackDrop() {
1637 return m_pOriDevice;
1638 }
1639
SetDIBits(const CFX_DIBSource * pBitmap,uint32_t argb,const FX_RECT * pSrcRect,int left,int top,int blend_type)1640 bool CFX_AggDeviceDriver::SetDIBits(const CFX_DIBSource* pBitmap,
1641 uint32_t argb,
1642 const FX_RECT* pSrcRect,
1643 int left,
1644 int top,
1645 int blend_type) {
1646 if (!m_pBitmap->GetBuffer())
1647 return true;
1648
1649 if (pBitmap->IsAlphaMask()) {
1650 return m_pBitmap->CompositeMask(
1651 left, top, pSrcRect->Width(), pSrcRect->Height(), pBitmap, argb,
1652 pSrcRect->left, pSrcRect->top, blend_type, m_pClipRgn.get(),
1653 m_bRgbByteOrder, 0, nullptr);
1654 }
1655 return m_pBitmap->CompositeBitmap(
1656 left, top, pSrcRect->Width(), pSrcRect->Height(), pBitmap, pSrcRect->left,
1657 pSrcRect->top, blend_type, m_pClipRgn.get(), m_bRgbByteOrder, nullptr);
1658 }
1659
StretchDIBits(const CFX_DIBSource * pSource,uint32_t argb,int dest_left,int dest_top,int dest_width,int dest_height,const FX_RECT * pClipRect,uint32_t flags,int blend_type)1660 bool CFX_AggDeviceDriver::StretchDIBits(const CFX_DIBSource* pSource,
1661 uint32_t argb,
1662 int dest_left,
1663 int dest_top,
1664 int dest_width,
1665 int dest_height,
1666 const FX_RECT* pClipRect,
1667 uint32_t flags,
1668 int blend_type) {
1669 if (!m_pBitmap->GetBuffer())
1670 return true;
1671
1672 if (dest_width == pSource->GetWidth() &&
1673 dest_height == pSource->GetHeight()) {
1674 FX_RECT rect(0, 0, dest_width, dest_height);
1675 return SetDIBits(pSource, argb, &rect, dest_left, dest_top, blend_type);
1676 }
1677 FX_RECT dest_rect(dest_left, dest_top, dest_left + dest_width,
1678 dest_top + dest_height);
1679 dest_rect.Normalize();
1680 FX_RECT dest_clip = dest_rect;
1681 dest_clip.Intersect(*pClipRect);
1682 CFX_BitmapComposer composer;
1683 composer.Compose(m_pBitmap, m_pClipRgn.get(), 255, argb, dest_clip, false,
1684 false, false, m_bRgbByteOrder, 0, nullptr, blend_type);
1685 dest_clip.Offset(-dest_rect.left, -dest_rect.top);
1686 CFX_ImageStretcher stretcher(&composer, pSource, dest_width, dest_height,
1687 dest_clip, flags);
1688 if (stretcher.Start())
1689 stretcher.Continue(nullptr);
1690 return true;
1691 }
1692
StartDIBits(const CFX_DIBSource * pSource,int bitmap_alpha,uint32_t argb,const CFX_Matrix * pMatrix,uint32_t render_flags,void * & handle,int blend_type)1693 bool CFX_AggDeviceDriver::StartDIBits(const CFX_DIBSource* pSource,
1694 int bitmap_alpha,
1695 uint32_t argb,
1696 const CFX_Matrix* pMatrix,
1697 uint32_t render_flags,
1698 void*& handle,
1699 int blend_type) {
1700 if (!m_pBitmap->GetBuffer())
1701 return true;
1702
1703 CFX_ImageRenderer* pRenderer = new CFX_ImageRenderer;
1704 pRenderer->Start(m_pBitmap, m_pClipRgn.get(), pSource, bitmap_alpha, argb,
1705 pMatrix, render_flags, m_bRgbByteOrder, 0, nullptr);
1706 handle = pRenderer;
1707 return true;
1708 }
1709
ContinueDIBits(void * pHandle,IFX_Pause * pPause)1710 bool CFX_AggDeviceDriver::ContinueDIBits(void* pHandle, IFX_Pause* pPause) {
1711 if (!m_pBitmap->GetBuffer()) {
1712 return true;
1713 }
1714 return ((CFX_ImageRenderer*)pHandle)->Continue(pPause);
1715 }
1716
CancelDIBits(void * pHandle)1717 void CFX_AggDeviceDriver::CancelDIBits(void* pHandle) {
1718 if (!m_pBitmap->GetBuffer()) {
1719 return;
1720 }
1721 delete (CFX_ImageRenderer*)pHandle;
1722 }
1723
1724 #ifndef _SKIA_SUPPORT_
CFX_FxgeDevice()1725 CFX_FxgeDevice::CFX_FxgeDevice() {
1726 m_bOwnedBitmap = false;
1727 }
1728
Attach(CFX_DIBitmap * pBitmap,bool bRgbByteOrder,CFX_DIBitmap * pOriDevice,bool bGroupKnockout)1729 bool CFX_FxgeDevice::Attach(CFX_DIBitmap* pBitmap,
1730 bool bRgbByteOrder,
1731 CFX_DIBitmap* pOriDevice,
1732 bool bGroupKnockout) {
1733 if (!pBitmap)
1734 return false;
1735
1736 SetBitmap(pBitmap);
1737 SetDeviceDriver(pdfium::MakeUnique<CFX_AggDeviceDriver>(
1738 pBitmap, bRgbByteOrder, pOriDevice, bGroupKnockout));
1739 return true;
1740 }
1741
Create(int width,int height,FXDIB_Format format,CFX_DIBitmap * pOriDevice)1742 bool CFX_FxgeDevice::Create(int width,
1743 int height,
1744 FXDIB_Format format,
1745 CFX_DIBitmap* pOriDevice) {
1746 m_bOwnedBitmap = true;
1747 CFX_DIBitmap* pBitmap = new CFX_DIBitmap;
1748 if (!pBitmap->Create(width, height, format)) {
1749 delete pBitmap;
1750 return false;
1751 }
1752 SetBitmap(pBitmap);
1753 SetDeviceDriver(pdfium::MakeUnique<CFX_AggDeviceDriver>(pBitmap, false,
1754 pOriDevice, false));
1755 return true;
1756 }
1757
~CFX_FxgeDevice()1758 CFX_FxgeDevice::~CFX_FxgeDevice() {
1759 if (m_bOwnedBitmap) {
1760 delete GetBitmap();
1761 }
1762 }
1763 #endif
1764