bool CFX_RenderDevice::DrawPathWithBlend(const CFX_PathData* pPathData, const CFX_Matrix* pObject2Device, const CFX_GraphStateData* pGraphState, uint32_t fill_color, uint32_t stroke_color, int fill_mode, BlendMode blend_type) { uint8_t stroke_alpha = pGraphState ? FXARGB_A(stroke_color) : 0; uint8_t fill_alpha = (fill_mode & 3) ? FXARGB_A(fill_color) : 0; const std::vector<FX_PATHPOINT>& pPoints = pPathData->GetPoints(); if (stroke_alpha == 0 && pPoints.size() == 2) { CFX_PointF pos1 = pPoints[0].m_Point; CFX_PointF pos2 = pPoints[1].m_Point; if (pObject2Device) { pos1 = pObject2Device->Transform(pos1); pos2 = pObject2Device->Transform(pos2); } DrawCosmeticLine(pos1, pos2, fill_color, fill_mode, blend_type); return true; } if ((pPoints.size() == 5 || pPoints.size() == 4) && stroke_alpha == 0) { CFX_FloatRect rect_f; if (!(fill_mode & FXFILL_RECT_AA) && pPathData->IsRect(pObject2Device, &rect_f)) { FX_RECT rect_i = rect_f.GetOuterRect(); // Depending on the top/bottom, left/right values of the rect it's // possible to overflow the Width() and Height() calculations. Check that // the rect will have valid dimension before continuing. if (!rect_i.Valid()) return false; int width = static_cast<int>(ceil(rect_f.right - rect_f.left)); if (width < 1) { width = 1; if (rect_i.left == rect_i.right) ++rect_i.right; } int height = static_cast<int>(ceil(rect_f.top - rect_f.bottom)); if (height < 1) { height = 1; if (rect_i.bottom == rect_i.top) ++rect_i.bottom; } if (rect_i.Width() >= width + 1) { if (rect_f.left - static_cast<float>(rect_i.left) > static_cast<float>(rect_i.right) - rect_f.right) { ++rect_i.left; } else { --rect_i.right; } } if (rect_i.Height() >= height + 1) { if (rect_f.top - static_cast<float>(rect_i.top) > static_cast<float>(rect_i.bottom) - rect_f.bottom) { ++rect_i.top; } else { --rect_i.bottom; } } if (FillRectWithBlend(rect_i, fill_color, blend_type)) return true; } } if ((fill_mode & 3) && stroke_alpha == 0 && !(fill_mode & FX_FILL_STROKE) && !(fill_mode & FX_FILL_TEXT_MODE)) { CFX_PathData newPath; bool bThin = false; bool setIdentity = false; if (pPathData->GetZeroAreaPath(pObject2Device, !!m_pDeviceDriver->GetDriverType(), &newPath, &bThin, &setIdentity)) { CFX_GraphStateData graphState; graphState.m_LineWidth = 0.0f; uint32_t strokecolor = fill_color; if (bThin) strokecolor = (((fill_alpha >> 2) << 24) | (strokecolor & 0x00ffffff)); const CFX_Matrix* pMatrix = nullptr; if (pObject2Device && !pObject2Device->IsIdentity() && !setIdentity) pMatrix = pObject2Device; int smooth_path = FX_ZEROAREA_FILL; if (fill_mode & FXFILL_NOPATHSMOOTH) smooth_path |= FXFILL_NOPATHSMOOTH; m_pDeviceDriver->DrawPath(&newPath, pMatrix, &graphState, 0, strokecolor, smooth_path, blend_type); }
bool CFX_RenderDevice::DrawPathWithBlend(const CFX_PathData* pPathData, const CFX_Matrix* pObject2Device, const CFX_GraphStateData* pGraphState, uint32_t fill_color, uint32_t stroke_color, int fill_mode, int blend_type) { uint8_t stroke_alpha = pGraphState ? FXARGB_A(stroke_color) : 0; uint8_t fill_alpha = (fill_mode & 3) ? FXARGB_A(fill_color) : 0; if (stroke_alpha == 0 && pPathData->GetPointCount() == 2) { FX_PATHPOINT* pPoints = pPathData->GetPoints(); FX_FLOAT x1, x2, y1, y2; if (pObject2Device) { pObject2Device->Transform(pPoints[0].m_PointX, pPoints[0].m_PointY, x1, y1); pObject2Device->Transform(pPoints[1].m_PointX, pPoints[1].m_PointY, x2, y2); } else { x1 = pPoints[0].m_PointX; y1 = pPoints[0].m_PointY; x2 = pPoints[1].m_PointX; y2 = pPoints[1].m_PointY; } DrawCosmeticLine(x1, y1, x2, y2, fill_color, fill_mode, blend_type); return true; } if ((pPathData->GetPointCount() == 5 || pPathData->GetPointCount() == 4) && stroke_alpha == 0) { CFX_FloatRect rect_f; if (!(fill_mode & FXFILL_RECT_AA) && pPathData->IsRect(pObject2Device, &rect_f)) { FX_RECT rect_i = rect_f.GetOuterRect(); // Depending on the top/bottom, left/right values of the rect it's // possible to overflow the Width() and Height() calculations. Check that // the rect will have valid dimension before continuing. if (!rect_i.Valid()) return false; int width = (int)FXSYS_ceil(rect_f.right - rect_f.left); if (width < 1) { width = 1; if (rect_i.left == rect_i.right) rect_i.right++; } int height = (int)FXSYS_ceil(rect_f.top - rect_f.bottom); if (height < 1) { height = 1; if (rect_i.bottom == rect_i.top) rect_i.bottom++; } if (rect_i.Width() >= width + 1) { if (rect_f.left - (FX_FLOAT)(rect_i.left) > (FX_FLOAT)(rect_i.right) - rect_f.right) { rect_i.left++; } else { rect_i.right--; } } if (rect_i.Height() >= height + 1) { if (rect_f.top - (FX_FLOAT)(rect_i.top) > (FX_FLOAT)(rect_i.bottom) - rect_f.bottom) { rect_i.top++; } else { rect_i.bottom--; } } if (FillRectWithBlend(&rect_i, fill_color, blend_type)) return true; } } if ((fill_mode & 3) && stroke_alpha == 0 && !(fill_mode & FX_FILL_STROKE) && !(fill_mode & FX_FILL_TEXT_MODE)) { CFX_PathData newPath; bool bThin = false; if (pPathData->GetZeroAreaPath(newPath, (CFX_Matrix*)pObject2Device, bThin, !!m_pDeviceDriver->GetDriverType())) { CFX_GraphStateData graphState; graphState.m_LineWidth = 0.0f; uint32_t strokecolor = fill_color; if (bThin) strokecolor = (((fill_alpha >> 2) << 24) | (strokecolor & 0x00ffffff)); CFX_Matrix* pMatrix = nullptr; if (pObject2Device && !pObject2Device->IsIdentity()) pMatrix = (CFX_Matrix*)pObject2Device; int smooth_path = FX_ZEROAREA_FILL; if (fill_mode & FXFILL_NOPATHSMOOTH) smooth_path |= FXFILL_NOPATHSMOOTH; m_pDeviceDriver->DrawPath(&newPath, pMatrix, &graphState, 0, strokecolor, smooth_path, blend_type); }