microvg  2.1.0
microvg
LLVG_PATH_impl.c
Go to the documentation of this file.
1 /*
2  * C
3  *
4  * Copyright 2022 MicroEJ Corp. All rights reserved.
5  * Use of this source code is governed by a BSD-style license that can be found with this software.
6  */
7 
21 #include "microvg_configuration.h"
22 
23 #ifdef VG_FEATURE_PATH
24 
25 // -----------------------------------------------------------------------------
26 // Includes
27 // -----------------------------------------------------------------------------
28 
29 #include <math.h>
30 #include <string.h>
31 
32 #include <LLVG_PATH_impl.h>
33 
34 #include "microvg_path.h"
35 #include "microvg_helper.h"
36 #include "bsp_util.h"
37 
38 #include "mej_math.h"
39 
40 // -----------------------------------------------------------------------------
41 // Private functions
42 // -----------------------------------------------------------------------------
43 
44 /*
45  * @brief Extends the path to be able to store the command and its parameters.
46  *
47  * @return the offset in path buffer where the command will be stored. If the path
48  * buffer is not large enough to contain the requested command, returns a negative
49  * number corresponding to size the buffer must be enlarged for this command.
50  */
51 static int32_t _extend_path(MICROVG_PATH_HEADER_t* path, jint length, jint cmd, uint32_t nb_fields) {
52  uint32_t index = path->data_offset + path->data_size;
53  uint32_t extra_size = MICROVG_PATH_get_path_command_size(cmd, nb_fields);
54  int32_t ret;
55 
56  if (length >= (index + extra_size)) {
57  path->data_size += extra_size;
58 
59  // return next free space (return a positive value)
60  ret = index;
61  }
62  else {
63  // too small buffer, ret is the required extra size
64  // (return a negative value)
65  ret = -extra_size;
66  }
67 
68  return ret;
69 }
70 
71 static int32_t _close_path(MICROVG_PATH_HEADER_t* path, jint length, jfloat x1, jfloat y1, jfloat x2, jfloat y2) {
72  int32_t index = _extend_path(path, length, LLVG_PATH_CMD_CLOSE, 0);
73  int32_t ret = LLVG_SUCCESS;
74  if (index > 0) {
75  // finalizes the path by storing the path's bounds
76  path->bounds_xmin = x1;
77  path->bounds_xmax = x2;
78  path->bounds_ymin = y1;
79  path->bounds_ymax = y2;
80  (void)MICROVG_PATH_append_path_command0((jbyte*)path, (uint32_t)index, LLVG_PATH_CMD_CLOSE);
81  }
82  else {
83  // too small buffer, ret is the required extra size * -1
84  ret = -index;
85  }
86  return ret;
87 }
88 
89 // -----------------------------------------------------------------------------
90 // Specific path format functions [optional]: weak functions
91 // -----------------------------------------------------------------------------
92 
93 // See the header file for the function documentation
94 BSP_DECLARE_WEAK_FCNT void MICROVG_PATH_initialize(void) {
95  // nothing to do
96 }
97 
98 // See the header file for the function documentation
99 BSP_DECLARE_WEAK_FCNT uint32_t MICROVG_PATH_get_path_header_size(void) {
100  return sizeof(MICROVG_PATH_HEADER_t);
101 }
102 
103 // See the header file for the function documentation
104 BSP_DECLARE_WEAK_FCNT uint32_t MICROVG_PATH_get_path_command_size(jint command, uint32_t nbParams) {
105  (void)command;
106  return (nbParams + (uint32_t)1 /* command */) * sizeof(uint32_t);
107 }
108 
109 // See the header file for the function documentation
110 BSP_DECLARE_WEAK_FCNT uint32_t MICROVG_PATH_append_path_command0(jbyte* path, uint32_t offset, jint cmd) {
111  uint32_t* data = (uint32_t*)(path + offset);
112  *data = MICROVG_PATH_convert_path_command(cmd);
113  return sizeof(uint32_t);
114 }
115 
116 // See the header file for the function documentation
117 BSP_DECLARE_WEAK_FCNT uint32_t MICROVG_PATH_append_path_command1(jbyte* path, uint32_t offset, jint cmd, jfloat x, jfloat y) {
118  uint32_t* data = (uint32_t*)(path + offset);
119  *data = MICROVG_PATH_convert_path_command(cmd);
120  ++data;
121  *data = JFLOAT_TO_UINT32_t(x);
122  ++data;
123  *data = JFLOAT_TO_UINT32_t(y);
124  return (uint32_t)3 * sizeof(uint32_t);
125 }
126 
127 // See the header file for the function documentation
128 BSP_DECLARE_WEAK_FCNT uint32_t MICROVG_PATH_append_path_command2(jbyte* path, uint32_t offset, jint cmd, jfloat x1, jfloat y1, jfloat x2, jfloat y2) {
129  uint32_t* data = (uint32_t*)(path + offset);
130  *data = MICROVG_PATH_convert_path_command(cmd);
131  ++data;
132  *data = JFLOAT_TO_UINT32_t(x1);
133  ++data;
134  *data = JFLOAT_TO_UINT32_t(y1);
135  ++data;
136  *data = JFLOAT_TO_UINT32_t(x2);
137  ++data;
138  *data = JFLOAT_TO_UINT32_t(y2);
139  return (uint32_t)5 * sizeof(uint32_t);
140 }
141 
142 // See the header file for the function documentation
143 BSP_DECLARE_WEAK_FCNT uint32_t MICROVG_PATH_append_path_command3(jbyte* path, uint32_t offset, jint cmd, jfloat x1, jfloat y1, jfloat x2, jfloat y2,
144  jfloat x3, jfloat y3) {
145  uint32_t* data = (uint32_t*)(path + offset);
146  *data = MICROVG_PATH_convert_path_command(cmd);
147  ++data;
148  *data = JFLOAT_TO_UINT32_t(x1);
149  ++data;
150  *data = JFLOAT_TO_UINT32_t(y1);
151  ++data;
152  *data = JFLOAT_TO_UINT32_t(x2);
153  ++data;
154  *data = JFLOAT_TO_UINT32_t(y2);
155  ++data;
156  *data = JFLOAT_TO_UINT32_t(x3);
157  ++data;
158  *data = JFLOAT_TO_UINT32_t(y3);
159  return (uint32_t)7 * sizeof(uint32_t);
160 }
161 
162 // -----------------------------------------------------------------------------
163 // LLVG_PATH_impl.h functions
164 // -----------------------------------------------------------------------------
165 
166 // See the header file for the function documentation
167 jint LLVG_PATH_IMPL_initializePath(jbyte* jpath, jint length) {
168 
170  uint32_t header_size = MICROVG_PATH_get_path_header_size();
171  jint ret = LLVG_SUCCESS;
172 
173  if (length >= header_size) {
174  path->data_size = 0;
175  path->data_offset = header_size;
176  path->format = MICROVG_PATH_get_path_encoder_format();
177  }
178  else {
179  // the given byte array is too small
180  ret = header_size;
181  }
182 
183  return ret;
184 }
185 
186 // See the header file for the function documentation
187 jint LLVG_PATH_IMPL_appendPathCommand1(jbyte* jpath, jint length, jint cmd, jfloat x, jfloat y) {
188 
190  jint ret = LLVG_SUCCESS;
191 
192  int32_t index = _extend_path(path, length, cmd, 2);
193  if (index > 0) {
194  (void)MICROVG_PATH_append_path_command1((jbyte*)path, (uint32_t)index, cmd, x, y);
195  }
196  else {
197  // too small buffer, ret is the required extra size * -1
198  ret = -index;
199  }
200 
201  return ret;
202 }
203 
204 // See the header file for the function documentation
205 jint LLVG_PATH_IMPL_appendPathCommand2(jbyte* jpath, jint length, jint cmd, jfloat x1, jfloat y1, jfloat x2,
206  jfloat y2) {
207 
209  jint ret = LLVG_SUCCESS;
210 
211  if (LLVG_PATH_CMD_CLOSE == cmd) {
212  // parameters are path's bounds
213  ret = _close_path(path, length, x1, y1, x2, y2);
214  }
215  else {
216  int32_t index = _extend_path(path, length, cmd, 4);
217  if (index > 0) {
218  (void)MICROVG_PATH_append_path_command2((jbyte*)path, (uint32_t)index, cmd, x1, y1, x2, y2);
219  }
220  else {
221  // too small buffer, ret is the required extra size * -1
222  ret = -index;
223  }
224  }
225 
226  return ret;
227 }
228 
229 // See the header file for the function documentation
230 jint LLVG_PATH_IMPL_appendPathCommand3(jbyte* jpath, jint length, jint cmd, jfloat x1, jfloat y1, jfloat x2,
231  jfloat y2, jfloat x3, jfloat y3) {
232 
234  jint ret = LLVG_SUCCESS;
235 
236  int32_t index = _extend_path(path, length, cmd, 6);
237  if (index > 0) {
238  (void)MICROVG_PATH_append_path_command3((jbyte*)path, (uint32_t)index, cmd, x1, y1, x2, y2, x3, y3);
239  }
240  else {
241  // too small buffer, ret is the required extra size * -1
242  ret = -index;
243  }
244 
245  return ret;
246 }
247 
248 // See the header file for the function documentation
249 void LLVG_PATH_IMPL_reopenPath(jbyte* jpath) {
251  path->data_size -= MICROVG_PATH_get_path_command_size(LLVG_PATH_CMD_CLOSE, 0);
252 }
253 
254 
255 // See the header file for the function documentation
256 jint LLVG_PATH_IMPL_mergePaths(jbyte* jpathDest, jbyte* jpathSrc1, jbyte* jpathSrc2, jfloat ratio){
257 
258  jint ret = LLVG_SUCCESS;
259  float remaining = (1-ratio);
260 
261  MICROVG_PATH_HEADER_t* pathDest = (MICROVG_PATH_HEADER_t*)jpathDest;
262  MICROVG_PATH_HEADER_t* pathSrc1 = (MICROVG_PATH_HEADER_t*)jpathSrc1;
263  MICROVG_PATH_HEADER_t* pathSrc2 = (MICROVG_PATH_HEADER_t*)jpathSrc2;
264 
265  // Copy header from pathSrc1
266  pathDest->data_size = pathSrc1->data_size;
267  pathDest->data_offset = pathSrc1->data_offset;
268  pathDest->format = pathSrc1->format;
269 
270  // Compute bounds
271  float fSrc1 = pathSrc1->bounds_xmin;
272  float fSrc2 = pathSrc2->bounds_xmin;
273  float fDest = MEJ_MIN(fSrc1, fSrc2);
274  pathDest->bounds_xmin = fDest;
275 
276  fSrc1 = pathSrc1->bounds_ymin;
277  fSrc2 = pathSrc2->bounds_ymin;
278  fDest = MEJ_MIN(fSrc1, fSrc2);
279  pathDest->bounds_ymin = fDest;
280 
281  fSrc1 = pathSrc1->bounds_xmax;
282  fSrc2 = pathSrc2->bounds_xmax;
283  fDest = MEJ_MAX(fSrc1, fSrc2);
284  pathDest->bounds_xmax = fDest;
285 
286  fSrc1 = pathSrc1->bounds_ymax;
287  fSrc2 = pathSrc2->bounds_ymax;
288  fDest = MEJ_MAX(fSrc1, fSrc2);
289  pathDest->bounds_ymax = fDest;
290 
291  // Compute commands
292  uint32_t* dataDest = (uint32_t*)(jpathDest + pathDest->data_offset);
293  uint32_t* dataSrc1 = (uint32_t*)(jpathSrc1 + pathSrc1->data_offset);
294  uint32_t* dataSrc2 = (uint32_t*)(jpathSrc2 + pathSrc2->data_offset);
295 
296  for(uint16_t i=0; i < pathDest->data_size;){
297 
298  uint32_t cmdSrc1 = *dataSrc1;
299 
300  uint32_t nb_parameters = MICROVG_PATH_get_command_parameter_number(cmdSrc1);
301 
302  *dataDest = cmdSrc1;
303  dataSrc1++;
304  dataSrc2++;
305  dataDest++;
306  i += (uint16_t) 4;
307 
308  for(uint32_t j=0; j<nb_parameters;j++ ){
309 
310  // cppcheck-suppress [invalidPointerCast,redundantPointerOp,misra-c2012-11.3] accepted casting macro
311  fSrc1 = UINT32_t_TO_JFLOAT(*dataSrc1);
312  // cppcheck-suppress [invalidPointerCast,redundantPointerOp,misra-c2012-11.3] accepted casting macro
313  fSrc2 = UINT32_t_TO_JFLOAT(*dataSrc2);
314  fDest = (remaining * fSrc1) + (ratio * fSrc2);
315 
316  // cppcheck-suppress [invalidPointerCast,misra-c2012-11.3] accepted casting macro
317  *dataDest = JFLOAT_TO_UINT32_t(fDest);
318 
319  dataSrc1++;
320  dataSrc2++;
321  dataDest++;
322  i += (uint16_t)4;
323  }
324  }
325  return ret;
326 }
327 
328 // -----------------------------------------------------------------------------
329 // EOF
330 // -----------------------------------------------------------------------------
331 
332 #endif // VG_FEATURE_PATH
MicroEJ MicroVG library low level API: helper to implement library natives methods.
MicroEJ MicroVG library low level API: implementation of Path.
MicroEJ MicroVG library low level API: enable some features according to the hardware capacities...