1 /* 2 * Copyright (c) 2025 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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_PICKER_PAINT_METHOD_UTILS_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_PICKER_PAINT_METHOD_UTILS_H 18 19 #include "base/geometry/ng/size_t.h" 20 #include "base/memory/ace_type.h" 21 #include "base/memory/referenced.h" 22 #include "base/utils/macros.h" 23 #include "base/utils/utils.h" 24 #include "core/components_ng/render/divider_painter.h" 25 #include "core/components_ng/render/node_paint_method.h" 26 #include "core/components/common/properties/color.h" 27 #include "core/components/picker/picker_theme.h" 28 #include "core/components_ng/pattern/time_picker/timepicker_layout_property.h" 29 #include "core/components_ng/pattern/picker/datepicker_row_layout_property.h" 30 #include "core/components_ng/render/drawing_prop_convertor.h" 31 #include "core/pipeline_ng/pipeline_context.h" 32 33 namespace OHOS::Ace::NG { 34 constexpr int32_t CONST_AVERAGE = 2; 35 constexpr int32_t BACKGROUND_HIGH = 12; 36 constexpr uint32_t SELECTED_ROW_BACKGROUND_COLOR = 0x33FFFFFF; 37 constexpr double CONST_HALF_VALUE = 2.0; 38 constexpr int32_t CONST_DELTA_STEP = 1; 39 constexpr int32_t CONST_LINE_DIFF = 1; 40 41 class PickerPaintMethodCircleUtils { 42 public: PickerPaintMethodCircleUtils()43 PickerPaintMethodCircleUtils() {} 44 ~PickerPaintMethodCircleUtils()45 virtual ~PickerPaintMethodCircleUtils() {} 46 47 template<class T> GetContentDrawFunctionL(PaintWrapper * paintWrapper,const RefPtr<PipelineBase> & pipeline)48 CanvasDrawFunction GetContentDrawFunctionL(PaintWrapper* paintWrapper, const RefPtr<PipelineBase>& pipeline) 49 { 50 CHECK_NULL_RETURN(paintWrapper, nullptr); 51 CHECK_NULL_RETURN(pipeline, nullptr); 52 auto theme = pipeline->GetTheme<PickerTheme>(); 53 CHECK_NULL_RETURN(theme, nullptr); 54 auto dividerSpacing = pipeline->NormalizeToPx(theme->GetDividerSpacing()); 55 const auto& geometryNode = paintWrapper->GetGeometryNode(); 56 CHECK_NULL_RETURN(geometryNode, nullptr); 57 auto frameRect = geometryNode->GetFrameRect(); 58 auto renderContext = paintWrapper->GetRenderContext(); 59 CHECK_NULL_RETURN(renderContext, nullptr); 60 auto pickerNode = renderContext->GetHost(); 61 CHECK_NULL_RETURN(pickerNode, nullptr); 62 auto layoutProperty = pickerNode->GetLayoutProperty<T>(); 63 CHECK_NULL_RETURN(layoutProperty, nullptr); 64 65 Color paintcolor(SELECTED_ROW_BACKGROUND_COLOR); 66 if (theme->GetOptionDecoration(false)) { 67 paintcolor = theme->GetOptionDecoration(false)->GetBackgroundColor(); 68 } 69 70 return [layoutProperty, frameRect, dividerSpacing, paintcolor](RSCanvas& canvas) { 71 PaddingPropertyF padding = layoutProperty->CreatePaddingAndBorder(); 72 RectF contentRect = { padding.left.value_or(0), padding.top.value_or(0), 73 frameRect.Width() - padding.Width(), frameRect.Height() - padding.Height() }; 74 if (GreatOrEqual(contentRect.Height(), dividerSpacing)) { 75 double upperLine = (contentRect.Height() - dividerSpacing) / CONST_HALF_VALUE + contentRect.GetY(); 76 double downLine = (contentRect.Height() + dividerSpacing) / CONST_HALF_VALUE + contentRect.GetY(); 77 DrawCapsule(upperLine, downLine, contentRect.Width(), BACKGROUND_HIGH, paintcolor, canvas); 78 } 79 }; 80 } 81 82 protected: checkRepeat(std::vector<int32_t> & vec,int32_t _x,int32_t _y,int32_t up)83 static void checkRepeat(std::vector<int32_t>& vec, int32_t _x, int32_t _y, int32_t up) 84 { 85 if (vec[_y - up] < _x) { 86 vec[_y - up] = _x; 87 } 88 } 89 DrawCapsule(int32_t up,int32_t down,int32_t width,int32_t margins,const Color & paintcolor,RSCanvas & canvas)90 static void DrawCapsule(int32_t up, int32_t down, int32_t width, int32_t margins, const Color &paintcolor, 91 RSCanvas& canvas) 92 { 93 int32_t radius = (down - up) / CONST_AVERAGE; 94 int32_t leftXc = margins + radius; 95 int32_t rightXc = width - radius - margins; 96 int32_t yC = up + radius; 97 98 int32_t x = 0; 99 int32_t y = radius; 100 int32_t delta = CONST_AVERAGE - CONST_AVERAGE * radius; 101 const double penWidth = 1.0; 102 103 RSPen pen; 104 pen.SetColor(paintcolor.GetValue()); 105 pen.SetWidth(penWidth); 106 canvas.AttachPen(pen); 107 108 // draw the capsule algorithm 109 std::vector<int32_t> xOffset(down - up + CONST_LINE_DIFF); 110 std::fill(xOffset.begin(), xOffset.end(), 0); 111 while (x <= y) { 112 checkRepeat(xOffset, x, yC + y, up); 113 checkRepeat(xOffset, x, yC - y, up); 114 checkRepeat(xOffset, y, yC + x, up); 115 checkRepeat(xOffset, y, yC - x, up); 116 117 if (delta > 0) { 118 delta += CONST_AVERAGE * (x - y) + CONST_DELTA_STEP; 119 y--; 120 } else { 121 delta += CONST_AVERAGE * x + CONST_DELTA_STEP; 122 } 123 x++; 124 } 125 for (int y = up; y <= down; y++) { 126 canvas.DrawLine(RSPoint(leftXc - xOffset[y - up], y), RSPoint(rightXc + xOffset[y - up], y)); 127 } 128 canvas.DetachPen(); 129 } 130 }; 131 } 132 #endif 133