From adee4859cdb4a591cdc202d0a4452d17a827fc90 Mon Sep 17 00:00:00 2001 From: Nicolas Pena Date: Fri, 17 Mar 2017 10:11:19 -0400 Subject: Cleanup in fx_agg_driver part 2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moved CFX_Renderer to namespace and added some private auxiliary methods to reduce duplicated code. Also, more nit cleanup (casts, brackets, etc). Change-Id: I66f36177767325068a8a9ebf04a5d9b3a1762d94 Reviewed-on: https://pdfium-review.googlesource.com/3093 Commit-Queue: Nicolás Peña Reviewed-by: Tom Sepez Reviewed-by: dsinclair --- core/fxge/agg/fx_agg_driver.cpp | 1890 +++++++++++++++++++-------------------- 1 file changed, 929 insertions(+), 961 deletions(-) diff --git a/core/fxge/agg/fx_agg_driver.cpp b/core/fxge/agg/fx_agg_driver.cpp index 982b61e269..5ab48a95fe 100644 --- a/core/fxge/agg/fx_agg_driver.cpp +++ b/core/fxge/agg/fx_agg_driver.cpp @@ -10,16 +10,11 @@ #include #include "core/fxcodec/fx_codec.h" -#include "core/fxcrt/fx_memory.h" #include "core/fxge/cfx_fxgedevice.h" #include "core/fxge/cfx_gemodule.h" #include "core/fxge/cfx_graphstatedata.h" #include "core/fxge/cfx_pathdata.h" -#include "core/fxge/cfx_renderdevice.h" -#include "core/fxge/dib/dib_int.h" #include "core/fxge/ge/cfx_cliprgn.h" -#include "core/fxge/ge/fx_text_int.h" -#include "core/fxge/ifx_renderdevicedriver.h" #include "third_party/agg23/agg_conv_dash.h" #include "third_party/agg23/agg_conv_stroke.h" #include "third_party/agg23/agg_curves.h" @@ -71,6 +66,7 @@ void RgbByteOrderCompositeRect(CFX_DIBitmap* pBitmap, int src_g = FXARGB_G(argb); int src_b = FXARGB_B(argb); int Bpp = pBitmap->GetBPP() / 8; + int dib_argb = FXARGB_TOBGRORDERDIB(argb); uint8_t* pBuffer = pBitmap->GetBuffer(); if (src_alpha == 255) { for (int row = rect.top; row < rect.bottom; row++) { @@ -79,7 +75,7 @@ void RgbByteOrderCompositeRect(CFX_DIBitmap* pBitmap, if (Bpp == 4) { uint32_t* scan = reinterpret_cast(dest_scan); for (int col = 0; col < width; col++) - *scan++ = FXARGB_TOBGRORDERDIB(argb); + *scan++ = dib_argb; } else { for (int col = 0; col < width; col++) { *dest_scan++ = src_r; @@ -90,9 +86,10 @@ void RgbByteOrderCompositeRect(CFX_DIBitmap* pBitmap, } return; } + bool bAlpha = pBitmap->HasAlpha(); for (int row = rect.top; row < rect.bottom; row++) { uint8_t* dest_scan = pBuffer + row * pBitmap->GetPitch() + rect.left * Bpp; - if (pBitmap->HasAlpha()) { + if (bAlpha) { for (int col = 0; col < width; col++) { uint8_t back_alpha = dest_scan[3]; if (back_alpha == 0) { @@ -332,272 +329,85 @@ void RasterizeStroke(agg::rasterizer_scanline_aa* rasterizer, rasterizer->add_path_transformed(stroke, pObject2Device); } -} // namespace - -namespace agg { - -template -class renderer_scanline_aa_offset { +class CFX_Renderer { public: - typedef BaseRenderer base_ren_type; - typedef typename base_ren_type::color_type color_type; - renderer_scanline_aa_offset(base_ren_type& ren, unsigned left, unsigned top) - : m_ren(&ren), m_left(left), m_top(top) {} - void color(const color_type& c) { m_color = c; } - const color_type& color() const { return m_color; } + // Needed for agg caller void prepare(unsigned) {} - template - void render(const Scanline& sl) { - int y = sl.y(); - unsigned num_spans = sl.num_spans(); - typename Scanline::const_iterator span = sl.begin(); - for (;;) { - int x = span->x; - if (span->len > 0) { - m_ren->blend_solid_hspan(x - m_left, y - m_top, (unsigned)span->len, - m_color, span->covers); - } else { - m_ren->blend_hline(x - m_left, y - m_top, (unsigned)(x - span->len - 1), - m_color, *(span->covers)); - } - if (--num_spans == 0) { - break; - } - ++span; - } - } - private: - base_ren_type* m_ren; - color_type m_color; - unsigned m_left, m_top; -}; - -} // namespace agg - -void CAgg_PathData::BuildPath(const CFX_PathData* pPathData, - const CFX_Matrix* pObject2Device) { - const std::vector& pPoints = pPathData->GetPoints(); - for (size_t i = 0; i < pPoints.size(); i++) { - CFX_PointF pos = pPoints[i].m_Point; - if (pObject2Device) - pos = pObject2Device->Transform(pos); - - pos = HardClip(pos); - FXPT_TYPE point_type = pPoints[i].m_Type; - if (point_type == FXPT_TYPE::MoveTo) { - m_PathData.move_to(pos.x, pos.y); - } else if (point_type == FXPT_TYPE::LineTo) { - if (pPoints[i - 1].IsTypeAndOpen(FXPT_TYPE::MoveTo) && - (i == pPoints.size() - 1 || - pPoints[i + 1].IsTypeAndOpen(FXPT_TYPE::MoveTo)) && - pPoints[i].m_Point == pPoints[i - 1].m_Point) { - pos.x += 1; - } - m_PathData.line_to(pos.x, pos.y); - } else if (point_type == FXPT_TYPE::BezierTo) { - CFX_PointF pos0 = pPoints[i - 1].m_Point; - CFX_PointF pos2 = pPoints[i + 1].m_Point; - CFX_PointF pos3 = pPoints[i + 2].m_Point; - if (pObject2Device) { - pos0 = pObject2Device->Transform(pos0); - pos2 = pObject2Device->Transform(pos2); - pos3 = pObject2Device->Transform(pos3); - } - pos0 = HardClip(pos0); - pos2 = HardClip(pos2); - pos3 = HardClip(pos3); - agg::curve4 curve(pos0.x, pos0.y, pos.x, pos.y, pos2.x, pos2.y, pos3.x, - pos3.y); - i += 2; - m_PathData.add_path_curve(curve); - } - if (pPoints[i].m_CloseFigure) - m_PathData.end_poly(); - } -} - -CFX_AggDeviceDriver::CFX_AggDeviceDriver(CFX_DIBitmap* pBitmap, - bool bRgbByteOrder, - CFX_DIBitmap* pOriDevice, - bool bGroupKnockout) - : m_pBitmap(pBitmap), -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - m_pPlatformGraphics(nullptr), -#endif - m_FillFlags(0), - m_bRgbByteOrder(bRgbByteOrder), - m_pOriDevice(pOriDevice), - m_bGroupKnockout(bGroupKnockout) { - InitPlatform(); -} - -CFX_AggDeviceDriver::~CFX_AggDeviceDriver() { - DestroyPlatform(); -} - -uint8_t* CFX_AggDeviceDriver::GetBuffer() const { - return m_pBitmap->GetBuffer(); -} - -#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ -void CFX_AggDeviceDriver::InitPlatform() {} - -void CFX_AggDeviceDriver::DestroyPlatform() {} - -bool CFX_AggDeviceDriver::DrawDeviceText(int nChars, - const FXTEXT_CHARPOS* pCharPos, - CFX_Font* pFont, - const CFX_Matrix* pObject2Device, - float font_size, - uint32_t color) { - return false; -} -#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ - -int CFX_AggDeviceDriver::GetDeviceCaps(int caps_id) const { - switch (caps_id) { - case FXDC_DEVICE_CLASS: - return FXDC_DISPLAY; - case FXDC_PIXEL_WIDTH: - return m_pBitmap->GetWidth(); - case FXDC_PIXEL_HEIGHT: - return m_pBitmap->GetHeight(); - case FXDC_BITS_PIXEL: - return m_pBitmap->GetBPP(); - case FXDC_HORZ_SIZE: - case FXDC_VERT_SIZE: - return 0; - case FXDC_RENDER_CAPS: { - int flags = FXRC_GET_BITS | FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE | - FXRC_BLEND_MODE | FXRC_SOFT_CLIP; - if (m_pBitmap->HasAlpha()) { - flags |= FXRC_ALPHA_OUTPUT; - } else if (m_pBitmap->IsAlphaMask()) { - if (m_pBitmap->GetBPP() == 1) - flags |= FXRC_BITMASK_OUTPUT; - else - flags |= FXRC_BYTEMASK_OUTPUT; - } - if (m_pBitmap->IsCmykImage()) - flags |= FXRC_CMYK_OUTPUT; - return flags; - } - } - return 0; -} + void 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); -void CFX_AggDeviceDriver::SaveState() { - std::unique_ptr pClip; - if (m_pClipRgn) - pClip = pdfium::MakeUnique(*m_pClipRgn); - m_StateStack.push_back(std::move(pClip)); -} + void 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); -void CFX_AggDeviceDriver::RestoreState(bool bKeepSaved) { - m_pClipRgn.reset(); + void 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); - if (m_StateStack.empty()) - return; + void 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); - if (bKeepSaved) { - if (m_StateStack.back()) - m_pClipRgn = pdfium::MakeUnique(*m_StateStack.back()); - } else { - m_pClipRgn = std::move(m_StateStack.back()); - m_StateStack.pop_back(); - } -} + void 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); -void CFX_AggDeviceDriver::SetClipMask(agg::rasterizer_scanline_aa& rasterizer) { - FX_RECT path_rect(rasterizer.min_x(), rasterizer.min_y(), - rasterizer.max_x() + 1, rasterizer.max_y() + 1); - path_rect.Intersect(m_pClipRgn->GetBox()); - CFX_DIBitmapRef mask; - CFX_DIBitmap* pThisLayer = mask.Emplace(); - pThisLayer->Create(path_rect.Width(), path_rect.Height(), FXDIB_8bppMask); - pThisLayer->Clear(0); - agg::rendering_buffer raw_buf(pThisLayer->GetBuffer(), pThisLayer->GetWidth(), - pThisLayer->GetHeight(), - pThisLayer->GetPitch()); - agg::pixfmt_gray8 pixel_buf(raw_buf); - agg::renderer_base base_buf(pixel_buf); - agg::renderer_scanline_aa_offset > - final_render(base_buf, path_rect.left, path_rect.top); - final_render.color(agg::gray8(255)); - agg::scanline_u8 scanline; - agg::render_scanlines(rasterizer, scanline, final_render, - (m_FillFlags & FXFILL_NOPATHSMOOTH) != 0); - m_pClipRgn->IntersectMaskF(path_rect.left, path_rect.top, mask); -} + void 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); -bool CFX_AggDeviceDriver::SetClip_PathFill(const CFX_PathData* pPathData, - const CFX_Matrix* pObject2Device, - int fill_mode) { - m_FillFlags = fill_mode; - if (!m_pClipRgn) { - m_pClipRgn = pdfium::MakeUnique( - GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT)); - } - size_t size = pPathData->GetPoints().size(); - if (size == 5 || size == 4) { - CFX_FloatRect rectf; - if (pPathData->IsRect(pObject2Device, &rectf)) { - rectf.Intersect(CFX_FloatRect( - 0, 0, static_cast(GetDeviceCaps(FXDC_PIXEL_WIDTH)), - static_cast(GetDeviceCaps(FXDC_PIXEL_HEIGHT)))); - FX_RECT rect = rectf.GetOuterRect(); - m_pClipRgn->IntersectRect(rect); - return true; - } - } - CAgg_PathData path_data; - path_data.BuildPath(pPathData, pObject2Device); - path_data.m_PathData.end_poly(); - agg::rasterizer_scanline_aa rasterizer; - rasterizer.clip_box(0.0f, 0.0f, - static_cast(GetDeviceCaps(FXDC_PIXEL_WIDTH)), - static_cast(GetDeviceCaps(FXDC_PIXEL_HEIGHT))); - rasterizer.add_path(path_data.m_PathData); - rasterizer.filling_rule((fill_mode & 3) == FXFILL_WINDING - ? agg::fill_non_zero - : agg::fill_even_odd); - SetClipMask(rasterizer); - return true; -} + bool Init(CFX_DIBitmap* pDevice, + CFX_DIBitmap* pOriDevice, + const CFX_ClipRgn* pClipRgn, + uint32_t color, + bool bFullCover, + bool bRgbByteOrder, + int alpha_flag, + void* pIccTransform); -bool CFX_AggDeviceDriver::SetClip_PathStroke( - const CFX_PathData* pPathData, - const CFX_Matrix* pObject2Device, - const CFX_GraphStateData* pGraphState) { - if (!m_pClipRgn) { - m_pClipRgn = pdfium::MakeUnique( - GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT)); - } - CAgg_PathData path_data; - path_data.BuildPath(pPathData, nullptr); - agg::rasterizer_scanline_aa rasterizer; - rasterizer.clip_box(0.0f, 0.0f, - static_cast(GetDeviceCaps(FXDC_PIXEL_WIDTH)), - static_cast(GetDeviceCaps(FXDC_PIXEL_HEIGHT))); - RasterizeStroke(&rasterizer, &path_data.m_PathData, pObject2Device, - pGraphState, 1.0f, false, false); - rasterizer.filling_rule(agg::fill_non_zero); - SetClipMask(rasterizer); - return true; -} + template + void render(const Scanline& sl); -class CFX_Renderer { private: - int m_Alpha, m_Red, m_Green, m_Blue, m_Gray; - uint32_t m_Color; - bool m_bFullCover; - bool m_bRgbByteOrder; - CFX_DIBitmap* m_pOriDevice; - FX_RECT m_ClipBox; - const CFX_DIBitmap* m_pClipMask; - CFX_DIBitmap* m_pDevice; - const CFX_ClipRgn* m_pClipRgn; void (CFX_Renderer::*composite_span)(uint8_t*, int, int, @@ -608,122 +418,92 @@ class CFX_Renderer { uint8_t*, uint8_t*); - public: - void prepare(unsigned) {} + void CompositeSpan1bppHelper(uint8_t* dest_scan, + int col_start, + int col_end, + const uint8_t* cover_scan, + const uint8_t* clip_scan, + int span_left); - void 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) { - ASSERT(!m_pDevice->IsCmykImage()); - int col_start = span_left < clip_left ? clip_left - span_left : 0; - int col_end = (span_left + span_len) < clip_right - ? span_len - : (clip_right - span_left); - if (Bpp) { - dest_scan += col_start * Bpp; - ori_scan += col_start * Bpp; - } else { - dest_scan += col_start / 8; - ori_scan += col_start / 8; - } - if (m_bRgbByteOrder) { - if (Bpp == 4 && bDestAlpha) { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) - src_alpha = m_Alpha * clip_scan[col] / 255; - else - src_alpha = m_Alpha; - uint8_t dest_alpha = - ori_scan[3] + src_alpha - ori_scan[3] * src_alpha / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - if (m_bFullCover) { - *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, alpha_ratio); - *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, alpha_ratio); - *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, alpha_ratio); - dest_scan++; - ori_scan++; - } else { - int r = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, alpha_ratio); - int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, alpha_ratio); - int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, alpha_ratio); - ori_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]); - dest_scan += 2; - } - } - return; - } - if (Bpp == 3 || Bpp == 4) { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = m_Alpha * clip_scan[col] / 255; - } else { - src_alpha = m_Alpha; - } - int r = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, src_alpha); - int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha); - int b = FXDIB_ALPHA_MERGE(*ori_scan, m_Blue, src_alpha); - ori_scan += Bpp - 2; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]); - dest_scan += Bpp - 2; - } - } - return; - } + inline int GetSrcAlpha(const uint8_t* clip_scan, int col) const { + return clip_scan ? m_Alpha * clip_scan[col] / 255 : m_Alpha; + } + + inline int GetSourceAlpha(const uint8_t* cover_scan, + const uint8_t* clip_scan, + int col) const { + return clip_scan ? m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255 + : m_Alpha * cover_scan[col] / 255; + } + + inline int GetColStart(int span_left, int clip_left) const { + return span_left < clip_left ? clip_left - span_left : 0; + } + + inline int GetColEnd(int span_left, int span_len, int clip_right) const { + return span_left + span_len < clip_right ? span_len + : clip_right - span_left; + } + + int m_Alpha; + int m_Red; + int m_Green; + int m_Blue; + int m_Gray; + uint32_t m_Color; + bool m_bFullCover; + bool m_bRgbByteOrder; + CFX_DIBitmap* m_pOriDevice; + FX_RECT m_ClipBox; + const CFX_DIBitmap* m_pClipMask; + CFX_DIBitmap* m_pDevice; + const CFX_ClipRgn* m_pClipRgn; +}; + +void CFX_Renderer::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) { + ASSERT(!m_pDevice->IsCmykImage()); + int col_start = GetColStart(span_left, clip_left); + int col_end = GetColEnd(span_left, span_len, clip_right); + if (Bpp) { + dest_scan += col_start * Bpp; + ori_scan += col_start * Bpp; + } else { + dest_scan += col_start / 8; + ori_scan += col_start / 8; + } + if (m_bRgbByteOrder) { if (Bpp == 4 && bDestAlpha) { for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = m_Alpha * clip_scan[col] / 255; - } else { - src_alpha = m_Alpha; - } - int src_alpha_covered = src_alpha * cover_scan[col] / 255; - if (src_alpha_covered == 0) { - dest_scan += 4; - continue; - } - if (cover_scan[col] == 255) { - dest_scan[3] = src_alpha_covered; - *dest_scan++ = m_Blue; - *dest_scan++ = m_Green; - *dest_scan = m_Red; - dest_scan += 2; - continue; + int src_alpha = GetSrcAlpha(clip_scan, col); + uint8_t dest_alpha = + ori_scan[3] + src_alpha - ori_scan[3] * src_alpha / 255; + dest_scan[3] = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + if (m_bFullCover) { + *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, alpha_ratio); + *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, alpha_ratio); + *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, alpha_ratio); + dest_scan++; + ori_scan++; } else { - if (dest_scan[3] == 0) { - dest_scan[3] = src_alpha_covered; - *dest_scan++ = m_Blue; - *dest_scan++ = m_Green; - *dest_scan = m_Red; - dest_scan += 2; - continue; - } - uint8_t cover = cover_scan[col]; - dest_scan[3] = FXDIB_ALPHA_MERGE(dest_scan[3], src_alpha, cover); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, cover); + int r = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, alpha_ratio); + int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, alpha_ratio); + int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, alpha_ratio); + ori_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]); dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, cover); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]); dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, cover); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]); dest_scan += 2; } } @@ -731,671 +511,861 @@ class CFX_Renderer { } if (Bpp == 3 || Bpp == 4) { for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = m_Alpha * clip_scan[col] / 255; - } else { - src_alpha = m_Alpha; - } - if (m_bFullCover) { - *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha); - *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha); - *dest_scan = FXDIB_ALPHA_MERGE(*ori_scan, m_Red, src_alpha); - dest_scan += Bpp - 2; - ori_scan += Bpp - 2; - continue; - } - int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha); + int src_alpha = GetSrcAlpha(clip_scan, col); + int r = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, src_alpha); int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha); - int r = FXDIB_ALPHA_MERGE(*ori_scan, m_Red, src_alpha); + int b = FXDIB_ALPHA_MERGE(*ori_scan, m_Blue, src_alpha); ori_scan += Bpp - 2; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]); dest_scan++; *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]); dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]); dest_scan += Bpp - 2; - continue; } - return; } - if (Bpp == 1) { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = m_Alpha * clip_scan[col] / 255; - } else { - src_alpha = m_Alpha; - } - if (m_bFullCover) { - *dest_scan = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha); - } else { - int gray = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, cover_scan[col]); - dest_scan++; - } + return; + } + if (Bpp == 4 && bDestAlpha) { + for (int col = col_start; col < col_end; col++) { + int src_alpha = GetSrcAlpha(clip_scan, col); + int src_alpha_covered = src_alpha * cover_scan[col] / 255; + if (src_alpha_covered == 0) { + dest_scan += 4; + continue; } - } else { - int index = 0; - if (m_pDevice->GetPalette()) { - for (int i = 0; i < 2; i++) { - if (FXARGB_TODIB(m_pDevice->GetPalette()[i]) == m_Color) - index = i; - } - } else { - index = (static_cast(m_Color) == 0xff) ? 1 : 0; + if (cover_scan[col] == 255) { + dest_scan[3] = src_alpha_covered; + *dest_scan++ = m_Blue; + *dest_scan++ = m_Green; + *dest_scan = m_Red; + dest_scan += 2; + continue; } - uint8_t* dest_scan1 = dest_scan; - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - else - src_alpha = m_Alpha * cover_scan[col] / 255; - if (src_alpha) { - if (!index) - *dest_scan1 &= ~(1 << (7 - (col + span_left) % 8)); - else - *dest_scan1 |= 1 << (7 - (col + span_left) % 8); - } - dest_scan1 = dest_scan + (span_left % 8 + col - col_start + 1) / 8; + if (dest_scan[3] == 0) { + dest_scan[3] = src_alpha_covered; + *dest_scan++ = m_Blue; + *dest_scan++ = m_Green; + *dest_scan = m_Red; + dest_scan += 2; + continue; } + uint8_t cover = cover_scan[col]; + dest_scan[3] = FXDIB_ALPHA_MERGE(dest_scan[3], src_alpha, cover); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, cover); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, cover); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, cover); + dest_scan += 2; } + return; } - - void 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) { - ASSERT(!m_bRgbByteOrder); - ASSERT(!m_pDevice->IsCmykImage()); - int col_start = span_left < clip_left ? clip_left - span_left : 0; - int col_end = (span_left + span_len) < clip_right - ? span_len - : (clip_right - span_left); - dest_scan += col_start / 8; - int index = 0; - if (m_pDevice->GetPalette()) { - for (int i = 0; i < 2; i++) { - if (FXARGB_TODIB(m_pDevice->GetPalette()[i]) == m_Color) - index = i; - } - } else { - index = (static_cast(m_Color) == 0xff) ? 1 : 0; - } - uint8_t* dest_scan1 = dest_scan; + if (Bpp == 3 || Bpp == 4) { for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - else - src_alpha = m_Alpha * cover_scan[col] / 255; - if (src_alpha) { - if (!index) - *dest_scan1 &= ~(1 << (7 - (col + span_left) % 8)); - else - *dest_scan1 |= 1 << (7 - (col + span_left) % 8); + int src_alpha = GetSrcAlpha(clip_scan, col); + if (m_bFullCover) { + *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha); + *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha); + *dest_scan = FXDIB_ALPHA_MERGE(*ori_scan, m_Red, src_alpha); + dest_scan += Bpp - 2; + ori_scan += Bpp - 2; + continue; } - dest_scan1 = dest_scan + (span_left % 8 + col - col_start + 1) / 8; + int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha); + int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha); + int r = FXDIB_ALPHA_MERGE(*ori_scan, m_Red, src_alpha); + ori_scan += Bpp - 2; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]); + dest_scan += Bpp - 2; + continue; } + return; } - - void 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) { - ASSERT(!m_bRgbByteOrder); - int col_start = span_left < clip_left ? clip_left - span_left : 0; - int col_end = (span_left + span_len) < clip_right - ? span_len - : (clip_right - span_left); - dest_scan += col_start; - if (dest_extra_alpha_scan) { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (m_bFullCover) { - if (clip_scan) - src_alpha = m_Alpha * clip_scan[col] / 255; - else - src_alpha = m_Alpha; - } else { - if (clip_scan) - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - else - src_alpha = m_Alpha * cover_scan[col] / 255; - } - if (src_alpha) { - if (src_alpha == 255) { - *dest_scan = m_Gray; - *dest_extra_alpha_scan = m_Alpha; - } else { - uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha - - (*dest_extra_alpha_scan) * src_alpha / 255; - *dest_extra_alpha_scan++ = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, alpha_ratio); - dest_scan++; - continue; - } - } - dest_extra_alpha_scan++; - dest_scan++; - } - } else { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - else - src_alpha = m_Alpha * cover_scan[col] / 255; - if (src_alpha) { - if (src_alpha == 255) - *dest_scan = m_Gray; - else - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha); - } - dest_scan++; + if (Bpp == 1) { + for (int col = col_start; col < col_end; col++) { + int src_alpha = GetSrcAlpha(clip_scan, col); + if (m_bFullCover) { + *dest_scan = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha); + continue; } + int gray = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, cover_scan[col]); + dest_scan++; } + return; } + CompositeSpan1bppHelper(dest_scan, col_start, col_end, cover_scan, clip_scan, + span_left); +} - void 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) { - int col_start = span_left < clip_left ? clip_left - span_left : 0; - int col_end = (span_left + span_len) < clip_right - ? span_len - : (clip_right - span_left); - dest_scan += col_start * Bpp; - if (m_bRgbByteOrder) { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (m_bFullCover) { - if (clip_scan) - src_alpha = m_Alpha * clip_scan[col] / 255; - else - src_alpha = m_Alpha; - } else { - if (clip_scan) - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - else - src_alpha = m_Alpha * cover_scan[col] / 255; - } - if (src_alpha) { - if (src_alpha == 255) { - *(reinterpret_cast(dest_scan)) = m_Color; - } else { - uint8_t dest_alpha = - dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); - dest_scan += 2; - continue; - } - } - dest_scan += 4; - } - return; - } +void CFX_Renderer::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) { + ASSERT(!m_bRgbByteOrder); + ASSERT(!m_pDevice->IsCmykImage()); + int col_start = GetColStart(span_left, clip_left); + int col_end = GetColEnd(span_left, span_len, clip_right); + dest_scan += col_start / 8; + CompositeSpan1bppHelper(dest_scan, col_start, col_end, cover_scan, clip_scan, + span_left); +} + +void CFX_Renderer::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) { + ASSERT(!m_bRgbByteOrder); + int col_start = GetColStart(span_left, clip_left); + int col_end = GetColEnd(span_left, span_len, clip_right); + dest_scan += col_start; + if (dest_extra_alpha_scan) { for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (m_bFullCover) { - if (clip_scan) { - src_alpha = m_Alpha * clip_scan[col] / 255; - } else { - src_alpha = m_Alpha; - } - } else { - if (clip_scan) { - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - } else { - src_alpha = m_Alpha * cover_scan[col] / 255; - } - } + int src_alpha = m_bFullCover ? GetSrcAlpha(clip_scan, col) + : GetSourceAlpha(cover_scan, clip_scan, col); if (src_alpha) { if (src_alpha == 255) { - *(uint32_t*)dest_scan = m_Color; - } else { - if (dest_scan[3] == 0) { - dest_scan[3] = src_alpha; - *dest_scan++ = m_Blue; - *dest_scan++ = m_Green; - *dest_scan = m_Red; - dest_scan += 2; - continue; - } - uint8_t dest_alpha = - dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); - dest_scan += 2; - continue; - } - } - dest_scan += Bpp; - } - } - - void 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) { - int col_start = span_left < clip_left ? clip_left - span_left : 0; - int col_end = (span_left + span_len) < clip_right - ? span_len - : (clip_right - span_left); - dest_scan += col_start * Bpp; - if (m_bRgbByteOrder) { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) { - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - } else { - src_alpha = m_Alpha * cover_scan[col] / 255; - } - if (src_alpha) { - if (src_alpha == 255) { - if (Bpp == 4) { - *(uint32_t*)dest_scan = m_Color; - } else if (Bpp == 3) { - *dest_scan++ = m_Red; - *dest_scan++ = m_Green; - *dest_scan++ = m_Blue; - continue; - } - } else { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha); - dest_scan += Bpp - 2; - continue; - } - } - dest_scan += Bpp; - } - return; - } - if (Bpp == 3 && dest_extra_alpha_scan) { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (m_bFullCover) { - if (clip_scan) { - src_alpha = m_Alpha * clip_scan[col] / 255; - } else { - src_alpha = m_Alpha; - } + *dest_scan = m_Gray; + *dest_extra_alpha_scan = m_Alpha; } else { - if (clip_scan) - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - else - src_alpha = m_Alpha * cover_scan[col] / 255; - } - if (src_alpha) { - if (src_alpha == 255) { - *dest_scan++ = static_cast(m_Blue); - *dest_scan++ = static_cast(m_Green); - *dest_scan++ = static_cast(m_Red); - *dest_extra_alpha_scan++ = static_cast(m_Alpha); - continue; - } uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha - (*dest_extra_alpha_scan) * src_alpha / 255; *dest_extra_alpha_scan++ = dest_alpha; int alpha_ratio = src_alpha * 255 / dest_alpha; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, alpha_ratio); dest_scan++; continue; } - dest_extra_alpha_scan++; - dest_scan += Bpp; } - return; + dest_extra_alpha_scan++; + dest_scan++; + } + return; + } + for (int col = col_start; col < col_end; col++) { + int src_alpha = GetSourceAlpha(cover_scan, clip_scan, col); + if (src_alpha) { + if (src_alpha == 255) + *dest_scan = m_Gray; + else + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha); } + dest_scan++; + } +} + +void CFX_Renderer::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) { + int col_start = GetColStart(span_left, clip_left); + int col_end = GetColEnd(span_left, span_len, clip_right); + dest_scan += col_start * Bpp; + if (m_bRgbByteOrder) { for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (m_bFullCover) { - if (clip_scan) { - src_alpha = m_Alpha * clip_scan[col] / 255; + int src_alpha = m_bFullCover ? GetSrcAlpha(clip_scan, col) + : GetSourceAlpha(cover_scan, clip_scan, col); + if (src_alpha) { + if (src_alpha == 255) { + *(reinterpret_cast(dest_scan)) = m_Color; } else { - src_alpha = m_Alpha; + uint8_t dest_alpha = + dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255; + dest_scan[3] = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); + dest_scan += 2; + continue; } + } + dest_scan += 4; + } + return; + } + for (int col = col_start; col < col_end; col++) { + int src_alpha = m_bFullCover ? GetSrcAlpha(clip_scan, col) + : GetSourceAlpha(cover_scan, clip_scan, col); + if (src_alpha) { + if (src_alpha == 255) { + *(reinterpret_cast(dest_scan)) = m_Color; } else { - if (clip_scan) { - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - } else { - src_alpha = m_Alpha * cover_scan[col] / 255; + if (dest_scan[3] == 0) { + dest_scan[3] = src_alpha; + *dest_scan++ = m_Blue; + *dest_scan++ = m_Green; + *dest_scan = m_Red; + dest_scan += 2; + continue; } + uint8_t dest_alpha = + dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255; + dest_scan[3] = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); + dest_scan += 2; + continue; } + } + dest_scan += Bpp; + } +} + +void CFX_Renderer::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) { + int col_start = GetColStart(span_left, clip_left); + int col_end = GetColEnd(span_left, span_len, clip_right); + dest_scan += col_start * Bpp; + if (m_bRgbByteOrder) { + for (int col = col_start; col < col_end; col++) { + int src_alpha = GetSourceAlpha(cover_scan, clip_scan, col); if (src_alpha) { if (src_alpha == 255) { if (Bpp == 4) { *(uint32_t*)dest_scan = m_Color; } else if (Bpp == 3) { - *dest_scan++ = m_Blue; - *dest_scan++ = m_Green; *dest_scan++ = m_Red; + *dest_scan++ = m_Green; + *dest_scan++ = m_Blue; continue; } } else { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha); dest_scan++; *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha); dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha); dest_scan += Bpp - 2; continue; } } dest_scan += Bpp; } + return; } - - void 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) { - ASSERT(!m_bRgbByteOrder); - int col_start = span_left < clip_left ? clip_left - span_left : 0; - int col_end = (span_left + span_len) < clip_right - ? span_len - : (clip_right - span_left); - dest_scan += col_start * 4; - if (dest_extra_alpha_scan) { - for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (m_bFullCover) { - if (clip_scan) - src_alpha = m_Alpha * clip_scan[col] / 255; - else - src_alpha = m_Alpha; - } else { - if (clip_scan) - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - else - src_alpha = m_Alpha * cover_scan[col] / 255; + if (Bpp == 3 && dest_extra_alpha_scan) { + for (int col = col_start; col < col_end; col++) { + int src_alpha = m_bFullCover ? GetSrcAlpha(clip_scan, col) + : GetSourceAlpha(cover_scan, clip_scan, col); + if (src_alpha) { + if (src_alpha == 255) { + *dest_scan++ = static_cast(m_Blue); + *dest_scan++ = static_cast(m_Green); + *dest_scan++ = static_cast(m_Red); + *dest_extra_alpha_scan++ = static_cast(m_Alpha); + continue; } - if (src_alpha) { - if (src_alpha == 255) { - *(FX_CMYK*)dest_scan = m_Color; - *dest_extra_alpha_scan = (uint8_t)m_Alpha; - } else { - uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha - - (*dest_extra_alpha_scan) * src_alpha / 255; - *dest_extra_alpha_scan++ = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, alpha_ratio); - dest_scan++; - continue; - } + uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha - + (*dest_extra_alpha_scan) * src_alpha / 255; + *dest_extra_alpha_scan++ = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); + dest_scan++; + continue; + } + dest_extra_alpha_scan++; + dest_scan += Bpp; + } + return; + } + for (int col = col_start; col < col_end; col++) { + int src_alpha = m_bFullCover ? GetSrcAlpha(clip_scan, col) + : GetSourceAlpha(cover_scan, clip_scan, col); + if (src_alpha) { + if (src_alpha == 255) { + if (Bpp == 4) { + *(uint32_t*)dest_scan = m_Color; + } else if (Bpp == 3) { + *dest_scan++ = m_Blue; + *dest_scan++ = m_Green; + *dest_scan++ = m_Red; + continue; } - dest_extra_alpha_scan++; - dest_scan += 4; + } else { + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha); + dest_scan += Bpp - 2; + continue; } - return; } + dest_scan += Bpp; + } +} + +void CFX_Renderer::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) { + ASSERT(!m_bRgbByteOrder); + int col_start = GetColStart(span_left, clip_left); + int col_end = GetColEnd(span_left, span_len, clip_right); + dest_scan += col_start * 4; + if (dest_extra_alpha_scan) { for (int col = col_start; col < col_end; col++) { - int src_alpha; - if (clip_scan) - src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; - else - src_alpha = m_Alpha * cover_scan[col] / 255; + int src_alpha = m_bFullCover ? GetSrcAlpha(clip_scan, col) + : GetSourceAlpha(cover_scan, clip_scan, col); if (src_alpha) { if (src_alpha == 255) { - *(FX_CMYK*)dest_scan = m_Color; + *(reinterpret_cast(dest_scan)) = m_Color; + *dest_extra_alpha_scan = static_cast(m_Alpha); } else { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha); + uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha - + (*dest_extra_alpha_scan) * src_alpha / 255; + *dest_extra_alpha_scan++ = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, alpha_ratio); dest_scan++; continue; } } - dest_scan += 4; + dest_extra_alpha_scan++; + dest_scan += 4; + } + return; + } + for (int col = col_start; col < col_end; col++) { + int src_alpha = GetSourceAlpha(cover_scan, clip_scan, col); + if (src_alpha) { + if (src_alpha == 255) { + *(reinterpret_cast(dest_scan)) = m_Color; + } else { + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha); + dest_scan++; + continue; + } + } + dest_scan += 4; + } +} + +bool CFX_Renderer::Init(CFX_DIBitmap* pDevice, + CFX_DIBitmap* pOriDevice, + const CFX_ClipRgn* pClipRgn, + uint32_t color, + bool bFullCover, + bool bRgbByteOrder, + int alpha_flag, + void* pIccTransform) { + m_pDevice = pDevice; + m_pClipRgn = pClipRgn; + composite_span = nullptr; + m_bRgbByteOrder = bRgbByteOrder; + m_pOriDevice = pOriDevice; + if (m_pClipRgn) { + m_ClipBox = m_pClipRgn->GetBox(); + } else { + m_ClipBox.left = m_ClipBox.top = 0; + m_ClipBox.right = m_pDevice->GetWidth(); + m_ClipBox.bottom = m_pDevice->GetHeight(); + } + m_pClipMask = nullptr; + if (m_pClipRgn && m_pClipRgn->GetType() == CFX_ClipRgn::MaskF) + m_pClipMask = m_pClipRgn->GetMask().GetObject(); + m_bFullCover = bFullCover; + bool bObjectCMYK = !!FXGETFLAG_COLORTYPE(alpha_flag); + bool bDeviceCMYK = pDevice->IsCmykImage(); + m_Alpha = bObjectCMYK ? FXGETFLAG_ALPHA_FILL(alpha_flag) : FXARGB_A(color); + CCodec_IccModule* pIccModule = nullptr; + if (!CFX_GEModule::Get()->GetCodecModule() || + !CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) { + pIccTransform = nullptr; + } else { + pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); + } + if (m_pDevice->GetBPP() == 8) { + ASSERT(!m_bRgbByteOrder); + composite_span = &CFX_Renderer::CompositeSpanGray; + if (m_pDevice->IsAlphaMask()) { + m_Gray = 255; + } else { + if (pIccTransform) { + uint8_t gray; + color = bObjectCMYK ? FXCMYK_TODIB(color) : FXARGB_TODIB(color); + pIccModule->TranslateScanline(pIccTransform, &gray, + (const uint8_t*)&color, 1); + m_Gray = gray; + } else { + if (bObjectCMYK) { + uint8_t r, g, b; + AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color), + FXSYS_GetYValue(color), FXSYS_GetKValue(color), r, + g, b); + m_Gray = FXRGB2GRAY(r, g, b); + } else { + m_Gray = + FXRGB2GRAY(FXARGB_R(color), FXARGB_G(color), FXARGB_B(color)); + } + } + } + return true; + } + if (bDeviceCMYK) { + ASSERT(!m_bRgbByteOrder); + composite_span = &CFX_Renderer::CompositeSpanCMYK; + if (bObjectCMYK) { + m_Color = FXCMYK_TODIB(color); + if (pIccTransform) { + uint8_t* pColor = reinterpret_cast(&m_Color); + pIccModule->TranslateScanline(pIccTransform, pColor, pColor, 1); + } + } else { + if (!pIccTransform) + return false; + + color = FXARGB_TODIB(color); + pIccModule->TranslateScanline( + pIccTransform, reinterpret_cast(&m_Color), + reinterpret_cast(&color), 1); + } + uint8_t* pColor = reinterpret_cast(&m_Color); + m_Red = pColor[0]; + m_Green = pColor[1]; + m_Blue = pColor[2]; + m_Gray = pColor[3]; + } else { + composite_span = (pDevice->GetFormat() == FXDIB_Argb) + ? &CFX_Renderer::CompositeSpanARGB + : &CFX_Renderer::CompositeSpanRGB; + if (pIccTransform) { + color = bObjectCMYK ? FXCMYK_TODIB(color) : FXARGB_TODIB(color); + pIccModule->TranslateScanline( + pIccTransform, reinterpret_cast(&m_Color), + reinterpret_cast(&color), 1); + uint8_t* pColor = reinterpret_cast(&m_Color); + pColor[3] = m_Alpha; + m_Red = pColor[2]; + m_Green = pColor[1]; + m_Blue = pColor[0]; + if (m_bRgbByteOrder) + m_Color = FXARGB_TOBGRORDERDIB(FXARGB_TODIB(m_Color)); + } else { + if (bObjectCMYK) { + uint8_t r, g, b; + AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color), + FXSYS_GetYValue(color), FXSYS_GetKValue(color), r, g, + b); + m_Color = FXARGB_MAKE(m_Alpha, r, g, b); + if (m_bRgbByteOrder) + m_Color = FXARGB_TOBGRORDERDIB(m_Color); + else + m_Color = FXARGB_TODIB(m_Color); + m_Red = r; + m_Green = g; + m_Blue = b; + } else { + if (m_bRgbByteOrder) + m_Color = FXARGB_TOBGRORDERDIB(color); + else + m_Color = FXARGB_TODIB(color); + ArgbDecode(color, m_Alpha, m_Red, m_Green, m_Blue); + } + } + } + if (m_pDevice->GetBPP() == 1) + composite_span = &CFX_Renderer::CompositeSpan1bpp; + return true; +} + +template +void CFX_Renderer::render(const Scanline& sl) { + if (!m_pOriDevice && !composite_span) + return; + + int y = sl.y(); + if (y < m_ClipBox.top || y >= m_ClipBox.bottom) + return; + + uint8_t* dest_scan = m_pDevice->GetBuffer() + m_pDevice->GetPitch() * y; + uint8_t* dest_scan_extra_alpha = nullptr; + CFX_DIBitmap* pAlphaMask = m_pDevice->m_pAlphaMask; + if (pAlphaMask) { + dest_scan_extra_alpha = + pAlphaMask->GetBuffer() + pAlphaMask->GetPitch() * y; + } + uint8_t* ori_scan = nullptr; + if (m_pOriDevice) + ori_scan = m_pOriDevice->GetBuffer() + m_pOriDevice->GetPitch() * y; + int Bpp = m_pDevice->GetBPP() / 8; + bool bDestAlpha = m_pDevice->HasAlpha() || m_pDevice->IsAlphaMask(); + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + while (1) { + int x = span->x; + ASSERT(span->len > 0); + uint8_t* dest_pos = nullptr; + uint8_t* dest_extra_alpha_pos = nullptr; + uint8_t* ori_pos = nullptr; + if (Bpp) { + ori_pos = ori_scan ? ori_scan + x * Bpp : nullptr; + dest_pos = dest_scan + x * Bpp; + dest_extra_alpha_pos = + dest_scan_extra_alpha ? dest_scan_extra_alpha + x : nullptr; + } else { + dest_pos = dest_scan + x / 8; + ori_pos = ori_scan ? ori_scan + x / 8 : nullptr; + } + uint8_t* clip_pos = nullptr; + if (m_pClipMask) { + clip_pos = m_pClipMask->GetBuffer() + + (y - m_ClipBox.top) * m_pClipMask->GetPitch() + x - + m_ClipBox.left; + } + if (ori_pos) { + CompositeSpan(dest_pos, ori_pos, Bpp, bDestAlpha, x, span->len, + span->covers, m_ClipBox.left, m_ClipBox.right, clip_pos); + } else { + (this->*composite_span)(dest_pos, Bpp, x, span->len, span->covers, + m_ClipBox.left, m_ClipBox.right, clip_pos, + dest_extra_alpha_pos); + } + if (--num_spans == 0) + break; + + ++span; + } +} + +void CFX_Renderer::CompositeSpan1bppHelper(uint8_t* dest_scan, + int col_start, + int col_end, + const uint8_t* cover_scan, + const uint8_t* clip_scan, + int span_left) { + int index = 0; + if (m_pDevice->GetPalette()) { + for (int i = 0; i < 2; i++) { + if (FXARGB_TODIB(m_pDevice->GetPalette()[i]) == m_Color) + index = i; + } + } else { + index = (static_cast(m_Color) == 0xff) ? 1 : 0; + } + uint8_t* dest_scan1 = dest_scan; + for (int col = col_start; col < col_end; col++) { + int src_alpha = GetSourceAlpha(cover_scan, clip_scan, col); + if (src_alpha) { + if (!index) + *dest_scan1 &= ~(1 << (7 - (col + span_left) % 8)); + else + *dest_scan1 |= 1 << (7 - (col + span_left) % 8); + } + dest_scan1 = dest_scan + (span_left % 8 + col - col_start + 1) / 8; + } +} + +} // namespace + +namespace agg { + +template +class renderer_scanline_aa_offset { + public: + typedef BaseRenderer base_ren_type; + typedef typename base_ren_type::color_type color_type; + renderer_scanline_aa_offset(base_ren_type& ren, unsigned left, unsigned top) + : m_ren(&ren), m_left(left), m_top(top) {} + void color(const color_type& c) { m_color = c; } + const color_type& color() const { return m_color; } + void prepare(unsigned) {} + template + void render(const Scanline& sl) { + int y = sl.y(); + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + while (1) { + int x = span->x; + if (span->len > 0) { + m_ren->blend_solid_hspan(x - m_left, y - m_top, (unsigned)span->len, + m_color, span->covers); + } else { + m_ren->blend_hline(x - m_left, y - m_top, (unsigned)(x - span->len - 1), + m_color, *(span->covers)); + } + if (--num_spans == 0) + break; + + ++span; + } + } + + private: + base_ren_type* m_ren; + color_type m_color; + unsigned m_left, m_top; +}; + +} // namespace agg + +void CAgg_PathData::BuildPath(const CFX_PathData* pPathData, + const CFX_Matrix* pObject2Device) { + const std::vector& pPoints = pPathData->GetPoints(); + for (size_t i = 0; i < pPoints.size(); i++) { + CFX_PointF pos = pPoints[i].m_Point; + if (pObject2Device) + pos = pObject2Device->Transform(pos); + + pos = HardClip(pos); + FXPT_TYPE point_type = pPoints[i].m_Type; + if (point_type == FXPT_TYPE::MoveTo) { + m_PathData.move_to(pos.x, pos.y); + } else if (point_type == FXPT_TYPE::LineTo) { + if (pPoints[i - 1].IsTypeAndOpen(FXPT_TYPE::MoveTo) && + (i == pPoints.size() - 1 || + pPoints[i + 1].IsTypeAndOpen(FXPT_TYPE::MoveTo)) && + pPoints[i].m_Point == pPoints[i - 1].m_Point) { + pos.x += 1; + } + m_PathData.line_to(pos.x, pos.y); + } else if (point_type == FXPT_TYPE::BezierTo) { + CFX_PointF pos0 = pPoints[i - 1].m_Point; + CFX_PointF pos2 = pPoints[i + 1].m_Point; + CFX_PointF pos3 = pPoints[i + 2].m_Point; + if (pObject2Device) { + pos0 = pObject2Device->Transform(pos0); + pos2 = pObject2Device->Transform(pos2); + pos3 = pObject2Device->Transform(pos3); + } + pos0 = HardClip(pos0); + pos2 = HardClip(pos2); + pos3 = HardClip(pos3); + agg::curve4 curve(pos0.x, pos0.y, pos.x, pos.y, pos2.x, pos2.y, pos3.x, + pos3.y); + i += 2; + m_PathData.add_path_curve(curve); } + if (pPoints[i].m_CloseFigure) + m_PathData.end_poly(); } +} - template - void render(const Scanline& sl) { - if (!m_pOriDevice && !composite_span) { - return; - } - int y = sl.y(); - if (y < m_ClipBox.top || y >= m_ClipBox.bottom) { - return; - } - uint8_t* dest_scan = m_pDevice->GetBuffer() + m_pDevice->GetPitch() * y; - uint8_t* dest_scan_extra_alpha = nullptr; - CFX_DIBitmap* pAlphaMask = m_pDevice->m_pAlphaMask; - if (pAlphaMask) { - dest_scan_extra_alpha = - pAlphaMask->GetBuffer() + pAlphaMask->GetPitch() * y; - } - uint8_t* ori_scan = nullptr; - if (m_pOriDevice) { - ori_scan = m_pOriDevice->GetBuffer() + m_pOriDevice->GetPitch() * y; - } - int Bpp = m_pDevice->GetBPP() / 8; - bool bDestAlpha = m_pDevice->HasAlpha() || m_pDevice->IsAlphaMask(); - unsigned num_spans = sl.num_spans(); - typename Scanline::const_iterator span = sl.begin(); - while (1) { - int x = span->x; - ASSERT(span->len > 0); - uint8_t* dest_pos = nullptr; - uint8_t* dest_extra_alpha_pos = nullptr; - uint8_t* ori_pos = nullptr; - if (Bpp) { - ori_pos = ori_scan ? ori_scan + x * Bpp : nullptr; - dest_pos = dest_scan + x * Bpp; - dest_extra_alpha_pos = - dest_scan_extra_alpha ? dest_scan_extra_alpha + x : nullptr; - } else { - dest_pos = dest_scan + x / 8; - ori_pos = ori_scan ? ori_scan + x / 8 : nullptr; - } - uint8_t* clip_pos = nullptr; - if (m_pClipMask) { - clip_pos = m_pClipMask->GetBuffer() + - (y - m_ClipBox.top) * m_pClipMask->GetPitch() + x - - m_ClipBox.left; - } - if (ori_pos) { - CompositeSpan(dest_pos, ori_pos, Bpp, bDestAlpha, x, span->len, - span->covers, m_ClipBox.left, m_ClipBox.right, clip_pos); - } else { - (this->*composite_span)(dest_pos, Bpp, x, span->len, span->covers, - m_ClipBox.left, m_ClipBox.right, clip_pos, - dest_extra_alpha_pos); - } - if (--num_spans == 0) { - break; +CFX_AggDeviceDriver::CFX_AggDeviceDriver(CFX_DIBitmap* pBitmap, + bool bRgbByteOrder, + CFX_DIBitmap* pOriDevice, + bool bGroupKnockout) + : m_pBitmap(pBitmap), +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ + m_pPlatformGraphics(nullptr), +#endif + m_FillFlags(0), + m_bRgbByteOrder(bRgbByteOrder), + m_pOriDevice(pOriDevice), + m_bGroupKnockout(bGroupKnockout) { + InitPlatform(); +} + +CFX_AggDeviceDriver::~CFX_AggDeviceDriver() { + DestroyPlatform(); +} + +uint8_t* CFX_AggDeviceDriver::GetBuffer() const { + return m_pBitmap->GetBuffer(); +} + +#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ +void CFX_AggDeviceDriver::InitPlatform() {} + +void CFX_AggDeviceDriver::DestroyPlatform() {} + +bool CFX_AggDeviceDriver::DrawDeviceText(int nChars, + const FXTEXT_CHARPOS* pCharPos, + CFX_Font* pFont, + const CFX_Matrix* pObject2Device, + float font_size, + uint32_t color) { + return false; +} +#endif // _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ + +int CFX_AggDeviceDriver::GetDeviceCaps(int caps_id) const { + switch (caps_id) { + case FXDC_DEVICE_CLASS: + return FXDC_DISPLAY; + case FXDC_PIXEL_WIDTH: + return m_pBitmap->GetWidth(); + case FXDC_PIXEL_HEIGHT: + return m_pBitmap->GetHeight(); + case FXDC_BITS_PIXEL: + return m_pBitmap->GetBPP(); + case FXDC_HORZ_SIZE: + case FXDC_VERT_SIZE: + return 0; + case FXDC_RENDER_CAPS: { + int flags = FXRC_GET_BITS | FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE | + FXRC_BLEND_MODE | FXRC_SOFT_CLIP; + if (m_pBitmap->HasAlpha()) { + flags |= FXRC_ALPHA_OUTPUT; + } else if (m_pBitmap->IsAlphaMask()) { + if (m_pBitmap->GetBPP() == 1) + flags |= FXRC_BITMASK_OUTPUT; + else + flags |= FXRC_BYTEMASK_OUTPUT; } - ++span; + if (m_pBitmap->IsCmykImage()) + flags |= FXRC_CMYK_OUTPUT; + return flags; } + default: + return 0; } +} - bool 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) { - m_pDevice = pDevice; - m_pClipRgn = pClipRgn; - composite_span = nullptr; - m_bRgbByteOrder = bRgbByteOrder; - m_pOriDevice = pOriDevice; - if (m_pClipRgn) { - m_ClipBox = m_pClipRgn->GetBox(); - } else { - m_ClipBox.left = m_ClipBox.top = 0; - m_ClipBox.right = m_pDevice->GetWidth(); - m_ClipBox.bottom = m_pDevice->GetHeight(); - } - m_pClipMask = nullptr; - if (m_pClipRgn && m_pClipRgn->GetType() == CFX_ClipRgn::MaskF) { - m_pClipMask = m_pClipRgn->GetMask().GetObject(); - } - m_bFullCover = bFullCover; - bool bObjectCMYK = !!FXGETFLAG_COLORTYPE(alpha_flag); - bool bDeviceCMYK = pDevice->IsCmykImage(); - m_Alpha = bObjectCMYK ? FXGETFLAG_ALPHA_FILL(alpha_flag) : FXARGB_A(color); - CCodec_IccModule* pIccModule = nullptr; - if (!CFX_GEModule::Get()->GetCodecModule() || - !CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) { - pIccTransform = nullptr; - } else { - pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); - } - if (m_pDevice->GetBPP() == 8) { - ASSERT(!m_bRgbByteOrder); - composite_span = &CFX_Renderer::CompositeSpanGray; - if (m_pDevice->IsAlphaMask()) { - m_Gray = 255; - } else { - if (pIccTransform) { - uint8_t gray; - color = bObjectCMYK ? FXCMYK_TODIB(color) : FXARGB_TODIB(color); - pIccModule->TranslateScanline(pIccTransform, &gray, - (const uint8_t*)&color, 1); - m_Gray = gray; - } else { - if (bObjectCMYK) { - uint8_t r, g, b; - AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color), - FXSYS_GetYValue(color), FXSYS_GetKValue(color), - r, g, b); - m_Gray = FXRGB2GRAY(r, g, b); - } else { - m_Gray = - FXRGB2GRAY(FXARGB_R(color), FXARGB_G(color), FXARGB_B(color)); - } - } - } +void CFX_AggDeviceDriver::SaveState() { + std::unique_ptr pClip; + if (m_pClipRgn) + pClip = pdfium::MakeUnique(*m_pClipRgn); + m_StateStack.push_back(std::move(pClip)); +} + +void CFX_AggDeviceDriver::RestoreState(bool bKeepSaved) { + m_pClipRgn.reset(); + + if (m_StateStack.empty()) + return; + + if (bKeepSaved) { + if (m_StateStack.back()) + m_pClipRgn = pdfium::MakeUnique(*m_StateStack.back()); + } else { + m_pClipRgn = std::move(m_StateStack.back()); + m_StateStack.pop_back(); + } +} + +void CFX_AggDeviceDriver::SetClipMask(agg::rasterizer_scanline_aa& rasterizer) { + FX_RECT path_rect(rasterizer.min_x(), rasterizer.min_y(), + rasterizer.max_x() + 1, rasterizer.max_y() + 1); + path_rect.Intersect(m_pClipRgn->GetBox()); + CFX_DIBitmapRef mask; + CFX_DIBitmap* pThisLayer = mask.Emplace(); + pThisLayer->Create(path_rect.Width(), path_rect.Height(), FXDIB_8bppMask); + pThisLayer->Clear(0); + agg::rendering_buffer raw_buf(pThisLayer->GetBuffer(), pThisLayer->GetWidth(), + pThisLayer->GetHeight(), + pThisLayer->GetPitch()); + agg::pixfmt_gray8 pixel_buf(raw_buf); + agg::renderer_base base_buf(pixel_buf); + agg::renderer_scanline_aa_offset > + final_render(base_buf, path_rect.left, path_rect.top); + final_render.color(agg::gray8(255)); + agg::scanline_u8 scanline; + agg::render_scanlines(rasterizer, scanline, final_render, + (m_FillFlags & FXFILL_NOPATHSMOOTH) != 0); + m_pClipRgn->IntersectMaskF(path_rect.left, path_rect.top, mask); +} + +bool CFX_AggDeviceDriver::SetClip_PathFill(const CFX_PathData* pPathData, + const CFX_Matrix* pObject2Device, + int fill_mode) { + m_FillFlags = fill_mode; + if (!m_pClipRgn) { + m_pClipRgn = pdfium::MakeUnique( + GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT)); + } + size_t size = pPathData->GetPoints().size(); + if (size == 5 || size == 4) { + CFX_FloatRect rectf; + if (pPathData->IsRect(pObject2Device, &rectf)) { + rectf.Intersect(CFX_FloatRect( + 0, 0, static_cast(GetDeviceCaps(FXDC_PIXEL_WIDTH)), + static_cast(GetDeviceCaps(FXDC_PIXEL_HEIGHT)))); + FX_RECT rect = rectf.GetOuterRect(); + m_pClipRgn->IntersectRect(rect); return true; } - if (bDeviceCMYK) { - ASSERT(!m_bRgbByteOrder); - composite_span = &CFX_Renderer::CompositeSpanCMYK; - if (bObjectCMYK) { - m_Color = FXCMYK_TODIB(color); - if (pIccTransform) { - pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&m_Color, - (const uint8_t*)&m_Color, 1); - } - } else { - if (!pIccTransform) { - return false; - } - color = FXARGB_TODIB(color); - pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&m_Color, - (const uint8_t*)&color, 1); - } - m_Red = ((uint8_t*)&m_Color)[0]; - m_Green = ((uint8_t*)&m_Color)[1]; - m_Blue = ((uint8_t*)&m_Color)[2]; - m_Gray = ((uint8_t*)&m_Color)[3]; - } else { - composite_span = (pDevice->GetFormat() == FXDIB_Argb) - ? &CFX_Renderer::CompositeSpanARGB - : &CFX_Renderer::CompositeSpanRGB; - if (pIccTransform) { - color = bObjectCMYK ? FXCMYK_TODIB(color) : FXARGB_TODIB(color); - pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&m_Color, - (const uint8_t*)&color, 1); - ((uint8_t*)&m_Color)[3] = m_Alpha; - m_Red = ((uint8_t*)&m_Color)[2]; - m_Green = ((uint8_t*)&m_Color)[1]; - m_Blue = ((uint8_t*)&m_Color)[0]; - if (m_bRgbByteOrder) { - m_Color = FXARGB_TODIB(m_Color); - m_Color = FXARGB_TOBGRORDERDIB(m_Color); - } - } else { - if (bObjectCMYK) { - uint8_t r, g, b; - AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color), - FXSYS_GetYValue(color), FXSYS_GetKValue(color), r, - g, b); - m_Color = FXARGB_MAKE(m_Alpha, r, g, b); - if (m_bRgbByteOrder) { - m_Color = FXARGB_TOBGRORDERDIB(m_Color); - } else { - m_Color = FXARGB_TODIB(m_Color); - } - m_Red = r; - m_Green = g; - m_Blue = b; - } else { - if (m_bRgbByteOrder) { - m_Color = FXARGB_TOBGRORDERDIB(color); - } else { - m_Color = FXARGB_TODIB(color); - } - ArgbDecode(color, m_Alpha, m_Red, m_Green, m_Blue); - } - } - } - if (m_pDevice->GetBPP() == 1) { - composite_span = &CFX_Renderer::CompositeSpan1bpp; - } - return true; } -}; + CAgg_PathData path_data; + path_data.BuildPath(pPathData, pObject2Device); + path_data.m_PathData.end_poly(); + agg::rasterizer_scanline_aa rasterizer; + rasterizer.clip_box(0.0f, 0.0f, + static_cast(GetDeviceCaps(FXDC_PIXEL_WIDTH)), + static_cast(GetDeviceCaps(FXDC_PIXEL_HEIGHT))); + rasterizer.add_path(path_data.m_PathData); + rasterizer.filling_rule((fill_mode & 3) == FXFILL_WINDING + ? agg::fill_non_zero + : agg::fill_even_odd); + SetClipMask(rasterizer); + return true; +} + +bool CFX_AggDeviceDriver::SetClip_PathStroke( + const CFX_PathData* pPathData, + const CFX_Matrix* pObject2Device, + const CFX_GraphStateData* pGraphState) { + if (!m_pClipRgn) { + m_pClipRgn = pdfium::MakeUnique( + GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT)); + } + CAgg_PathData path_data; + path_data.BuildPath(pPathData, nullptr); + agg::rasterizer_scanline_aa rasterizer; + rasterizer.clip_box(0.0f, 0.0f, + static_cast(GetDeviceCaps(FXDC_PIXEL_WIDTH)), + static_cast(GetDeviceCaps(FXDC_PIXEL_HEIGHT))); + RasterizeStroke(&rasterizer, &path_data.m_PathData, pObject2Device, + pGraphState, 1.0f, false, false); + rasterizer.filling_rule(agg::fill_non_zero); + SetClipMask(rasterizer); + return true; +} int CFX_AggDeviceDriver::GetDriverType() const { return 1; @@ -1682,17 +1652,16 @@ bool CFX_AggDeviceDriver::StartDIBits(const CFX_DIBSource* pSource, } bool CFX_AggDeviceDriver::ContinueDIBits(void* pHandle, IFX_Pause* pPause) { - if (!m_pBitmap->GetBuffer()) { - return true; - } - return ((CFX_ImageRenderer*)pHandle)->Continue(pPause); + return m_pBitmap->GetBuffer() + ? reinterpret_cast(pHandle)->Continue(pPause) + : true; } void CFX_AggDeviceDriver::CancelDIBits(void* pHandle) { - if (!m_pBitmap->GetBuffer()) { + if (!m_pBitmap->GetBuffer()) return; - } - delete (CFX_ImageRenderer*)pHandle; + + delete reinterpret_cast(pHandle); } #ifndef _SKIA_SUPPORT_ @@ -1730,8 +1699,7 @@ bool CFX_FxgeDevice::Create(int width, } CFX_FxgeDevice::~CFX_FxgeDevice() { - if (m_bOwnedBitmap) { + if (m_bOwnedBitmap) delete GetBitmap(); - } } #endif -- cgit v1.2.3