microvg  2.1.0
microvg
LLVG_GRADIENT_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 
19 #include "microvg_configuration.h"
20 
21 #ifdef VG_FEATURE_GRADIENT
22 
23 // -----------------------------------------------------------------------------
24 // Includes
25 // -----------------------------------------------------------------------------
26 
27 #include <math.h>
28 #include <string.h>
29 
30 #include <LLVG_GRADIENT_impl.h>
31 
32 #include "microvg_gradient.h"
33 #include "microvg_helper.h"
34 #include "bsp_util.h"
35 
36 #if defined (VG_FEATURE_GRADIENT) && defined (VG_FEATURE_GRADIENT_FULL) && (VG_FEATURE_GRADIENT == VG_FEATURE_GRADIENT_FULL)
37 
38 // -----------------------------------------------------------------------------
39 // Specific gradient format functions [optional]: weak functions
40 // -----------------------------------------------------------------------------
41 
42 // See the header file for the function documentation
43 BSP_DECLARE_WEAK_FCNT uint32_t MICROVG_GRADIENT_get_gradient_header_size(void) {
44  return sizeof(MICROVG_GRADIENT_HEADER_t) / sizeof(uint32_t);
45 }
46 
47 // -----------------------------------------------------------------------------
48 // LLVG_GRADIENT_impl.h functions
49 // -----------------------------------------------------------------------------
50 
51 // See the header file for the function documentation
52 jint LLVG_GRADIENT_IMPL_initializeGradient(jint* jgradient, jint length, jint* colors, jint count,
53  jfloat* positions, jfloat xStart, jfloat yStart, jfloat xEnd, jfloat yEnd) {
55  uint32_t expectedLength = MICROVG_GRADIENT_get_gradient_header_size() + (count * 2 /* colors and positions */);
56  jint ret;
57  if (length >= expectedLength) {
58 
59  // fill header
60  float angle = RAD_TO_DEG(atan2f(yEnd - yStart, xEnd - xStart));
61  float l = sqrtf(powf(xEnd - xStart, 2) + powf(yEnd - yStart, 2));
62 
63  gradient->x = xStart;
64  gradient->y = yStart;
65  gradient->angle = angle;
66 
67  // If gradient length is null, create a horizontal gradient
68  // with length==1 using first and last color.
69  // The transition point is placed at the center of the scale.
70  if(0.f == l){
71  gradient->length = 1;
72  gradient->count = 2;
73 
74  gradient->colors_offset = MICROVG_GRADIENT_get_gradient_header_size();
75  gradient->positions_offset = MICROVG_GRADIENT_get_gradient_header_size() + (jint)2;
76 
77  uint32_t* colors_addr = &((uint32_t*)gradient)[gradient->colors_offset];
78  *colors_addr = *colors;
79  colors_addr[1] = colors[count - 1];
80 
81  uint32_t* positions_addr = &((uint32_t*)gradient)[gradient->positions_offset];
82  *positions_addr = (uint32_t) (MICROVG_GRADIENT_get_gradient_scale_size() / 2);
83  positions_addr[1] = (*positions_addr) + 1;
84  }
85  else{
86 
87  gradient->count = (uint32_t)count;
88  gradient->length = l;
89 
90  gradient->colors_offset = MICROVG_GRADIENT_get_gradient_header_size();
91  gradient->positions_offset = MICROVG_GRADIENT_get_gradient_header_size() + count;
92 
93  // fill colors
94  void* colors_addr = (void*)&((uint32_t*)gradient)[gradient->colors_offset];
95  (void)memcpy(colors_addr, colors, count * sizeof(uint32_t));
96 
97  // fill positions
98  uint32_t max_position = (uint32_t) (MICROVG_GRADIENT_get_gradient_scale_size() - 1);
99  uint32_t* positions_addr = &((uint32_t*)gradient)[gradient->positions_offset];
100  if (NULL == positions) {
101  float step = (float) (max_position / (count - 1));
102  float currentStep = 0.f;
103  for (uint32_t i = 0; i < count; i++) {
104  *positions_addr = (uint32_t) currentStep;
105  ++positions_addr;
106  currentStep += step;
107  }
108  }
109  else {
110  // scales an Android gradient stops array with the gradient scale
111  for (uint32_t i = 0; i < count; i++) {
112  *positions_addr = (uint32_t) (positions[i] * max_position);
113  ++positions_addr;
114  }
115  }
116  }
117  ret = LLVG_SUCCESS;
118  }
119  else {
120  // the given array is too small
121  ret = expectedLength;
122  }
123  return ret;
124 }
125 
126 #else // #if (VG_FEATURE_GRADIENT == VG_FEATURE_GRADIENT_FULL) => VG_FEATURE_GRADIENT_FIRST_COLOR
127 
128 // See the header file for the function documentation
129 jint LLVG_GRADIENT_IMPL_initializeGradient(jint* gradient, jint length, jint* colors, jint count,
130  jfloat* positions, jfloat xStart, jfloat yStart, jfloat xEnd, jfloat yEnd) {
131 
132  (void)count;
133  (void)positions;
134  (void)xStart;
135  (void)yStart;
136  (void)xEnd;
137  (void)yEnd;
138 
139  jint ret;
140 
141  if (length < 1) {
142  // the given array is too small
143  ret = 1; // return the expected minimal size
144  }
145  else {
146  // just store the first color
147  gradient[0] = colors[0];
148  ret = LLVG_SUCCESS;
149  }
150 
151  return ret;
152 }
153 
154 #endif // #if (VG_FEATURE_GRADIENT == VG_FEATURE_GRADIENT_FULL)
155 
156 // -----------------------------------------------------------------------------
157 // EOF
158 // -----------------------------------------------------------------------------
159 
160 #endif // VG_FEATURE_GRADIENT
MicroEJ MicroVG library low level API: helper to implement library natives methods.
MicroEJ MicroVG library low level API: implementation of LinearGradient.
MicroEJ MicroVG library low level API: enable some features according to the hardware capacities...