1 /* 2 * Copyright (c) 2021-2021 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 GRAPHIC_LITE_CLIP_UTILS_H 17 #define GRAPHIC_LITE_CLIP_UTILS_H 18 19 #include "gfx_utils/geometry2d.h" 20 #include "gfx_utils/image_info.h" 21 #include "gfx_utils/list.h" 22 #include "gfx_utils/vector.h" 23 24 namespace OHOS { 25 /* Indicates an interval with the same transparency */ 26 struct Span : public HeapBase { 27 int16_t left; 28 int16_t right; 29 uint8_t opa; 30 }; 31 32 /* Indicates a point in float */ 33 struct PointF { 34 float x; 35 float y; 36 }; 37 38 /* Indicates a rectangle in flaot */ 39 struct RectF { 40 float left; 41 float top; 42 float right; 43 float bottom; 44 }; 45 46 /* Indicates an edge */ 47 struct Edge : public HeapBase { 48 /* The maximum y coordinate of the edge */ 49 int16_t ymax; 50 /* The minimum y coordinate of the edge */ 51 int16_t ymin; 52 /* The x-coordinate of the intersection with the current row */ 53 float x; 54 /* Increment of x-coordinate when y-coordinate increases by 1 */ 55 float dx; 56 }; 57 58 /* Indicates an edge that to be antialiased */ 59 struct AAEdge : public HeapBase { 60 /* The y-coordinate of current integer x-coordinate */ 61 float y; 62 /* Increment of y-coordinate when x-coordinate step by sx */ 63 float dy; 64 /* Current integer x-coordinate */ 65 int16_t x; 66 /* Step of x, 1 or -1 */ 67 int16_t sx; 68 /* Upper limit of steps */ 69 int16_t xIndex; 70 }; 71 72 /* Indicates a cubic Bezier curve */ 73 struct Spline : public HeapBase { 74 /* Start point */ 75 PointF a; 76 /* First control point */ 77 PointF b; 78 /* Second control point */ 79 PointF c; 80 /* End point */ 81 PointF d; 82 }; 83 84 enum ClipPathCmd { 85 CMD_MOVE_TO, 86 CMD_LINE_TO, 87 CMD_CURVE_TO, 88 }; 89 90 class ClipPolygon : public HeapBase { 91 public: ClipPolygon()92 ClipPolygon() {} ~ClipPolygon()93 ~ClipPolygon() 94 { 95 Clear(); 96 } 97 Clear()98 void Clear() 99 { 100 points_.Clear(); 101 bound_ = {0, 0, 0, 0}; 102 } 103 AddPoint(const PointF & p)104 void AddPoint(const PointF& p) 105 { 106 if (points_.IsEmpty()) { 107 bound_.left = p.x; 108 bound_.right = p.x; 109 bound_.top = p.y; 110 bound_.bottom = p.y; 111 points_.PushBack(p); 112 } else if (!MATH_FLT_EQUAL(points_.Back().x, p.x) || !MATH_FLT_EQUAL(points_.Back().y, p.y)) { 113 bound_.left = (p.x < bound_.left) ? p.x : bound_.left; 114 bound_.top = (p.y < bound_.top) ? p.y : bound_.top; 115 bound_.right = (p.x > bound_.right) ? p.x : bound_.right; 116 bound_.bottom = (p.y > bound_.bottom) ? p.y : bound_.bottom; 117 points_.PushBack(p); 118 } 119 } 120 121 Graphic::Vector<PointF> points_; 122 RectF bound_ = {0, 0, 0, 0}; 123 }; 124 125 /* 126 * Indicates a path to be cliped. 127 * Note: The path will be automatically closed. Only non-self-intersecting path are supported. 128 */ 129 class ClipPath : public HeapBase { 130 public: ClipPath()131 ClipPath() {} ~ClipPath()132 ~ClipPath() 133 { 134 points_.Clear(); 135 cmd_.Clear(); 136 } 137 void GeneratePolygon(ClipPolygon& polygon) const; 138 139 ClipPath& MoveTo(const PointF& point); 140 ClipPath& LineTo(const PointF& point); 141 ClipPath& CurveTo(const PointF& control1, const PointF& control2, const PointF& end); 142 ClipPath& Arc(const PointF& center, float radius, int16_t startAngle, int16_t endAngle); 143 ClipPath& Circle(const PointF& center, float radius); 144 145 private: 146 bool CheckoutSplineError(const Spline& spline) const; 147 void MidPointOfLine(const PointF& a, const PointF& b, PointF& mid) const; 148 void SplitSpline(Spline& s1, Spline& s2) const; 149 void SplineDecompose(Spline& s, ClipPolygon& polygon) const; 150 151 void ArcInner(const PointF& center, float radius, int16_t startAngle, int16_t endAngle); 152 153 List<PointF> points_; 154 List<ClipPathCmd> cmd_; 155 PointF startPos_ = {0, 0}; 156 }; 157 158 /* 159 * Blitter and its subclasses are responible for handling the span list and actually draws the pixels 160 */ 161 class Blitter : public HeapBase { 162 public: Blitter()163 Blitter() {} ~Blitter()164 virtual ~Blitter() {} 165 DrawHorSpan(const List<Span> & span,int16_t yCur)166 virtual void DrawHorSpan(const List<Span>& span, int16_t yCur) {} Finish()167 virtual void Finish() {} 168 }; 169 170 /* Clipimageblitter will clip the image on its original memory */ 171 class ClipImageBlitter : public Blitter { 172 public: ClipImageBlitter(const ImageInfo * src)173 explicit ClipImageBlitter(const ImageInfo* src) : src_(src) {} ~ClipImageBlitter()174 virtual ~ClipImageBlitter() {} 175 176 void DrawHorSpan(const List<Span>& span, int16_t yCur) override; 177 void Finish() override; 178 private: 179 void DrawPixel(int16_t x, int16_t y, uint8_t opa); 180 void DrawHorLine(int16_t x, int16_t y, int16_t width, uint8_t opa); 181 182 const ImageInfo* src_ = nullptr; 183 int16_t iy_ = 0; 184 }; 185 186 class ClipUtils : public HeapBase { 187 public: ClipUtils()188 ClipUtils() {} ~ClipUtils()189 ~ClipUtils() {} 190 191 void PerformScan(const ClipPath& path, Blitter& blitter); 192 private: 193 void ClearSpanTable(); 194 195 void CreateNewSpan(List<Span>& list, ListNode<Span>* node, int16_t left, int16_t right, uint8_t opa); 196 void InsertSpan(List<Span>& curList, int16_t left, int16_t right, uint8_t opa); 197 void MergeSpan(List<Span>& s); 198 199 void CreateEdgeList(const ClipPath& path); 200 void DrawAntiAliasedPoints(int16_t yCur); 201 202 /* Save the lines that needs to be scanned vertically */ 203 List<Edge> edgeList_; 204 /* Save the non steep lines that need to be antialiased */ 205 List<AAEdge> aaList_; 206 /* Pointer to the span of the current row */ 207 List<Span>* span0_ = nullptr; 208 /* Pointer to the span of the next row */ 209 List<Span>* span1_ = nullptr; 210 211 int16_t minY_ = INT16_MAX; 212 int16_t maxY_ = INT16_MIN; 213 }; 214 }; 215 #endif