cfx_graphics.cpp revision 4d3acf4ec42bf6e838f9060103aff98fbf170794
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 "xfa/fxgraphics/cfx_graphics.h"
8
9#include <memory>
10
11#include "core/fxge/cfx_fxgedevice.h"
12#include "core/fxge/cfx_gemodule.h"
13#include "core/fxge/cfx_renderdevice.h"
14#include "core/fxge/cfx_unicodeencoding.h"
15#include "third_party/base/ptr_util.h"
16#include "xfa/fxgraphics/cagg_graphics.h"
17#include "xfa/fxgraphics/cfx_color.h"
18#include "xfa/fxgraphics/cfx_path.h"
19#include "xfa/fxgraphics/cfx_path_generator.h"
20#include "xfa/fxgraphics/cfx_pattern.h"
21#include "xfa/fxgraphics/cfx_shading.h"
22
23namespace {
24
25enum {
26  FX_CONTEXT_None = 0,
27  FX_CONTEXT_Device,
28};
29
30#define FX_HATCHSTYLE_Total 53
31
32struct FX_HATCHDATA {
33  int32_t width;
34  int32_t height;
35  uint8_t maskBits[64];
36};
37
38const FX_HATCHDATA hatchBitmapData[FX_HATCHSTYLE_Total] = {
39    {16,
40     16,
41     {
42         0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
43         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
44         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
45         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
46         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
47         0x00, 0x00, 0x00, 0x00,
48     }},
49    {16,
50     16,
51     {
52         0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
53         0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
54         0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
55         0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
56         0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
57         0x80, 0x80, 0x00, 0x00,
58     }},
59    {16,
60     16,
61     {
62         0x80, 0x80, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00,
63         0x10, 0x10, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00,
64         0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
65         0x40, 0x40, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,
66         0x08, 0x08, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,
67         0x01, 0x01, 0x00, 0x00,
68     }},
69    {16,
70     16,
71     {
72         0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00,
73         0x08, 0x08, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00,
74         0x40, 0x40, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,
75         0x02, 0x02, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00,
76         0x10, 0x10, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00,
77         0x80, 0x80, 0x00, 0x00,
78     }},
79    {16,
80     16,
81     {
82         0xff, 0xff, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
83         0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
84         0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
85         0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
86         0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
87         0x80, 0x80, 0x00, 0x00,
88     }},
89    {16,
90     16,
91     {
92         0x81, 0x81, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00,
93         0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00,
94         0x42, 0x42, 0x00, 0x00, 0x81, 0x81, 0x00, 0x00, 0x81, 0x81, 0x00, 0x00,
95         0x42, 0x42, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
96         0x18, 0x18, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00,
97         0x81, 0x81, 0x00, 0x00,
98     }},
99    {16,
100     16,
101     {
102         0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
103         0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
104         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
105         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
106         0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
107         0x00, 0x00, 0x00, 0x00,
108     }},
109    {16,
110     16,
111     {
112         0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00,
113         0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
114         0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
115         0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116         0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00,
117         0x00, 0x00, 0x00, 0x00,
118     }},
119    {16,
120     16,
121     {
122         0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00,
123         0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
124         0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00,
125         0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
126         0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00,
127         0x00, 0x00, 0x00, 0x00,
128     }},
129    {16,
130     16,
131     {
132         0x88, 0x88, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00,
133         0x22, 0x22, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00,
134         0x88, 0x88, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00,
135         0x22, 0x22, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00,
136         0x88, 0x88, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00,
137         0x22, 0x22, 0x00, 0x00,
138     }},
139    {16,
140     16,
141     {
142         0xaa, 0xaa, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00,
143         0x11, 0x11, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
144         0xaa, 0xaa, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00,
145         0x44, 0x44, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00,
146         0xaa, 0xaa, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00,
147         0x11, 0x11, 0x00, 0x00,
148     }},
149    {16,
150     16,
151     {
152         0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00,
153         0x51, 0x51, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00,
154         0xaa, 0xaa, 0x00, 0x00, 0x15, 0x15, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00,
155         0x55, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x51, 0x51, 0x00, 0x00,
156         0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00,
157         0x15, 0x15, 0x00, 0x00,
158     }},
159    {16,
160     16,
161     {
162         0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00,
163         0x55, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00,
164         0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00,
165         0x55, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00,
166         0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00,
167         0x55, 0x55, 0x00, 0x00,
168     }},
169    {16,
170     16,
171     {
172         0xee, 0xee, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xbb, 0xbb, 0x00, 0x00,
173         0x55, 0x55, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00,
174         0xbb, 0xbb, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00,
175         0x55, 0x55, 0x00, 0x00, 0xbb, 0xbb, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00,
176         0xee, 0xee, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xbb, 0xbb, 0x00, 0x00,
177         0x55, 0x55, 0x00, 0x00,
178     }},
179    {16,
180     16,
181     {
182         0x77, 0x77, 0x00, 0x00, 0xdd, 0xdd, 0x00, 0x00, 0x77, 0x77, 0x00, 0x00,
183         0xdd, 0xdd, 0x00, 0x00, 0x77, 0x77, 0x00, 0x00, 0xdd, 0xdd, 0x00, 0x00,
184         0x77, 0x77, 0x00, 0x00, 0xdd, 0xdd, 0x00, 0x00, 0x77, 0x77, 0x00, 0x00,
185         0xdd, 0xdd, 0x00, 0x00, 0x77, 0x77, 0x00, 0x00, 0xdd, 0xdd, 0x00, 0x00,
186         0x77, 0x77, 0x00, 0x00, 0xdd, 0xdd, 0x00, 0x00, 0x77, 0x77, 0x00, 0x00,
187         0xdd, 0xdd, 0x00, 0x00,
188     }},
189    {16,
190     16,
191     {
192         0x77, 0x77, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xdd, 0xdd, 0x00, 0x00,
193         0xff, 0xff, 0x00, 0x00, 0x77, 0x77, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
194         0xdd, 0xdd, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x77, 0x77, 0x00, 0x00,
195         0xff, 0xff, 0x00, 0x00, 0xdd, 0xdd, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
196         0x77, 0x77, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xdd, 0xdd, 0x00, 0x00,
197         0xff, 0xff, 0x00, 0x00,
198     }},
199    {16,
200     16,
201     {
202         0xef, 0xef, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00,
203         0xff, 0xff, 0x00, 0x00, 0xef, 0xef, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
204         0xfe, 0xfe, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xef, 0xef, 0x00, 0x00,
205         0xff, 0xff, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
206         0xef, 0xef, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00,
207         0xff, 0xff, 0x00, 0x00,
208     }},
209    {16,
210     16,
211     {
212         0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
213         0xf7, 0xf7, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
214         0xff, 0xff, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
215         0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xf7, 0xf7, 0x00, 0x00,
216         0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
217         0x7f, 0x7f, 0x00, 0x00,
218     }},
219    {16,
220     16,
221     {
222         0x88, 0x88, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00,
223         0x11, 0x11, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
224         0x22, 0x22, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00,
225         0x44, 0x44, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00,
226         0x88, 0x88, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00,
227         0x11, 0x11, 0x00, 0x00,
228     }},
229    {16,
230     16,
231     {
232         0x11, 0x11, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
233         0x88, 0x88, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00,
234         0x44, 0x44, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00,
235         0x22, 0x22, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00,
236         0x11, 0x11, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
237         0x88, 0x88, 0x00, 0x00,
238     }},
239    {16,
240     16,
241     {
242         0xcc, 0xcc, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x33, 0x33, 0x00, 0x00,
243         0x99, 0x99, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00,
244         0x33, 0x33, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00,
245         0x66, 0x66, 0x00, 0x00, 0x33, 0x33, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00,
246         0xcc, 0xcc, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x33, 0x33, 0x00, 0x00,
247         0x99, 0x99, 0x00, 0x00,
248     }},
249    {16,
250     16,
251     {
252         0x33, 0x33, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00,
253         0x99, 0x99, 0x00, 0x00, 0x33, 0x33, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00,
254         0xcc, 0xcc, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00, 0x33, 0x33, 0x00, 0x00,
255         0x66, 0x66, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00,
256         0x33, 0x33, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00,
257         0x99, 0x99, 0x00, 0x00,
258     }},
259    {16,
260     16,
261     {
262         0xc1, 0xc1, 0x00, 0x00, 0xe0, 0xe0, 0x00, 0x00, 0x70, 0x70, 0x00, 0x00,
263         0x38, 0x38, 0x00, 0x00, 0x1c, 0x1c, 0x00, 0x00, 0x0e, 0x0e, 0x00, 0x00,
264         0x07, 0x07, 0x00, 0x00, 0x83, 0x83, 0x00, 0x00, 0xc1, 0xc1, 0x00, 0x00,
265         0xe0, 0xe0, 0x00, 0x00, 0x70, 0x70, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00,
266         0x1c, 0x1c, 0x00, 0x00, 0x0e, 0x0e, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00,
267         0x83, 0x83, 0x00, 0x00,
268     }},
269    {16,
270     16,
271     {
272         0x83, 0x83, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, 0x0e, 0x0e, 0x00, 0x00,
273         0x1c, 0x1c, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x70, 0x70, 0x00, 0x00,
274         0xe0, 0xe0, 0x00, 0x00, 0xc1, 0xc1, 0x00, 0x00, 0x83, 0x83, 0x00, 0x00,
275         0x07, 0x07, 0x00, 0x00, 0x0e, 0x0e, 0x00, 0x00, 0x1c, 0x1c, 0x00, 0x00,
276         0x38, 0x38, 0x00, 0x00, 0x70, 0x70, 0x00, 0x00, 0xe0, 0xe0, 0x00, 0x00,
277         0xc1, 0xc1, 0x00, 0x00,
278     }},
279    {16,
280     16,
281     {
282         0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00,
283         0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00,
284         0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00,
285         0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00,
286         0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00,
287         0x88, 0x88, 0x00, 0x00,
288     }},
289    {16,
290     16,
291     {
292         0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
293         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
294         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
295         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
296         0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
297         0x00, 0x00, 0x00, 0x00,
298     }},
299    {16,
300     16,
301     {
302         0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00,
303         0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00,
304         0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00,
305         0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00,
306         0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00,
307         0x55, 0x55, 0x00, 0x00,
308     }},
309    {16,
310     16,
311     {
312         0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
313         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
314         0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
315         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
316         0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
317         0x00, 0x00, 0x00, 0x00,
318     }},
319    {16,
320     16,
321     {
322         0xcc, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00,
323         0xcc, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00,
324         0xcc, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00,
325         0xcc, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00,
326         0xcc, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00,
327         0xcc, 0xcc, 0x00, 0x00,
328     }},
329    {16,
330     16,
331     {
332         0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
333         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
334         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
335         0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
336         0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
337         0x00, 0x00, 0x00, 0x00,
338     }},
339    {16,
340     16,
341     {
342         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00,
343         0x44, 0x44, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00,
344         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
345         0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
346         0x22, 0x22, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
347         0x00, 0x00, 0x00, 0x00,
348     }},
349    {16,
350     16,
351     {
352         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00,
353         0x22, 0x22, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00,
354         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
355         0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00,
356         0x44, 0x44, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
357         0x00, 0x00, 0x00, 0x00,
358     }},
359    {16,
360     16,
361     {
362         0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
363         0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
364         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00,
365         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
366         0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
367         0x00, 0x00, 0x00, 0x00,
368     }},
369    {16,
370     16,
371     {
372         0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
373         0x80, 0x80, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00,
374         0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
375         0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
376         0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00,
377         0x08, 0x08, 0x00, 0x00,
378     }},
379    {16,
380     16,
381     {
382         0x80, 0x80, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00,
383         0x02, 0x02, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,
384         0x20, 0x20, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
385         0x08, 0x08, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,
386         0x10, 0x10, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00,
387         0x04, 0x04, 0x00, 0x00,
388     }},
389    {16,
390     16,
391     {
392         0xb1, 0xb1, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00,
393         0x1b, 0x1b, 0x00, 0x00, 0xd8, 0xd8, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00,
394         0x0c, 0x0c, 0x00, 0x00, 0x8d, 0x8d, 0x00, 0x00, 0xb1, 0xb1, 0x00, 0x00,
395         0x30, 0x30, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x1b, 0x1b, 0x00, 0x00,
396         0xd8, 0xd8, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00,
397         0x8d, 0x8d, 0x00, 0x00,
398     }},
399    {16,
400     16,
401     {
402         0x81, 0x81, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00,
403         0x18, 0x18, 0x00, 0x00, 0x81, 0x81, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00,
404         0x24, 0x24, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x81, 0x81, 0x00, 0x00,
405         0x42, 0x42, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
406         0x81, 0x81, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00,
407         0x18, 0x18, 0x00, 0x00,
408     }},
409    {16,
410     16,
411     {
412         0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x25, 0x25, 0x00, 0x00,
413         0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
414         0x25, 0x25, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
415         0x18, 0x18, 0x00, 0x00, 0x25, 0x25, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00,
416         0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x25, 0x25, 0x00, 0x00,
417         0xc0, 0xc0, 0x00, 0x00,
418     }},
419    {16,
420     16,
421     {
422         0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00,
423         0x08, 0x08, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00,
424         0x42, 0x42, 0x00, 0x00, 0x81, 0x81, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,
425         0x02, 0x02, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00,
426         0x18, 0x18, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00,
427         0x81, 0x81, 0x00, 0x00,
428     }},
429    {16,
430     16,
431     {
432         0xff, 0xff, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
433         0x80, 0x80, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00,
434         0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
435         0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
436         0xff, 0xff, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00,
437         0x08, 0x08, 0x00, 0x00,
438     }},
439    {16,
440     16,
441     {
442         0x88, 0x88, 0x00, 0x00, 0x54, 0x54, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00,
443         0x45, 0x45, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x14, 0x14, 0x00, 0x00,
444         0x22, 0x22, 0x00, 0x00, 0x51, 0x51, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00,
445         0x54, 0x54, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x45, 0x45, 0x00, 0x00,
446         0x88, 0x88, 0x00, 0x00, 0x14, 0x14, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00,
447         0x51, 0x51, 0x00, 0x00,
448     }},
449    {16,
450     16,
451     {
452         0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00,
453         0x55, 0x55, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00,
454         0xf0, 0xf0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00,
455         0x55, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00,
456         0xf0, 0xf0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00,
457         0xf0, 0xf0, 0x00, 0x00,
458     }},
459    {16,
460     16,
461     {
462         0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00,
463         0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
464         0x01, 0x01, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
465         0x10, 0x10, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,
466         0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,
467         0x80, 0x80, 0x00, 0x00,
468     }},
469    {16,
470     16,
471     {
472         0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
473         0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
474         0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00,
475         0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
476         0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
477         0x00, 0x00, 0x00, 0x00,
478     }},
479    {16,
480     16,
481     {
482         0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00,
483         0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
484         0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
485         0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
486         0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00,
487         0x00, 0x00, 0x00, 0x00,
488     }},
489    {16,
490     16,
491     {
492         0x03, 0x03, 0x00, 0x00, 0x84, 0x84, 0x00, 0x00, 0x48, 0x48, 0x00, 0x00,
493         0x30, 0x30, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,
494         0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00,
495         0x84, 0x84, 0x00, 0x00, 0x48, 0x48, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00,
496         0x0c, 0x0c, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,
497         0x01, 0x01, 0x00, 0x00,
498     }},
499    {16,
500     16,
501     {
502         0xff, 0xff, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
503         0x99, 0x99, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00,
504         0xff, 0xff, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
505         0x66, 0x66, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00,
506         0xff, 0xff, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
507         0x99, 0x99, 0x00, 0x00,
508     }},
509    {16,
510     16,
511     {
512         0x77, 0x77, 0x00, 0x00, 0x89, 0x89, 0x00, 0x00, 0x8f, 0x8f, 0x00, 0x00,
513         0x8f, 0x8f, 0x00, 0x00, 0x77, 0x77, 0x00, 0x00, 0x98, 0x98, 0x00, 0x00,
514         0xf8, 0xf8, 0x00, 0x00, 0xf8, 0xf8, 0x00, 0x00, 0x77, 0x77, 0x00, 0x00,
515         0x89, 0x89, 0x00, 0x00, 0x8f, 0x8f, 0x00, 0x00, 0x8f, 0x8f, 0x00, 0x00,
516         0x77, 0x77, 0x00, 0x00, 0x98, 0x98, 0x00, 0x00, 0xf8, 0xf8, 0x00, 0x00,
517         0xf8, 0xf8, 0x00, 0x00,
518     }},
519    {16,
520     16,
521     {
522         0xff, 0xff, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00,
523         0x88, 0x88, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00,
524         0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
525         0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00,
526         0xff, 0xff, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00,
527         0x88, 0x88, 0x00, 0x00,
528     }},
529    {16,
530     16,
531     {
532         0x99, 0x99, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00,
533         0x99, 0x99, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00,
534         0x66, 0x66, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00,
535         0x66, 0x66, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00,
536         0x99, 0x99, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00,
537         0x99, 0x99, 0x00, 0x00,
538     }},
539    {16,
540     16,
541     {
542         0xf0, 0xf0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00,
543         0xf0, 0xf0, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00,
544         0x0f, 0x0f, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00,
545         0xf0, 0xf0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00,
546         0x0f, 0x0f, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00,
547         0x0f, 0x0f, 0x00, 0x00,
548     }},
549    {16,
550     16,
551     {
552         0x82, 0x82, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x28, 0x28, 0x00, 0x00,
553         0x10, 0x10, 0x00, 0x00, 0x28, 0x28, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
554         0x82, 0x82, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x82, 0x82, 0x00, 0x00,
555         0x44, 0x44, 0x00, 0x00, 0x28, 0x28, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,
556         0x28, 0x28, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x82, 0x82, 0x00, 0x00,
557         0x01, 0x01, 0x00, 0x00,
558     }},
559    {16,
560     16,
561     {
562         0x10, 0x10, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x7c, 0x7c, 0x00, 0x00,
563         0xfe, 0xfe, 0x00, 0x00, 0x7c, 0x7c, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00,
564         0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,
565         0x38, 0x38, 0x00, 0x00, 0x7c, 0x7c, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00,
566         0x7c, 0x7c, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,
567         0x00, 0x00, 0x00, 0x00,
568     }},
569};
570
571}  // namespace
572
573CFX_Graphics::CFX_Graphics()
574    : m_type(FX_CONTEXT_None), m_renderDevice(nullptr) {}
575
576FWL_Error CFX_Graphics::Create(CFX_RenderDevice* renderDevice,
577                               bool isAntialiasing) {
578  if (!renderDevice)
579    return FWL_Error::ParameterInvalid;
580  if (m_type != FX_CONTEXT_None)
581    return FWL_Error::PropertyInvalid;
582
583  m_type = FX_CONTEXT_Device;
584  m_info.isAntialiasing = isAntialiasing;
585  m_renderDevice = renderDevice;
586  if (m_renderDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_SOFT_CLIP)
587    return FWL_Error::Succeeded;
588  return FWL_Error::Indefinite;
589}
590
591FWL_Error CFX_Graphics::Create(int32_t width,
592                               int32_t height,
593                               FXDIB_Format format,
594                               bool isNative,
595                               bool isAntialiasing) {
596  if (m_type != FX_CONTEXT_None)
597    return FWL_Error::PropertyInvalid;
598
599  m_type = FX_CONTEXT_Device;
600  m_info.isAntialiasing = isAntialiasing;
601  m_aggGraphics = pdfium::MakeUnique<CAGG_Graphics>();
602  return m_aggGraphics->Create(this, width, height, format);
603}
604
605CFX_Graphics::~CFX_Graphics() {}
606
607FWL_Error CFX_Graphics::GetDeviceCap(const int32_t capID,
608                                     FX_DeviceCap& capVal) {
609  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
610    capVal = m_renderDevice->GetDeviceCaps(capID);
611    return FWL_Error::Succeeded;
612  }
613  return FWL_Error::PropertyInvalid;
614}
615
616FWL_Error CFX_Graphics::IsPrinterDevice(bool& isPrinter) {
617  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
618    isPrinter = m_renderDevice->GetDeviceClass() == FXDC_PRINTER;
619    return FWL_Error::Succeeded;
620  }
621  return FWL_Error::PropertyInvalid;
622}
623
624FWL_Error CFX_Graphics::EnableAntialiasing(bool isAntialiasing) {
625  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
626    m_info.isAntialiasing = isAntialiasing;
627    return FWL_Error::Succeeded;
628  }
629  return FWL_Error::PropertyInvalid;
630}
631
632FWL_Error CFX_Graphics::SaveGraphState() {
633  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
634    m_renderDevice->SaveState();
635    m_infoStack.Add(new TInfo(m_info));
636    return FWL_Error::Succeeded;
637  }
638  return FWL_Error::PropertyInvalid;
639}
640
641FWL_Error CFX_Graphics::RestoreGraphState() {
642  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
643    m_renderDevice->RestoreState(false);
644    int32_t size = m_infoStack.GetSize();
645    if (size <= 0) {
646      return FWL_Error::IntermediateValueInvalid;
647    }
648    int32_t topIndex = size - 1;
649    std::unique_ptr<TInfo> info(m_infoStack.GetAt(topIndex));
650    if (!info)
651      return FWL_Error::IntermediateValueInvalid;
652    m_info = *info;
653    m_infoStack.RemoveAt(topIndex);
654    return FWL_Error::Succeeded;
655  }
656  return FWL_Error::PropertyInvalid;
657}
658
659FWL_Error CFX_Graphics::GetLineCap(CFX_GraphStateData::LineCap& lineCap) const {
660  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
661    lineCap = m_info.graphState.m_LineCap;
662    return FWL_Error::Succeeded;
663  }
664  return FWL_Error::PropertyInvalid;
665}
666
667FWL_Error CFX_Graphics::SetLineCap(CFX_GraphStateData::LineCap lineCap) {
668  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
669    m_info.graphState.m_LineCap = lineCap;
670    return FWL_Error::Succeeded;
671  }
672  return FWL_Error::PropertyInvalid;
673}
674
675FWL_Error CFX_Graphics::GetDashCount(int32_t& dashCount) const {
676  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
677    dashCount = m_info.graphState.m_DashCount;
678    return FWL_Error::Succeeded;
679  }
680  return FWL_Error::PropertyInvalid;
681}
682
683FWL_Error CFX_Graphics::GetLineDash(FX_FLOAT& dashPhase,
684                                    FX_FLOAT* dashArray) const {
685  if (!dashArray)
686    return FWL_Error::ParameterInvalid;
687  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
688    dashPhase = m_info.graphState.m_DashPhase;
689    FXSYS_memcpy(dashArray, m_info.graphState.m_DashArray,
690                 m_info.graphState.m_DashCount * sizeof(FX_FLOAT));
691    return FWL_Error::Succeeded;
692  }
693  return FWL_Error::PropertyInvalid;
694}
695
696FWL_Error CFX_Graphics::SetLineDash(FX_FLOAT dashPhase,
697                                    FX_FLOAT* dashArray,
698                                    int32_t dashCount) {
699  if (dashCount > 0 && !dashArray)
700    return FWL_Error::ParameterInvalid;
701
702  dashCount = dashCount < 0 ? 0 : dashCount;
703  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
704    FX_FLOAT scale = 1.0;
705    if (m_info.isActOnDash) {
706      scale = m_info.graphState.m_LineWidth;
707    }
708    m_info.graphState.m_DashPhase = dashPhase;
709    m_info.graphState.SetDashCount(dashCount);
710    for (int32_t i = 0; i < dashCount; i++) {
711      m_info.graphState.m_DashArray[i] = dashArray[i] * scale;
712    }
713    return FWL_Error::Succeeded;
714  }
715  return FWL_Error::PropertyInvalid;
716}
717
718FWL_Error CFX_Graphics::SetLineDash(FX_DashStyle dashStyle) {
719  if (m_type == FX_CONTEXT_Device && m_renderDevice)
720    return RenderDeviceSetLineDash(dashStyle);
721  return FWL_Error::PropertyInvalid;
722}
723
724FWL_Error CFX_Graphics::GetLineJoin(
725    CFX_GraphStateData::LineJoin& lineJoin) const {
726  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
727    lineJoin = m_info.graphState.m_LineJoin;
728    return FWL_Error::Succeeded;
729  }
730  return FWL_Error::PropertyInvalid;
731}
732
733FWL_Error CFX_Graphics::SetLineJoin(CFX_GraphStateData::LineJoin lineJoin) {
734  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
735    m_info.graphState.m_LineJoin = lineJoin;
736    return FWL_Error::Succeeded;
737  }
738  return FWL_Error::PropertyInvalid;
739}
740
741FWL_Error CFX_Graphics::GetMiterLimit(FX_FLOAT& miterLimit) const {
742  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
743    miterLimit = m_info.graphState.m_MiterLimit;
744    return FWL_Error::Succeeded;
745  }
746  return FWL_Error::PropertyInvalid;
747}
748
749FWL_Error CFX_Graphics::SetMiterLimit(FX_FLOAT miterLimit) {
750  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
751    m_info.graphState.m_MiterLimit = miterLimit;
752    return FWL_Error::Succeeded;
753  }
754  return FWL_Error::PropertyInvalid;
755}
756
757FWL_Error CFX_Graphics::GetLineWidth(FX_FLOAT& lineWidth) const {
758  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
759    lineWidth = m_info.graphState.m_LineWidth;
760    return FWL_Error::Succeeded;
761  }
762  return FWL_Error::PropertyInvalid;
763}
764
765FWL_Error CFX_Graphics::SetLineWidth(FX_FLOAT lineWidth, bool isActOnDash) {
766  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
767    m_info.graphState.m_LineWidth = lineWidth;
768    m_info.isActOnDash = isActOnDash;
769    return FWL_Error::Succeeded;
770  }
771  return FWL_Error::PropertyInvalid;
772}
773
774FWL_Error CFX_Graphics::GetStrokeAlignment(
775    FX_StrokeAlignment& strokeAlignment) const {
776  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
777    strokeAlignment = m_info.strokeAlignment;
778    return FWL_Error::Succeeded;
779  }
780  return FWL_Error::PropertyInvalid;
781}
782
783FWL_Error CFX_Graphics::SetStrokeAlignment(FX_StrokeAlignment strokeAlignment) {
784  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
785    m_info.strokeAlignment = strokeAlignment;
786    return FWL_Error::Succeeded;
787  }
788  return FWL_Error::PropertyInvalid;
789}
790
791FWL_Error CFX_Graphics::SetStrokeColor(CFX_Color* color) {
792  if (!color)
793    return FWL_Error::ParameterInvalid;
794  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
795    m_info.strokeColor = color;
796    return FWL_Error::Succeeded;
797  }
798  return FWL_Error::PropertyInvalid;
799}
800
801FWL_Error CFX_Graphics::SetFillColor(CFX_Color* color) {
802  if (!color)
803    return FWL_Error::ParameterInvalid;
804  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
805    m_info.fillColor = color;
806    return FWL_Error::Succeeded;
807  }
808  return FWL_Error::PropertyInvalid;
809}
810
811FWL_Error CFX_Graphics::StrokePath(CFX_Path* path, CFX_Matrix* matrix) {
812  if (!path)
813    return FWL_Error::ParameterInvalid;
814  if (m_type == FX_CONTEXT_Device && m_renderDevice)
815    return RenderDeviceStrokePath(path, matrix);
816  return FWL_Error::PropertyInvalid;
817}
818
819FWL_Error CFX_Graphics::FillPath(CFX_Path* path,
820                                 FX_FillMode fillMode,
821                                 CFX_Matrix* matrix) {
822  if (!path)
823    return FWL_Error::ParameterInvalid;
824  if (m_type == FX_CONTEXT_Device && m_renderDevice)
825    return RenderDeviceFillPath(path, fillMode, matrix);
826  return FWL_Error::PropertyInvalid;
827}
828
829FWL_Error CFX_Graphics::ClipPath(CFX_Path* path,
830                                 FX_FillMode fillMode,
831                                 CFX_Matrix* matrix) {
832  if (!path)
833    return FWL_Error::ParameterInvalid;
834  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
835    bool result =
836        m_renderDevice->SetClip_PathFill(path->GetPathData(), matrix, fillMode);
837    if (!result)
838      return FWL_Error::Indefinite;
839    return FWL_Error::Succeeded;
840  }
841  return FWL_Error::PropertyInvalid;
842}
843
844FWL_Error CFX_Graphics::DrawImage(CFX_DIBSource* source,
845                                  const CFX_PointF& point,
846                                  CFX_Matrix* matrix) {
847  if (!source)
848    return FWL_Error::ParameterInvalid;
849  if (m_type == FX_CONTEXT_Device && m_renderDevice)
850    return RenderDeviceDrawImage(source, point, matrix);
851  return FWL_Error::PropertyInvalid;
852}
853
854FWL_Error CFX_Graphics::StretchImage(CFX_DIBSource* source,
855                                     const CFX_RectF& rect,
856                                     CFX_Matrix* matrix) {
857  if (!source)
858    return FWL_Error::ParameterInvalid;
859  if (m_type == FX_CONTEXT_Device && m_renderDevice)
860    return RenderDeviceStretchImage(source, rect, matrix);
861  return FWL_Error::PropertyInvalid;
862}
863
864FWL_Error CFX_Graphics::ConcatMatrix(const CFX_Matrix* matrix) {
865  if (!matrix)
866    return FWL_Error::ParameterInvalid;
867  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
868    m_info.CTM.Concat(*matrix);
869    return FWL_Error::Succeeded;
870  }
871  return FWL_Error::PropertyInvalid;
872}
873
874CFX_Matrix* CFX_Graphics::GetMatrix() {
875  if (m_type == FX_CONTEXT_Device && m_renderDevice)
876    return &m_info.CTM;
877  return nullptr;
878}
879
880FWL_Error CFX_Graphics::GetClipRect(CFX_RectF& rect) const {
881  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
882    FX_RECT r = m_renderDevice->GetClipBox();
883    rect.left = (FX_FLOAT)r.left;
884    rect.top = (FX_FLOAT)r.top;
885    rect.width = (FX_FLOAT)r.Width();
886    rect.height = (FX_FLOAT)r.Height();
887    return FWL_Error::Succeeded;
888  }
889  return FWL_Error::PropertyInvalid;
890}
891
892FWL_Error CFX_Graphics::SetClipRect(const CFX_RectF& rect) {
893  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
894    if (!m_renderDevice->SetClip_Rect(
895            FX_RECT(FXSYS_round(rect.left), FXSYS_round(rect.top),
896                    FXSYS_round(rect.right()), FXSYS_round(rect.bottom())))) {
897      return FWL_Error::MethodNotSupported;
898    }
899    return FWL_Error::Succeeded;
900  }
901  return FWL_Error::PropertyInvalid;
902}
903
904FWL_Error CFX_Graphics::ClearClip() {
905  if (m_type == FX_CONTEXT_Device && m_renderDevice)
906    return FWL_Error::Succeeded;
907  return FWL_Error::PropertyInvalid;
908}
909
910FWL_Error CFX_Graphics::SetFont(CFX_Font* font) {
911  if (!font)
912    return FWL_Error::ParameterInvalid;
913  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
914    m_info.font = font;
915    return FWL_Error::Succeeded;
916  }
917  return FWL_Error::PropertyInvalid;
918}
919
920FWL_Error CFX_Graphics::SetFontSize(const FX_FLOAT size) {
921  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
922    m_info.fontSize = size <= 0 ? 1.0f : size;
923    return FWL_Error::Succeeded;
924  }
925  return FWL_Error::PropertyInvalid;
926}
927
928FWL_Error CFX_Graphics::SetFontHScale(const FX_FLOAT scale) {
929  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
930    m_info.fontHScale = scale <= 0 ? 1.0f : scale;
931    return FWL_Error::Succeeded;
932  }
933  return FWL_Error::PropertyInvalid;
934}
935
936FWL_Error CFX_Graphics::SetCharSpacing(const FX_FLOAT spacing) {
937  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
938    m_info.fontSpacing = spacing < 0 ? 0 : spacing;
939    return FWL_Error::Succeeded;
940  }
941  return FWL_Error::PropertyInvalid;
942}
943
944FWL_Error CFX_Graphics::SetTextDrawingMode(const int32_t mode) {
945  if (m_type == FX_CONTEXT_Device && m_renderDevice)
946    return FWL_Error::Succeeded;
947  return FWL_Error::PropertyInvalid;
948}
949
950FWL_Error CFX_Graphics::ShowText(const CFX_PointF& point,
951                                 const CFX_WideString& text,
952                                 CFX_Matrix* matrix) {
953  if (m_type == FX_CONTEXT_Device && m_renderDevice)
954    return RenderDeviceShowText(point, text, matrix);
955  return FWL_Error::PropertyInvalid;
956}
957
958void CFX_Graphics::CalcTextRect(CFX_RectF& rect,
959                                const CFX_WideString& text,
960                                bool isMultiline,
961                                CFX_Matrix* matrix) {
962  if (m_type != FX_CONTEXT_Device || !m_renderDevice)
963    return;
964
965  int32_t length = text.GetLength();
966  uint32_t* charCodes = FX_Alloc(uint32_t, length);
967  FXTEXT_CHARPOS* charPos = FX_Alloc(FXTEXT_CHARPOS, length);
968  CalcTextInfo(text, charCodes, charPos, rect);
969  FX_Free(charPos);
970  FX_Free(charCodes);
971}
972
973FWL_Error CFX_Graphics::Transfer(CFX_Graphics* graphics,
974                                 const CFX_Matrix* matrix) {
975  if (!graphics || !graphics->m_renderDevice)
976    return FWL_Error::ParameterInvalid;
977  CFX_Matrix m;
978  m.Set(m_info.CTM.a, m_info.CTM.b, m_info.CTM.c, m_info.CTM.d, m_info.CTM.e,
979        m_info.CTM.f);
980  if (matrix) {
981    m.Concat(*matrix);
982  }
983  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
984    CFX_DIBitmap* bitmap = graphics->m_renderDevice->GetBitmap();
985    bool result = m_renderDevice->SetDIBits(bitmap, 0, 0);
986    if (!result)
987      return FWL_Error::MethodNotSupported;
988    return FWL_Error::Succeeded;
989  }
990  return FWL_Error::PropertyInvalid;
991}
992
993FWL_Error CFX_Graphics::Transfer(CFX_Graphics* graphics,
994                                 FX_FLOAT srcLeft,
995                                 FX_FLOAT srcTop,
996                                 const CFX_RectF& dstRect,
997                                 const CFX_Matrix* matrix) {
998  if (!graphics || !graphics->m_renderDevice)
999    return FWL_Error::ParameterInvalid;
1000  CFX_Matrix m;
1001  m.Set(m_info.CTM.a, m_info.CTM.b, m_info.CTM.c, m_info.CTM.d, m_info.CTM.e,
1002        m_info.CTM.f);
1003  if (matrix) {
1004    m.Concat(*matrix);
1005  }
1006  if (m_type == FX_CONTEXT_Device && m_renderDevice) {
1007    CFX_DIBitmap bmp;
1008    bool result =
1009        bmp.Create((int32_t)dstRect.width, (int32_t)dstRect.height,
1010                   graphics->m_renderDevice->GetBitmap()->GetFormat());
1011    if (!result)
1012      return FWL_Error::IntermediateValueInvalid;
1013    result = graphics->m_renderDevice->GetDIBits(&bmp, (int32_t)srcLeft,
1014                                                 (int32_t)srcTop);
1015    if (!result)
1016      return FWL_Error::MethodNotSupported;
1017    result = m_renderDevice->SetDIBits(&bmp, (int32_t)dstRect.left,
1018                                       (int32_t)dstRect.top);
1019    if (!result)
1020      return FWL_Error::MethodNotSupported;
1021    return FWL_Error::Succeeded;
1022  }
1023  return FWL_Error::PropertyInvalid;
1024}
1025
1026CFX_RenderDevice* CFX_Graphics::GetRenderDevice() {
1027  return m_renderDevice;
1028}
1029
1030FWL_Error CFX_Graphics::InverseRect(const CFX_RectF& rect) {
1031  if (!m_renderDevice)
1032    return FWL_Error::PropertyInvalid;
1033  CFX_DIBitmap* bitmap = m_renderDevice->GetBitmap();
1034  if (!bitmap)
1035    return FWL_Error::PropertyInvalid;
1036  CFX_RectF temp(rect);
1037  m_info.CTM.TransformRect(temp);
1038  CFX_RectF r;
1039  r.Set(0, 0, (FX_FLOAT)bitmap->GetWidth(), (FX_FLOAT)bitmap->GetWidth());
1040  r.Intersect(temp);
1041  if (r.IsEmpty()) {
1042    return FWL_Error::ParameterInvalid;
1043  }
1044  FX_ARGB* pBuf =
1045      (FX_ARGB*)(bitmap->GetBuffer() + int32_t(r.top) * bitmap->GetPitch());
1046  int32_t bottom = (int32_t)r.bottom();
1047  int32_t right = (int32_t)r.right();
1048  for (int32_t i = (int32_t)r.top; i < bottom; i++) {
1049    FX_ARGB* pLine = pBuf + (int32_t)r.left;
1050    for (int32_t j = (int32_t)r.left; j < right; j++) {
1051      FX_ARGB c = *pLine;
1052      *pLine++ = (c & 0xFF000000) | (0xFFFFFF - (c & 0x00FFFFFF));
1053    }
1054    pBuf = (FX_ARGB*)((uint8_t*)pBuf + bitmap->GetPitch());
1055  }
1056  return FWL_Error::Succeeded;
1057}
1058
1059FWL_Error CFX_Graphics::XorDIBitmap(const CFX_DIBitmap* srcBitmap,
1060                                    const CFX_RectF& rect) {
1061  if (!m_renderDevice)
1062    return FWL_Error::PropertyInvalid;
1063  CFX_DIBitmap* dst = m_renderDevice->GetBitmap();
1064  if (!dst)
1065    return FWL_Error::PropertyInvalid;
1066  CFX_RectF temp(rect);
1067  m_info.CTM.TransformRect(temp);
1068  CFX_RectF r;
1069  r.Set(0, 0, (FX_FLOAT)dst->GetWidth(), (FX_FLOAT)dst->GetWidth());
1070  r.Intersect(temp);
1071  if (r.IsEmpty()) {
1072    return FWL_Error::ParameterInvalid;
1073  }
1074  FX_ARGB* pSrcBuf = (FX_ARGB*)(srcBitmap->GetBuffer() +
1075                                int32_t(r.top) * srcBitmap->GetPitch());
1076  FX_ARGB* pDstBuf =
1077      (FX_ARGB*)(dst->GetBuffer() + int32_t(r.top) * dst->GetPitch());
1078  int32_t bottom = (int32_t)r.bottom();
1079  int32_t right = (int32_t)r.right();
1080  for (int32_t i = (int32_t)r.top; i < bottom; i++) {
1081    FX_ARGB* pSrcLine = pSrcBuf + (int32_t)r.left;
1082    FX_ARGB* pDstLine = pDstBuf + (int32_t)r.left;
1083    for (int32_t j = (int32_t)r.left; j < right; j++) {
1084      FX_ARGB c = *pDstLine;
1085      *pDstLine++ =
1086          ArgbEncode(FXARGB_A(c), (c & 0xFFFFFF) ^ (*pSrcLine & 0xFFFFFF));
1087      pSrcLine++;
1088    }
1089    pSrcBuf = (FX_ARGB*)((uint8_t*)pSrcBuf + srcBitmap->GetPitch());
1090    pDstBuf = (FX_ARGB*)((uint8_t*)pDstBuf + dst->GetPitch());
1091  }
1092  return FWL_Error::Succeeded;
1093}
1094
1095FWL_Error CFX_Graphics::EqvDIBitmap(const CFX_DIBitmap* srcBitmap,
1096                                    const CFX_RectF& rect) {
1097  if (!m_renderDevice)
1098    return FWL_Error::PropertyInvalid;
1099  CFX_DIBitmap* dst = m_renderDevice->GetBitmap();
1100  if (!dst)
1101    return FWL_Error::PropertyInvalid;
1102  CFX_RectF temp(rect);
1103  m_info.CTM.TransformRect(temp);
1104  CFX_RectF r;
1105  r.Set(0, 0, (FX_FLOAT)dst->GetWidth(), (FX_FLOAT)dst->GetWidth());
1106  r.Intersect(temp);
1107  if (r.IsEmpty()) {
1108    return FWL_Error::ParameterInvalid;
1109  }
1110  FX_ARGB* pSrcBuf = (FX_ARGB*)(srcBitmap->GetBuffer() +
1111                                int32_t(r.top) * srcBitmap->GetPitch());
1112  FX_ARGB* pDstBuf =
1113      (FX_ARGB*)(dst->GetBuffer() + int32_t(r.top) * dst->GetPitch());
1114  int32_t bottom = (int32_t)r.bottom();
1115  int32_t right = (int32_t)r.right();
1116  for (int32_t i = (int32_t)r.top; i < bottom; i++) {
1117    FX_ARGB* pSrcLine = pSrcBuf + (int32_t)r.left;
1118    FX_ARGB* pDstLine = pDstBuf + (int32_t)r.left;
1119    for (int32_t j = (int32_t)r.left; j < right; j++) {
1120      FX_ARGB c = *pDstLine;
1121      *pDstLine++ =
1122          ArgbEncode(FXARGB_A(c), ~((c & 0xFFFFFF) ^ (*pSrcLine & 0xFFFFFF)));
1123      pSrcLine++;
1124    }
1125    pSrcBuf = (FX_ARGB*)((uint8_t*)pSrcBuf + srcBitmap->GetPitch());
1126    pDstBuf = (FX_ARGB*)((uint8_t*)pDstBuf + dst->GetPitch());
1127  }
1128  return FWL_Error::Succeeded;
1129}
1130
1131FWL_Error CFX_Graphics::RenderDeviceSetLineDash(FX_DashStyle dashStyle) {
1132  switch (dashStyle) {
1133    case FX_DASHSTYLE_Solid: {
1134      m_info.graphState.SetDashCount(0);
1135      return FWL_Error::Succeeded;
1136    }
1137    case FX_DASHSTYLE_Dash: {
1138      FX_FLOAT dashArray[] = {3, 1};
1139      SetLineDash(0, dashArray, 2);
1140      return FWL_Error::Succeeded;
1141    }
1142    case FX_DASHSTYLE_Dot: {
1143      FX_FLOAT dashArray[] = {1, 1};
1144      SetLineDash(0, dashArray, 2);
1145      return FWL_Error::Succeeded;
1146    }
1147    case FX_DASHSTYLE_DashDot: {
1148      FX_FLOAT dashArray[] = {3, 1, 1, 1};
1149      SetLineDash(0, dashArray, 4);
1150      return FWL_Error::Succeeded;
1151    }
1152    case FX_DASHSTYLE_DashDotDot: {
1153      FX_FLOAT dashArray[] = {4, 1, 2, 1, 2, 1};
1154      SetLineDash(0, dashArray, 6);
1155      return FWL_Error::Succeeded;
1156    }
1157    default:
1158      return FWL_Error::ParameterInvalid;
1159  }
1160}
1161
1162FWL_Error CFX_Graphics::RenderDeviceStrokePath(CFX_Path* path,
1163                                               CFX_Matrix* matrix) {
1164  if (!m_info.strokeColor)
1165    return FWL_Error::PropertyInvalid;
1166  CFX_Matrix m;
1167  m.Set(m_info.CTM.a, m_info.CTM.b, m_info.CTM.c, m_info.CTM.d, m_info.CTM.e,
1168        m_info.CTM.f);
1169  if (matrix) {
1170    m.Concat(*matrix);
1171  }
1172  switch (m_info.strokeColor->m_type) {
1173    case FX_COLOR_Solid: {
1174      bool result =
1175          m_renderDevice->DrawPath(path->GetPathData(), &m, &m_info.graphState,
1176                                   0x0, m_info.strokeColor->m_info.argb, 0);
1177      if (!result)
1178        return FWL_Error::Indefinite;
1179      return FWL_Error::Succeeded;
1180    }
1181    case FX_COLOR_Pattern:
1182      return StrokePathWithPattern(path, &m);
1183    case FX_COLOR_Shading:
1184      return StrokePathWithShading(path, &m);
1185    default:
1186      return FWL_Error::PropertyInvalid;
1187  }
1188}
1189
1190FWL_Error CFX_Graphics::RenderDeviceFillPath(CFX_Path* path,
1191                                             FX_FillMode fillMode,
1192                                             CFX_Matrix* matrix) {
1193  if (!m_info.fillColor)
1194    return FWL_Error::PropertyInvalid;
1195  CFX_Matrix m;
1196  m.Set(m_info.CTM.a, m_info.CTM.b, m_info.CTM.c, m_info.CTM.d, m_info.CTM.e,
1197        m_info.CTM.f);
1198  if (matrix) {
1199    m.Concat(*matrix);
1200  }
1201  switch (m_info.fillColor->m_type) {
1202    case FX_COLOR_Solid: {
1203      bool result = m_renderDevice->DrawPath(
1204          path->GetPathData(), &m, &m_info.graphState,
1205          m_info.fillColor->m_info.argb, 0x0, fillMode);
1206      if (!result)
1207        return FWL_Error::Indefinite;
1208      return FWL_Error::Succeeded;
1209    }
1210    case FX_COLOR_Pattern:
1211      return FillPathWithPattern(path, fillMode, &m);
1212    case FX_COLOR_Shading:
1213      return FillPathWithShading(path, fillMode, &m);
1214    default:
1215      return FWL_Error::PropertyInvalid;
1216  }
1217}
1218
1219FWL_Error CFX_Graphics::RenderDeviceDrawImage(CFX_DIBSource* source,
1220                                              const CFX_PointF& point,
1221                                              CFX_Matrix* matrix) {
1222  CFX_Matrix m1;
1223  m1.Set(m_info.CTM.a, m_info.CTM.b, m_info.CTM.c, m_info.CTM.d, m_info.CTM.e,
1224         m_info.CTM.f);
1225  if (matrix) {
1226    m1.Concat(*matrix);
1227  }
1228  CFX_Matrix m2;
1229  m2.Set((FX_FLOAT)source->GetWidth(), 0.0, 0.0, (FX_FLOAT)source->GetHeight(),
1230         point.x, point.y);
1231  m2.Concat(m1);
1232  int32_t left, top;
1233  std::unique_ptr<CFX_DIBitmap> bmp1 = source->FlipImage(false, true);
1234  std::unique_ptr<CFX_DIBitmap> bmp2 = bmp1->TransformTo(&m2, left, top);
1235  CFX_RectF r;
1236  GetClipRect(r);
1237  CFX_DIBitmap* bitmap = m_renderDevice->GetBitmap();
1238  CFX_DIBitmap bmp;
1239  if (bmp.Create(bitmap->GetWidth(), bitmap->GetHeight(), FXDIB_Argb) &&
1240      m_renderDevice->GetDIBits(&bmp, 0, 0) &&
1241      bmp.TransferBitmap(FXSYS_round(r.left), FXSYS_round(r.top),
1242                         FXSYS_round(r.Width()), FXSYS_round(r.Height()),
1243                         bmp2.get(), FXSYS_round(r.left - left),
1244                         FXSYS_round(r.top - top)) &&
1245      m_renderDevice->SetDIBits(&bmp, 0, 0)) {
1246    return FWL_Error::Succeeded;
1247  }
1248  return FWL_Error::Indefinite;
1249}
1250
1251FWL_Error CFX_Graphics::RenderDeviceStretchImage(CFX_DIBSource* source,
1252                                                 const CFX_RectF& rect,
1253                                                 CFX_Matrix* matrix) {
1254  CFX_Matrix m1;
1255  m1.Set(m_info.CTM.a, m_info.CTM.b, m_info.CTM.c, m_info.CTM.d, m_info.CTM.e,
1256         m_info.CTM.f);
1257  if (matrix) {
1258    m1.Concat(*matrix);
1259  }
1260  std::unique_ptr<CFX_DIBitmap> bmp1 =
1261      source->StretchTo((int32_t)rect.Width(), (int32_t)rect.Height());
1262  CFX_Matrix m2;
1263  m2.Set(rect.Width(), 0.0, 0.0, rect.Height(), rect.left, rect.top);
1264  m2.Concat(m1);
1265  int32_t left, top;
1266  std::unique_ptr<CFX_DIBitmap> bmp2 = bmp1->FlipImage(false, true);
1267  std::unique_ptr<CFX_DIBitmap> bmp3 = bmp2->TransformTo(&m2, left, top);
1268  CFX_RectF r;
1269  GetClipRect(r);
1270  CFX_DIBitmap* bitmap = m_renderDevice->GetBitmap();
1271  if (bitmap->CompositeBitmap(FXSYS_round(r.left), FXSYS_round(r.top),
1272                              FXSYS_round(r.Width()), FXSYS_round(r.Height()),
1273                              bmp3.get(), FXSYS_round(r.left - left),
1274                              FXSYS_round(r.top - top))) {
1275    return FWL_Error::Succeeded;
1276  }
1277  return FWL_Error::Indefinite;
1278}
1279
1280FWL_Error CFX_Graphics::RenderDeviceShowText(const CFX_PointF& point,
1281                                             const CFX_WideString& text,
1282                                             CFX_Matrix* matrix) {
1283  int32_t length = text.GetLength();
1284  uint32_t* charCodes = FX_Alloc(uint32_t, length);
1285  FXTEXT_CHARPOS* charPos = FX_Alloc(FXTEXT_CHARPOS, length);
1286  CFX_RectF rect;
1287  rect.Set(point.x, point.y, 0, 0);
1288  CalcTextInfo(text, charCodes, charPos, rect);
1289  CFX_Matrix m;
1290  m.Set(m_info.CTM.a, m_info.CTM.b, m_info.CTM.c, m_info.CTM.d, m_info.CTM.e,
1291        m_info.CTM.f);
1292  m.Translate(0, m_info.fontSize * m_info.fontHScale);
1293  if (matrix) {
1294    m.Concat(*matrix);
1295  }
1296  bool result = m_renderDevice->DrawNormalText(
1297      length, charPos, m_info.font, -m_info.fontSize * m_info.fontHScale, &m,
1298      m_info.fillColor->m_info.argb, FXTEXT_CLEARTYPE);
1299  if (!result)
1300    return FWL_Error::Indefinite;
1301  FX_Free(charPos);
1302  FX_Free(charCodes);
1303  return FWL_Error::Succeeded;
1304}
1305
1306FWL_Error CFX_Graphics::StrokePathWithPattern(CFX_Path* path,
1307                                              CFX_Matrix* matrix) {
1308  return FWL_Error::MethodNotSupported;
1309}
1310
1311FWL_Error CFX_Graphics::StrokePathWithShading(CFX_Path* path,
1312                                              CFX_Matrix* matrix) {
1313  return FWL_Error::MethodNotSupported;
1314}
1315
1316FWL_Error CFX_Graphics::FillPathWithPattern(CFX_Path* path,
1317                                            FX_FillMode fillMode,
1318                                            CFX_Matrix* matrix) {
1319  CFX_Pattern* pattern = m_info.fillColor->m_info.pattern;
1320  CFX_DIBitmap* bitmap = m_renderDevice->GetBitmap();
1321  int32_t width = bitmap->GetWidth();
1322  int32_t height = bitmap->GetHeight();
1323  CFX_DIBitmap bmp;
1324  bmp.Create(width, height, FXDIB_Argb);
1325  m_renderDevice->GetDIBits(&bmp, 0, 0);
1326
1327  FX_HatchStyle hatchStyle = m_info.fillColor->m_info.pattern->m_hatchStyle;
1328  if (hatchStyle < FX_HATCHSTYLE_Horizontal ||
1329      hatchStyle > FX_HATCHSTYLE_SolidDiamond) {
1330    return FWL_Error::IntermediateValueInvalid;
1331  }
1332  const FX_HATCHDATA& data = hatchBitmapData[hatchStyle];
1333  CFX_DIBitmap mask;
1334  mask.Create(data.width, data.height, FXDIB_1bppMask);
1335  FXSYS_memcpy(mask.GetBuffer(), data.maskBits, mask.GetPitch() * data.height);
1336  CFX_FloatRect rectf = path->GetPathData()->GetBoundingBox();
1337  if (matrix) {
1338    rectf.Transform(matrix);
1339  }
1340  FX_RECT rect(FXSYS_round(rectf.left), FXSYS_round(rectf.top),
1341               FXSYS_round(rectf.right), FXSYS_round(rectf.bottom));
1342  CFX_FxgeDevice device;
1343  device.Attach(&bmp, false, nullptr, false);
1344  device.FillRect(&rect, m_info.fillColor->m_info.pattern->m_backArgb);
1345  for (int32_t j = rect.bottom; j < rect.top; j += mask.GetHeight()) {
1346    for (int32_t i = rect.left; i < rect.right; i += mask.GetWidth()) {
1347      device.SetBitMask(&mask, i, j,
1348                        m_info.fillColor->m_info.pattern->m_foreArgb);
1349    }
1350  }
1351
1352  m_renderDevice->SaveState();
1353  m_renderDevice->SetClip_PathFill(path->GetPathData(), matrix, fillMode);
1354  SetDIBitsWithMatrix(&bmp, &pattern->m_matrix);
1355  m_renderDevice->RestoreState(false);
1356  return FWL_Error::Succeeded;
1357}
1358
1359FWL_Error CFX_Graphics::FillPathWithShading(CFX_Path* path,
1360                                            FX_FillMode fillMode,
1361                                            CFX_Matrix* matrix) {
1362  CFX_DIBitmap* bitmap = m_renderDevice->GetBitmap();
1363  int32_t width = bitmap->GetWidth();
1364  int32_t height = bitmap->GetHeight();
1365  FX_FLOAT start_x = m_info.fillColor->m_shading->m_beginPoint.x;
1366  FX_FLOAT start_y = m_info.fillColor->m_shading->m_beginPoint.y;
1367  FX_FLOAT end_x = m_info.fillColor->m_shading->m_endPoint.x;
1368  FX_FLOAT end_y = m_info.fillColor->m_shading->m_endPoint.y;
1369  CFX_DIBitmap bmp;
1370  bmp.Create(width, height, FXDIB_Argb);
1371  m_renderDevice->GetDIBits(&bmp, 0, 0);
1372  int32_t pitch = bmp.GetPitch();
1373  bool result = false;
1374  switch (m_info.fillColor->m_shading->m_type) {
1375    case FX_SHADING_Axial: {
1376      FX_FLOAT x_span = end_x - start_x;
1377      FX_FLOAT y_span = end_y - start_y;
1378      FX_FLOAT axis_len_square = (x_span * x_span) + (y_span * y_span);
1379      for (int32_t row = 0; row < height; row++) {
1380        uint32_t* dib_buf = (uint32_t*)(bmp.GetBuffer() + row * pitch);
1381        for (int32_t column = 0; column < width; column++) {
1382          FX_FLOAT x = (FX_FLOAT)(column);
1383          FX_FLOAT y = (FX_FLOAT)(row);
1384          FX_FLOAT scale =
1385              (((x - start_x) * x_span) + ((y - start_y) * y_span)) /
1386              axis_len_square;
1387          if (scale < 0) {
1388            if (!m_info.fillColor->m_shading->m_isExtendedBegin) {
1389              continue;
1390            }
1391            scale = 0;
1392          } else if (scale > 1.0f) {
1393            if (!m_info.fillColor->m_shading->m_isExtendedEnd) {
1394              continue;
1395            }
1396            scale = 1.0f;
1397          }
1398          int32_t index = (int32_t)(scale * (FX_SHADING_Steps - 1));
1399          dib_buf[column] = m_info.fillColor->m_shading->m_argbArray[index];
1400        }
1401      }
1402      result = true;
1403      break;
1404    }
1405    case FX_SHADING_Radial: {
1406      FX_FLOAT start_r = m_info.fillColor->m_shading->m_beginRadius;
1407      FX_FLOAT end_r = m_info.fillColor->m_shading->m_endRadius;
1408      FX_FLOAT a = ((start_x - end_x) * (start_x - end_x)) +
1409                   ((start_y - end_y) * (start_y - end_y)) -
1410                   ((start_r - end_r) * (start_r - end_r));
1411      for (int32_t row = 0; row < height; row++) {
1412        uint32_t* dib_buf = (uint32_t*)(bmp.GetBuffer() + row * pitch);
1413        for (int32_t column = 0; column < width; column++) {
1414          FX_FLOAT x = (FX_FLOAT)(column);
1415          FX_FLOAT y = (FX_FLOAT)(row);
1416          FX_FLOAT b = -2 * (((x - start_x) * (end_x - start_x)) +
1417                             ((y - start_y) * (end_y - start_y)) +
1418                             (start_r * (end_r - start_r)));
1419          FX_FLOAT c = ((x - start_x) * (x - start_x)) +
1420                       ((y - start_y) * (y - start_y)) - (start_r * start_r);
1421          FX_FLOAT s;
1422          if (a == 0) {
1423            s = -c / b;
1424          } else {
1425            FX_FLOAT b2_4ac = (b * b) - 4 * (a * c);
1426            if (b2_4ac < 0) {
1427              continue;
1428            }
1429            FX_FLOAT root = (FXSYS_sqrt(b2_4ac));
1430            FX_FLOAT s1, s2;
1431            if (a > 0) {
1432              s1 = (-b - root) / (2 * a);
1433              s2 = (-b + root) / (2 * a);
1434            } else {
1435              s2 = (-b - root) / (2 * a);
1436              s1 = (-b + root) / (2 * a);
1437            }
1438            if (s2 <= 1.0f || m_info.fillColor->m_shading->m_isExtendedEnd) {
1439              s = (s2);
1440            } else {
1441              s = (s1);
1442            }
1443            if ((start_r) + s * (end_r - start_r) < 0) {
1444              continue;
1445            }
1446          }
1447          if (s < 0) {
1448            if (!m_info.fillColor->m_shading->m_isExtendedBegin) {
1449              continue;
1450            }
1451            s = 0;
1452          }
1453          if (s > 1.0f) {
1454            if (!m_info.fillColor->m_shading->m_isExtendedEnd) {
1455              continue;
1456            }
1457            s = 1.0f;
1458          }
1459          int index = (int32_t)(s * (FX_SHADING_Steps - 1));
1460          dib_buf[column] = m_info.fillColor->m_shading->m_argbArray[index];
1461        }
1462      }
1463      result = true;
1464      break;
1465    }
1466    default: {
1467      result = false;
1468      break;
1469    }
1470  }
1471  if (result) {
1472    m_renderDevice->SaveState();
1473    m_renderDevice->SetClip_PathFill(path->GetPathData(), matrix, fillMode);
1474    SetDIBitsWithMatrix(&bmp, matrix);
1475    m_renderDevice->RestoreState(false);
1476  }
1477  return result ? FWL_Error::Succeeded : FWL_Error::PropertyInvalid;
1478}
1479
1480FWL_Error CFX_Graphics::SetDIBitsWithMatrix(CFX_DIBSource* source,
1481                                            CFX_Matrix* matrix) {
1482  if (matrix->IsIdentity()) {
1483    m_renderDevice->SetDIBits(source, 0, 0);
1484  } else {
1485    CFX_Matrix m;
1486    m.Set((FX_FLOAT)source->GetWidth(), 0, 0, (FX_FLOAT)source->GetHeight(), 0,
1487          0);
1488    m.Concat(*matrix);
1489    int32_t left, top;
1490    std::unique_ptr<CFX_DIBitmap> bmp1 = source->FlipImage(false, true);
1491    std::unique_ptr<CFX_DIBitmap> bmp2 = bmp1->TransformTo(&m, left, top);
1492    m_renderDevice->SetDIBits(bmp2.get(), left, top);
1493  }
1494  return FWL_Error::Succeeded;
1495}
1496
1497FWL_Error CFX_Graphics::CalcTextInfo(const CFX_WideString& text,
1498                                     uint32_t* charCodes,
1499                                     FXTEXT_CHARPOS* charPos,
1500                                     CFX_RectF& rect) {
1501  std::unique_ptr<CFX_UnicodeEncoding> encoding(
1502      new CFX_UnicodeEncoding(m_info.font));
1503  int32_t length = text.GetLength();
1504  FX_FLOAT penX = (FX_FLOAT)rect.left;
1505  FX_FLOAT penY = (FX_FLOAT)rect.top;
1506  FX_FLOAT left = (FX_FLOAT)(0);
1507  FX_FLOAT top = (FX_FLOAT)(0);
1508  charCodes[0] = text.GetAt(0);
1509  charPos[0].m_OriginX = penX + left;
1510  charPos[0].m_OriginY = penY + top;
1511  charPos[0].m_GlyphIndex = encoding->GlyphFromCharCode(charCodes[0]);
1512  charPos[0].m_FontCharWidth = FXSYS_round(
1513      m_info.font->GetGlyphWidth(charPos[0].m_GlyphIndex) * m_info.fontHScale);
1514  charPos[0].m_bGlyphAdjust = true;
1515  charPos[0].m_AdjustMatrix[0] = -1;
1516  charPos[0].m_AdjustMatrix[1] = 0;
1517  charPos[0].m_AdjustMatrix[2] = 0;
1518  charPos[0].m_AdjustMatrix[3] = 1;
1519  penX += (FX_FLOAT)(charPos[0].m_FontCharWidth) * m_info.fontSize / 1000 +
1520          m_info.fontSpacing;
1521  for (int32_t i = 1; i < length; i++) {
1522    charCodes[i] = text.GetAt(i);
1523    charPos[i].m_OriginX = penX + left;
1524    charPos[i].m_OriginY = penY + top;
1525    charPos[i].m_GlyphIndex = encoding->GlyphFromCharCode(charCodes[i]);
1526    charPos[i].m_FontCharWidth =
1527        FXSYS_round(m_info.font->GetGlyphWidth(charPos[i].m_GlyphIndex) *
1528                    m_info.fontHScale);
1529    charPos[i].m_bGlyphAdjust = true;
1530    charPos[i].m_AdjustMatrix[0] = -1;
1531    charPos[i].m_AdjustMatrix[1] = 0;
1532    charPos[i].m_AdjustMatrix[2] = 0;
1533    charPos[i].m_AdjustMatrix[3] = 1;
1534    penX += (FX_FLOAT)(charPos[i].m_FontCharWidth) * m_info.fontSize / 1000 +
1535            m_info.fontSpacing;
1536  }
1537  rect.width = (FX_FLOAT)penX - rect.left;
1538  rect.height = rect.top + m_info.fontSize * m_info.fontHScale - rect.top;
1539  return FWL_Error::Succeeded;
1540}
1541
1542CFX_Graphics::TInfo::TInfo()
1543    : isAntialiasing(true),
1544      strokeAlignment(FX_STROKEALIGNMENT_Center),
1545      isActOnDash(false),
1546      strokeColor(nullptr),
1547      fillColor(nullptr),
1548      font(nullptr),
1549      fontSize(40.0),
1550      fontHScale(1.0),
1551      fontSpacing(0.0) {}
1552
1553CFX_Graphics::TInfo::TInfo(const TInfo& info)
1554    : graphState(info.graphState),
1555      isAntialiasing(info.isAntialiasing),
1556      strokeAlignment(info.strokeAlignment),
1557      CTM(info.CTM),
1558      isActOnDash(info.isActOnDash),
1559      strokeColor(info.strokeColor),
1560      fillColor(info.fillColor),
1561      font(info.font),
1562      fontSize(info.fontSize),
1563      fontHScale(info.fontHScale),
1564      fontSpacing(info.fontSpacing) {}
1565
1566CFX_Graphics::TInfo& CFX_Graphics::TInfo::operator=(const TInfo& other) {
1567  graphState.Copy(other.graphState);
1568  isAntialiasing = other.isAntialiasing;
1569  strokeAlignment = other.strokeAlignment;
1570  CTM = other.CTM;
1571  isActOnDash = other.isActOnDash;
1572  strokeColor = other.strokeColor;
1573  fillColor = other.fillColor;
1574  font = other.font;
1575  fontSize = other.fontSize;
1576  fontHScale = other.fontHScale;
1577  fontSpacing = other.fontSpacing;
1578  return *this;
1579}
1580