1 /* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 /** 17 * @file fill_gradient.h 18 * @brief Defines Scanline gradient mode 19 * @since 1.0 20 * @version 1.0 21 */ 22 23 24 #ifndef GRAPHIC_LITE_FILL_GRADIENT_H 25 #define GRAPHIC_LITE_FILL_GRADIENT_H 26 27 28 #include "gfx_utils/color.h" 29 #include "gfx_utils/diagram/common/common_basics.h" 30 #include "gfx_utils/diagram/spancolorfill/fill_interpolator.h" 31 #include "gfx_utils/diagram/spancolorfill/fill_gradient_lut.h" 32 #include "gfx_utils/graphic_math.h" 33 #include "fill_base.h" 34 namespace OHOS { 35 class Gradient { 36 public: 37 virtual int16_t Calculate(int16_t x, int16_t y, int16_t startRadius, int16_t endRadius, int16_t size) = 0; 38 }; 39 40 /** 41 * Gradient scanline fill 42 * @ColorT Color source type, Interpolator span interpolator 43 * @GradientFgradient_function The function of 44 * the corresponding mode to calculate the position of the current point 45 * @ColorF Color array 46 */ 47 class FillGradient : public SpanBase { 48 #if defined(GRAPHIC_ENABLE_GRADIENT_FILL_FLAG) && GRAPHIC_ENABLE_GRADIENT_FILL_FLAG 49 public: FillGradient()50 FillGradient() {} 51 /** 52 * @brief SpanGradient Constructor for scanline gradient 53 * @param inter Interpolator 54 * @param GradientFunction 55 * The function of the corresponding mode to calculate the position of the current point 56 * @param ColorFunction Gradient array 57 * @param distance1 The parameter content is determined according to the mode: 58 * it is the starting circle radius when radiating the gradient 59 * @param distance2 Determine the parameter content according to the mode: 60 * the radius of the end circle in the case of radial gradient and 61 * the distance of the starting and ending points in the case of linear gradient 62 */ FillGradient(FillInterpolator & inter,Gradient & GradientFunction,FillGradientLut & ColorFunction,float distance1,float distance2)63 FillGradient(FillInterpolator& inter, Gradient& GradientFunction, 64 FillGradientLut& ColorFunction, float distance1, float distance2) 65 : interpolator_(&inter), 66 gradientFunction_(&GradientFunction), 67 colorFunction_(&ColorFunction), 68 distance1_(static_cast<int32_t>(distance1 * GRADIENT_SUBPIXEL_SCALE)), 69 distance2_(static_cast<int32_t>(distance2 * GRADIENT_SUBPIXEL_SCALE)) {} 70 Prepare()71 void Prepare() {} 72 73 /** 74 * @brief Generate From colorfunction_ Remove the rgba from the span 75 * @param span First address of scan line to be filled 76 * @param x coordinate-x 77 * @param y coordinate-y 78 * @param len Scan line length 79 */ Generate(Rgba8T * span,int32_t x,int32_t y,uint32_t len)80 void Generate(Rgba8T* span, int32_t x, int32_t y, uint32_t len) 81 { 82 int32_t downscaleShift = FillInterpolator::SUBPIXEL_SHIFT - GRADIENT_SUBPIXEL_SHIFT; 83 interpolator_->Begin(x, y, len); 84 for (; len; --len, ++(*interpolator_), span++) { 85 interpolator_->Coordinates(&x, &y); 86 int32_t index = gradientFunction_->Calculate(x >> downscaleShift, y >> downscaleShift, 87 distance1_, distance2_, colorFunction_->GetSize()); 88 span->red = (*colorFunction_)[index].red; 89 span->green = (*colorFunction_)[index].green; 90 span->blue = (*colorFunction_)[index].blue; 91 span->alpha = (*colorFunction_)[index].alpha; 92 } 93 } 94 private: 95 FillInterpolator* interpolator_; 96 Gradient* gradientFunction_; 97 FillGradientLut* colorFunction_; 98 int32_t distance1_; 99 int32_t distance2_; 100 }; 101 102 103 /** 104 * GradientFunction 105 * @brief The subscript of the current (x, y) ColorFunction array when calculating the radial gradient 106 * @since 1.0 107 * @version 1.0 108 */ 109 class GradientRadialCalculate : public virtual Gradient { 110 public: GradientRadialCalculate()111 GradientRadialCalculate() 112 : endRadius_(HUNDRED_TIMES * GRADIENT_SUBPIXEL_SCALE), dx_(0), dy_(0) 113 { 114 UpdateValues(); 115 } 116 117 /** 118 * @brief GradientRadialCalculate Constructor arguments 119 * @param endRadius End circle radius 120 * @param dx In the x-axis direction, the distance from the end circle center to the start circle center 121 * @param dy In the y-axis direction, the distance from the end circle center to the start circle center 122 */ GradientRadialCalculate(float endRadius,float dx,float dy)123 GradientRadialCalculate(float endRadius, float dx, float dy) 124 : endRadius_(static_cast<int32_t>(endRadius * GRADIENT_SUBPIXEL_SCALE)), 125 dx_(static_cast<int32_t>(dx * GRADIENT_SUBPIXEL_SCALE)), 126 dy_(static_cast<int32_t>(dy * GRADIENT_SUBPIXEL_SCALE)) 127 { 128 UpdateValues(); 129 } 130 131 /** 132 * @brief calculate The subscript of the current (x, y) ColorFunction array 133 * when calculating the radial gradient 134 * @param x coordinate x 135 * @param y coordinate y 136 * @param startRadius Start circle radius 137 * @param endRadius End circle radius 138 * @param size colorFunction_µÄsize 139 * @return 140 */ Calculate(int16_t x,int16_t y,int16_t startRadius,int16_t endRadius,int16_t size)141 int16_t Calculate(int16_t x, int16_t y, int16_t startRadius, int16_t endRadius, int16_t size) 142 { 143 float dx = x - dx_; 144 float dy = y - dy_; 145 float distanceRadius = dx * dy_ - dy * dx_; 146 float radiusDistance = endRadiusSquare_ * (dx * dx + dy * dy) 147 - distanceRadius * distanceRadius; 148 float deltaRadius = endRadius - startRadius; // Difference of radius 149 if (deltaRadius < 1) { 150 deltaRadius = 1; 151 } 152 int16_t index = static_cast<int16_t>((((dx * dx_ + dy * dy_ + 153 Sqrt(fabs(radiusDistance))) 154 * mul_ - startRadius) * size) / deltaRadius); 155 if (index < 0) { 156 index = 0; 157 } 158 if (index >= size) { 159 index = size - 1; 160 } 161 return index; 162 } 163 164 private: 165 /** 166 * @brief update mul_ 167 */ UpdateValues()168 void UpdateValues() 169 { 170 endRadiusSquare_ = float(endRadius_) * float(endRadius_); 171 float dxSquare_ = float(dx_) * float(dx_); 172 float dySquare_ = float(dy_) * float(dy_); 173 float dRadius = (endRadiusSquare_ - (dxSquare_ + dySquare_)); 174 if (dRadius == 0.0f) { 175 if (dx_) { 176 if (dx_ < 0.0f) { 177 ++dx_; 178 } else { 179 --dx_; 180 } 181 } 182 if (dy_) { 183 if (dy_ < 0.0f) { 184 ++dy_; 185 } else { 186 --dy_; 187 } 188 } 189 dxSquare_ = float(dx_) * float(dx_); 190 dySquare_ = float(dy_) * float(dy_); 191 dRadius = (endRadiusSquare_ - (dxSquare_ + dySquare_)); 192 } 193 mul_ = endRadius_ / dRadius; 194 } 195 196 int32_t endRadius_; 197 /** In the x-axis direction, the distance from the end circle center to the start circle center */ 198 int32_t dx_; 199 /** In the y-axis direction, the distance from the end circle center to the start circle center */ 200 int32_t dy_; 201 float endRadiusSquare_; 202 float mul_; 203 }; 204 205 /** 206 * @brief The subscript of the current (x, y) ColorFunction array when calculating a linear gradient 207 * @since 1.0 208 * @version 1.0 209 */ 210 class GradientLinearCalculate : public virtual Gradient { 211 public: 212 /** 213 * @brief The subscript of the current (x, y) ColorFunction array when calculating a linear gradient 214 * @param x coordinate x 215 * @param distance Distance between start and end of linear gradient 216 * @param size color_functionµÄsize 217 * @return 218 */ Calculate(int16_t x,int16_t,int16_t,int16_t distance,int16_t size)219 int16_t Calculate(int16_t x, int16_t, int16_t, int16_t distance, int16_t size) 220 { 221 if (distance < 1) { 222 distance = 1; 223 } 224 int16_t index = (x * size) / distance; 225 if (index < 0) { 226 index = 0; 227 } 228 if (index >= size) { 229 index = size - 1; 230 } 231 return index; 232 } 233 #endif 234 }; 235 } // namespace OHOS 236 #endif 237