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