7#include "xfa/fgas/graphics/cfgas_gegraphics.h"
15#include "core/fxcrt/fx_system.h"
16#include "core/fxcrt/span_util.h"
17#include "core/fxge/cfx_defaultrenderdevice.h"
18#include "core/fxge/cfx_renderdevice.h"
19#include "core/fxge/cfx_unicodeencoding.h"
20#include "core/fxge/dib/cfx_dibitmap.h"
21#include "third_party/base/check.h"
22#include "xfa/fgas/graphics/cfgas_gecolor.h"
23#include "xfa/fgas/graphics/cfgas_gepath.h"
24#include "xfa/fgas/graphics/cfgas_gepattern.h"
25#include "xfa/fgas/graphics/cfgas_geshading.h"
35const FX_HATCHDATA kHatchBitmapData[] = {
39 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
40 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
41 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
42 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
43 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
44 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00,
50 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80,
51 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80,
52 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
53 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00,
54 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
59 0x80, 0x80, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x20, 0x20, 0x00,
60 0x00, 0x10, 0x10, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x04, 0x04,
61 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x80,
62 0x80, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00,
63 0x10, 0x10, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x04, 0x04, 0x00,
64 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,
69 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x04, 0x04, 0x00,
70 0x00, 0x08, 0x08, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x20, 0x20,
71 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x01,
72 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00,
73 0x08, 0x08, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x20, 0x20, 0x00,
74 0x00, 0x40, 0x40, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
79 0xff, 0xff, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00,
80 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80,
81 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0xff,
82 0xff, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
83 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00,
84 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
89 0x81, 0x81, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x24, 0x24, 0x00,
90 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x24, 0x24,
91 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x81, 0x81, 0x00, 0x00, 0x81,
92 0x81, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00,
93 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x24, 0x24, 0x00,
94 0x00, 0x42, 0x42, 0x00, 0x00, 0x81, 0x81, 0x00, 0x00,
98const FX_HATCHDATA kHatchPlaceHolder = {
102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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,
110const FX_HATCHDATA& GetHatchBitmapData(size_t index) {
111 return index <
std::size(kHatchBitmapData) ? kHatchBitmapData[index]
119 DCHECK(m_renderDevice);
125 m_renderDevice->SaveState();
126 m_infoStack.push_back(std::make_unique<TInfo>(m_info));
130 m_renderDevice->RestoreState(
false);
131 CHECK(!m_infoStack.empty());
132 m_info = *m_infoStack.back();
133 m_infoStack.pop_back();
138 m_info.graphState.m_LineCap = lineCap;
142 pdfium::span<
const float> dashArray) {
143 DCHECK(!dashArray.empty());
144 float scale = m_info.isActOnDash ? m_info.graphState.m_LineWidth : 1.0;
145 m_info.graphState.m_DashPhase = dashPhase;
146 m_info.graphState.m_DashArray.resize(dashArray.size());
147 for (size_t i = 0; i < dashArray.size(); ++i)
148 m_info.graphState.m_DashArray[i] = dashArray[i] * scale;
152 m_info.graphState.m_DashArray.clear();
156 m_info.graphState.m_LineWidth = lineWidth;
160 m_info.isActOnDash =
true;
164 m_info.strokeColor = color;
168 m_info.fillColor = color;
173 RenderDeviceStrokePath(path, matrix);
179 RenderDeviceFillPath(path, fill_type, matrix);
183 m_info.CTM.Concat(matrix);
191 FX_RECT r = m_renderDevice->GetClipBox();
196 m_renderDevice->SetClip_Rect(
197 FX_RECT(FXSYS_roundf(rect.left), FXSYS_roundf(rect.top),
198 FXSYS_roundf(rect.right()), FXSYS_roundf(rect.bottom())));
202 return m_renderDevice;
207 if (m_info.strokeColor.GetType() != CFGAS_GEColor::Solid)
212 m_renderDevice->DrawPath(path.GetPath(), &m, &m_info.graphState, 0x0,
213 m_info.strokeColor.GetArgb(),
214 CFX_FillRenderOptions());
218 const CFGAS_GEPath& path,
225 switch (m_info.fillColor.GetType()) {
226 case CFGAS_GEColor::Solid:
227 m_renderDevice->DrawPath(path.GetPath(), &m, &m_info.graphState,
228 m_info.fillColor.GetArgb(), 0x0, fill_options);
231 FillPathWithPattern(path, fill_options, m);
234 FillPathWithShading(path, fill_options, m);
242 const CFGAS_GEPath& path,
245 RetainPtr<
const CFX_DIBitmap> bitmap = m_renderDevice->GetBitmap();
246 int32_t width = bitmap->GetWidth();
247 int32_t height = bitmap->GetHeight();
248 auto bmp = pdfium::MakeRetain<CFX_DIBitmap>();
250 m_renderDevice->GetDIBits(bmp, 0, 0);
253 m_info.fillColor.GetPattern()->GetHatchStyle();
254 const FX_HATCHDATA& data =
255 GetHatchBitmapData(
static_cast<size_t>(hatchStyle));
257 auto mask = pdfium::MakeRetain<CFX_DIBitmap>();
260 mask->GetWritableBuffer(),
261 pdfium::make_span(data.maskBits).first(mask->GetPitch() * data.height));
266 CFX_DefaultRenderDevice device;
268 device.FillRect(rect, m_info.fillColor.GetPattern()->GetBackArgb());
269 for (int32_t j = rect
.bottom; j < rect
.top; j += mask->GetHeight()) {
270 for (int32_t i = rect
.left; i < rect
.right; i += mask->GetWidth()) {
271 device.SetBitMask(mask, i, j,
272 m_info.fillColor.GetPattern()->GetForeArgb());
276 m_renderDevice->SetClip_PathFill(path.GetPath(), &matrix, fill_options);
281 const CFGAS_GEPath& path,
284 RetainPtr<
const CFX_DIBitmap> bitmap = m_renderDevice->GetBitmap();
285 int32_t width = bitmap->GetWidth();
286 int32_t height = bitmap->GetHeight();
287 float start_x = m_info.fillColor.GetShading()->GetBeginPoint().x;
288 float start_y = m_info.fillColor.GetShading()->GetBeginPoint().y;
289 float end_x = m_info.fillColor.GetShading()->GetEndPoint().x;
290 float end_y = m_info.fillColor.GetShading()->GetEndPoint().y;
291 auto bmp = pdfium::MakeRetain<CFX_DIBitmap>();
293 m_renderDevice->GetDIBits(bmp, 0, 0);
295 switch (m_info.fillColor.GetShading()->GetType()) {
296 case CFGAS_GEShading::Type::kAxial: {
297 float x_span = end_x - start_x;
298 float y_span = end_y - start_y;
299 float axis_len_square = (x_span * x_span) + (y_span * y_span);
300 for (int32_t row = 0; row < height; row++) {
302 fxcrt::reinterpret_span<uint32_t>(bmp->GetWritableScanline(row))
304 for (int32_t column = 0; column < width; column++) {
306 if (axis_len_square) {
307 float y =
static_cast<
float>(row);
308 float x =
static_cast<
float>(column);
309 scale = (((x - start_x) * x_span) + ((y - start_y) * y_span)) /
311 if (isnan(scale) || scale < 0.0f) {
312 if (!m_info.fillColor.GetShading()->IsExtendedBegin())
315 }
else if (scale > 1.0f) {
316 if (!m_info.fillColor.GetShading()->IsExtendedEnd())
322 static_cast<int32_t>(scale * (CFGAS_GEShading::kSteps - 1));
323 dib_buf[column] = m_info.fillColor.GetShading()->GetArgb(index);
329 case CFGAS_GEShading::Type::kRadial: {
330 float start_r = m_info.fillColor.GetShading()->GetBeginRadius();
331 float end_r = m_info.fillColor.GetShading()->GetEndRadius();
332 float a = ((start_x - end_x) * (start_x - end_x)) +
333 ((start_y - end_y) * (start_y - end_y)) -
334 ((start_r - end_r) * (start_r - end_r));
335 for (int32_t row = 0; row < height; row++) {
337 fxcrt::reinterpret_span<uint32_t>(bmp->GetWritableScanline(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 int index =
static_cast<int32_t>(s * (CFGAS_GEShading::kSteps - 1));
385 dib_buf[column] = m_info.fillColor.GetShading()->GetArgb(index);
394 m_renderDevice->SetClip_PathFill(path.GetPath(), &matrix, fill_options);
395 SetDIBitsWithMatrix(
std::move(bmp), matrix);
402 m_renderDevice->SetDIBits(source, 0, 0);
404 CFX_Matrix m
((
float)source->GetWidth()
, 0
, 0
, (
float)source->GetHeight()
, 0
,
409 RetainPtr<CFX_DIBitmap> bmp1 = source->FlipImage(
false,
true);
410 RetainPtr<CFX_DIBitmap> bmp2 = bmp1->TransformTo(m, &left, &top);
411 m_renderDevice->SetDIBits(bmp2, left, top);
420 const TInfo& other) =
default;
424 graphics_->SaveGraphState();
428 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
CFX_FloatRect TransformRect(const CFX_FloatRect &rect) const
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)