7#include "xfa/fgas/graphics/cfgas_gegraphics.h"
16#include "core/fxcrt/check.h"
17#include "core/fxcrt/fx_system.h"
18#include "core/fxcrt/span_util.h"
19#include "core/fxcrt/stl_util.h"
20#include "core/fxge/cfx_defaultrenderdevice.h"
21#include "core/fxge/cfx_renderdevice.h"
22#include "core/fxge/cfx_unicodeencoding.h"
23#include "core/fxge/dib/cfx_dibitmap.h"
24#include "xfa/fgas/graphics/cfgas_gecolor.h"
25#include "xfa/fgas/graphics/cfgas_gepath.h"
26#include "xfa/fgas/graphics/cfgas_gepattern.h"
27#include "xfa/fgas/graphics/cfgas_geshading.h"
37constexpr auto kHatchBitmapData =
fxcrt::ToArray<
const FX_HATCHDATA>({
41 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
42 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
43 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
44 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
45 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
46 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00,
52 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80,
53 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80,
54 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
55 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00,
56 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
61 0x80, 0x80, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x20, 0x20, 0x00,
62 0x00, 0x10, 0x10, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x04, 0x04,
63 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x80,
64 0x80, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00,
65 0x10, 0x10, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x04, 0x04, 0x00,
66 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,
71 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x04, 0x04, 0x00,
72 0x00, 0x08, 0x08, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x20, 0x20,
73 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x01,
74 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00,
75 0x08, 0x08, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x20, 0x20, 0x00,
76 0x00, 0x40, 0x40, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
81 0xff, 0xff, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00,
82 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80,
83 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0xff,
84 0xff, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
85 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00,
86 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
91 0x81, 0x81, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x24, 0x24, 0x00,
92 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x24, 0x24,
93 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x81, 0x81, 0x00, 0x00, 0x81,
94 0x81, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00,
95 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x24, 0x24, 0x00,
96 0x00, 0x42, 0x42, 0x00, 0x00, 0x81, 0x81, 0x00, 0x00,
100const FX_HATCHDATA kHatchPlaceHolder = {
104 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
106 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
108 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
109 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
112const FX_HATCHDATA& GetHatchBitmapData(size_t index) {
113 return index <
std::size(kHatchBitmapData) ? kHatchBitmapData[index]
127 m_renderDevice->SaveState();
128 m_infoStack.push_back(std::make_unique<TInfo>(m_info));
132 m_renderDevice->RestoreState(
false);
133 CHECK(!m_infoStack.empty());
134 m_info = *m_infoStack.back();
135 m_infoStack.pop_back();
140 m_info.graphState.m_LineCap = lineCap;
144 pdfium::span<
const float> dashArray) {
145 DCHECK(!dashArray.empty());
146 float scale = m_info.isActOnDash ? m_info.graphState.m_LineWidth : 1.0;
147 m_info.graphState.m_DashPhase = dashPhase;
148 m_info.graphState.m_DashArray.resize(dashArray.size());
149 for (size_t i = 0; i < dashArray.size(); ++i)
150 m_info.graphState.m_DashArray[i] = dashArray[i] * scale;
154 m_info.graphState.m_DashArray.clear();
158 m_info.graphState.m_LineWidth = lineWidth;
162 m_info.isActOnDash =
true;
166 m_info.strokeColor = color;
170 m_info.fillColor = color;
175 RenderDeviceStrokePath(path, matrix);
181 RenderDeviceFillPath(path, fill_type, matrix);
185 m_info.CTM.Concat(matrix);
193 FX_RECT r = m_renderDevice->GetClipBox();
198 m_renderDevice->SetClip_Rect(
199 FX_RECT(FXSYS_roundf(rect.left), FXSYS_roundf(rect.top),
200 FXSYS_roundf(rect.right()), FXSYS_roundf(rect.bottom())));
204 return m_renderDevice;
209 if (m_info.strokeColor.GetType() != CFGAS_GEColor::Solid)
214 m_renderDevice->DrawPath(path.GetPath(), &m, &m_info.graphState, 0x0,
215 m_info.strokeColor.GetArgb(),
216 CFX_FillRenderOptions());
220 const CFGAS_GEPath& path,
227 switch (m_info.fillColor.GetType()) {
228 case CFGAS_GEColor::Solid:
229 m_renderDevice->DrawPath(path.GetPath(), &m, &m_info.graphState,
230 m_info.fillColor.GetArgb(), 0x0, fill_options);
233 FillPathWithPattern(path, fill_options, m);
236 FillPathWithShading(path, fill_options, m);
244 const CFGAS_GEPath& path,
247 RetainPtr<
const CFX_DIBitmap> bitmap = m_renderDevice->GetBitmap();
248 int32_t width = bitmap->GetWidth();
249 int32_t height = bitmap->GetHeight();
250 auto bmp =
pdfium::MakeRetain<CFX_DIBitmap>();
254 m_renderDevice->GetDIBits(bmp, 0, 0);
257 m_info.fillColor.GetPattern()->GetHatchStyle();
258 const FX_HATCHDATA& data =
259 GetHatchBitmapData(
static_cast<size_t>(hatchStyle));
261 auto mask =
pdfium::MakeRetain<CFX_DIBitmap>();
264 pdfium::make_span(data.maskBits).first(mask->GetPitch() * data.height),
265 mask->GetWritableBuffer());
270 CFX_DefaultRenderDevice device;
272 device.FillRect(rect, m_info.fillColor.GetPattern()->GetBackArgb());
273 for (int32_t j = rect
.bottom; j < rect
.top; j += mask->GetHeight()) {
274 for (int32_t i = rect
.left; i < rect
.right; i += mask->GetWidth()) {
275 device.SetBitMask(mask, i, j,
276 m_info.fillColor.GetPattern()->GetForeArgb());
280 m_renderDevice->SetClip_PathFill(path.GetPath(), &matrix, fill_options);
285 const CFGAS_GEPath& path,
288 RetainPtr<
const CFX_DIBitmap> bitmap = m_renderDevice->GetBitmap();
289 int32_t width = bitmap->GetWidth();
290 int32_t height = bitmap->GetHeight();
291 float start_x = m_info.fillColor.GetShading()->GetBeginPoint().x;
292 float start_y = m_info.fillColor.GetShading()->GetBeginPoint().y;
293 float end_x = m_info.fillColor.GetShading()->GetEndPoint().x;
294 float end_y = m_info.fillColor.GetShading()->GetEndPoint().y;
295 auto bmp =
pdfium::MakeRetain<CFX_DIBitmap>();
299 m_renderDevice->GetDIBits(bmp, 0, 0);
301 switch (m_info.fillColor.GetShading()->GetType()) {
302 case CFGAS_GEShading::Type::kAxial: {
303 float x_span = end_x - start_x;
304 float y_span = end_y - start_y;
305 float axis_len_square = (x_span * x_span) + (y_span * y_span);
306 for (int32_t row = 0; row < height; row++) {
307 auto dib_buf = bmp->GetWritableScanlineAs<uint32_t>(row);
308 for (int32_t column = 0; column < width; column++) {
310 if (axis_len_square) {
311 float y =
static_cast<
float>(row);
312 float x =
static_cast<
float>(column);
313 scale = (((x - start_x) * x_span) + ((y - start_y) * y_span)) /
315 if (isnan(scale) || scale < 0.0f) {
316 if (!m_info.fillColor.GetShading()->IsExtendedBegin())
319 }
else if (scale > 1.0f) {
320 if (!m_info.fillColor.GetShading()->IsExtendedEnd())
325 dib_buf[column] = m_info.fillColor.GetShading()->GetArgb(scale);
331 case CFGAS_GEShading::Type::kRadial: {
332 float start_r = m_info.fillColor.GetShading()->GetBeginRadius();
333 float end_r = m_info.fillColor.GetShading()->GetEndRadius();
334 float a = ((start_x - end_x) * (start_x - end_x)) +
335 ((start_y - end_y) * (start_y - end_y)) -
336 ((start_r - end_r) * (start_r - end_r));
337 for (int32_t row = 0; row < height; row++) {
338 auto dib_buf = bmp->GetWritableScanlineAs<uint32_t>(row);
339 for (int32_t column = 0; column < width; column++) {
340 float x = (
float)(column);
341 float y = (
float)(row);
342 float b = -2 * (((x - start_x) * (end_x - start_x)) +
343 ((y - start_y) * (end_y - start_y)) +
344 (start_r * (end_r - start_r)));
345 float c = ((x - start_x) * (x - start_x)) +
346 ((y - start_y) * (y - start_y)) - (start_r * start_r);
351 float b2_4ac = (b * b) - 4 * (a * c);
355 float root = (sqrt(b2_4ac));
359 s1 = (-b - root) / (2 * a);
360 s2 = (-b + root) / (2 * a);
362 s2 = (-b - root) / (2 * a);
363 s1 = (-b + root) / (2 * a);
365 if (s2 <= 1.0f || m_info.fillColor.GetShading()->IsExtendedEnd()) {
370 if ((start_r) + s * (end_r - start_r) < 0) {
374 if (isnan(s) || s < 0.0f) {
375 if (!m_info.fillColor.GetShading()->IsExtendedBegin())
380 if (!m_info.fillColor.GetShading()->IsExtendedEnd())
384 dib_buf[column] = m_info.fillColor.GetShading()->GetArgb(s);
393 m_renderDevice->SetClip_PathFill(path.GetPath(), &matrix, fill_options);
394 SetDIBitsWithMatrix(
std::move(bmp), matrix);
401 m_renderDevice->SetDIBits(source, 0, 0);
403 CFX_Matrix m
((
float)source->GetWidth()
, 0
, 0
, (
float)source->GetHeight()
, 0
,
408 RetainPtr<CFX_DIBitmap> bmp1 = source->FlipImage(
false,
true);
409 RetainPtr<CFX_DIBitmap> bmp2 = bmp1->TransformTo(m, &left, &top);
410 m_renderDevice->SetDIBits(bmp2, left, top);
419 const TInfo& other) =
default;
423 graphics_->SaveGraphState();
427 graphics_->RestoreGraphState();
StateRestorer(CFGAS_GEGraphics *graphics)
void FillPath(const CFGAS_GEPath &path, CFX_FillRenderOptions::FillType fill_type, const CFX_Matrix &matrix)
void SetLineDash(float dashPhase, pdfium::span< const float > dashArray)
void SetLineWidth(float lineWidth)
CFX_RenderDevice * GetRenderDevice()
CFGAS_GEGraphics(CFX_RenderDevice *renderDevice)
void SetClipRect(const CFX_RectF &rect)
void SetStrokeColor(const CFGAS_GEColor &color)
void ConcatMatrix(const CFX_Matrix &matrix)
const CFX_Matrix * GetMatrix() const
CFX_RectF GetClipRect() const
void SetLineCap(CFX_GraphStateData::LineCap lineCap)
void SetFillColor(const CFGAS_GEColor &color)
void StrokePath(const CFGAS_GEPath &path, const CFX_Matrix &matrix)
const CFX_Path & GetPath() const
bool Attach(RetainPtr< CFX_DIBitmap > pBitmap)
FX_RECT ToRoundedFxRect() const
constexpr CFX_Matrix()=default
CFX_FloatRect TransformRect(const CFX_FloatRect &rect) const
constexpr CFX_Matrix(float a1, float b1, float c1, float d1, float e1, float f1)
void Concat(const CFX_Matrix &right)
CFX_FloatRect GetBoundingBox() const
constexpr CFX_RectF(float dst_left, float dst_top, float dst_width, float dst_height)
constexpr CFX_FillRenderOptions(FillType fill_type)