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 #include "gfx_utils/diagram/rasterizer/rasterizer_cells_antialias.h"
17 #include "gfx_utils/graphic_log.h"
18 #include "securec.h"
19 
20 namespace OHOS {
~RasterizerCellsAntiAlias()21 RasterizerCellsAntiAlias::~RasterizerCellsAntiAlias()
22 {
23     if (numBlocks_) {
24         CellBuildAntiAlias** ptr = cells_ + numBlocks_ - 1;
25         while (numBlocks_--) {
26             GeometryArrayAllocator<CellBuildAntiAlias>::Deallocate(*ptr, CELL_BLOCK_SIZE);
27             ptr--;
28         }
29         GeometryArrayAllocator<CellBuildAntiAlias*>::Deallocate(cells_, maxBlocks_);
30         GeometryArrayAllocator<CellBuildAntiAlias*>::Deallocate(sortedCells_, numCells_ + CELLS_SIZE);
31         GeometryArrayAllocator<SortedYLevel>::Deallocate(sortedY_, maxY_ - minY_ + 1 + CELLS_SIZE);
32     }
33 }
34 
35 /**
36  * @brief RasterizerCellsAntiAlias Class constructor
37  * initialization numBlocks_,maxBlocks_,currBlock_ Other attributes
38  * @since 1.0
39  * @version 1.0
40  */
RasterizerCellsAntiAlias(uint32_t cellBlockLimit)41 RasterizerCellsAntiAlias::RasterizerCellsAntiAlias(uint32_t cellBlockLimit)
42     : numBlocks_(0),
43       maxBlocks_(0),
44       currBlock_(0),
45       numCells_(0),
46       cellBlockLimit_(cellBlockLimit),
47       cells_(0),
48       currCellPtr_(0),
49       sortedCells_(nullptr),
50       sortedY_(nullptr),
51       minX_(INT32_MAX),
52       minY_(INT32_MAX),
53       maxX_(INT32_MIN),
54       maxY_(INT32_MIN),
55       sorted_(false)
56 {
57     styleCell_.Initial();
58     currCell_.Initial();
59 }
60 
61 /**
62  * Reinitialize settings numBlocks_,maxBlocks_,currBlock_ and other attributes.
63  * @since 1.0
64  * @version 1.0
65  */
Reset()66 void RasterizerCellsAntiAlias::Reset()
67 {
68     numCells_ = 0;
69     currBlock_ = 0;
70     currCell_.Initial();
71     styleCell_.Initial();
72     sorted_ = false;
73     minX_ = INT32_MAX;
74     minY_ = INT32_MAX;
75     maxX_ = INT32_MIN;
76     maxY_ = INT32_MIN;
77 }
78 
79 /**
80  * @brief Add the current cell during rasterization.
81  * @since 1.0
82  * @version 1.0
83  */
AddCurrentCell()84 void RasterizerCellsAntiAlias::AddCurrentCell()
85 {
86     bool areaCoverFlags = currCell_.area | currCell_.cover;
87     if (areaCoverFlags) {
88         // Reach CELL_BLOCK_MASK After the number of mask, re allocate memory
89         if ((numCells_ & CELL_BLOCK_MASK) == 0) {
90             // Exceeds the memory block size limit. The default is 1024 limit
91             if (numBlocks_ >= cellBlockLimit_) {
92                 return;
93             }
94             AllocateBlock();
95         }
96         *currCellPtr_++ = currCell_;
97         ++numCells_;
98     }
99 }
100 
101 /**
102  * @brief Set the current cell during rasterization.
103  * @since 1.0
104  * @version 1.0
105  */
SetCurrentCell(int32_t x,int32_t y)106 inline void RasterizerCellsAntiAlias::SetCurrentCell(int32_t x, int32_t y)
107 {
108     if (currCell_.NotEqual(x, y, styleCell_)) {
109         AddCurrentCell();
110         currCell_.Style(styleCell_);
111         currCell_.x = x;
112         currCell_.y = y;
113         currCell_.cover = 0;
114         currCell_.area = 0;
115     }
116 }
117 
OutLineLegal(int32_t x1,int32_t y1,int32_t x2,int32_t y2)118 void RasterizerCellsAntiAlias::OutLineLegal(int32_t x1, int32_t y1, int32_t x2, int32_t y2)
119 {
120     /**
121      * outline range
122      */
123     if (x1 < minX_) {
124         minX_ = x1;
125     }
126     if (x1 > maxX_) {
127         maxX_ = x1;
128     }
129     if (y1 < minY_) {
130         minY_ = y1;
131     }
132     if (y1 > maxY_) {
133         maxY_ = y1;
134     }
135     if (x2 < minX_) {
136         minX_ = x2;
137     }
138     if (x2 > maxX_) {
139         maxX_ = x2;
140     }
141     if (y2 < minY_) {
142         minY_ = y2;
143     }
144     if (y2 > maxY_) {
145         maxY_ = y2;
146     }
147 }
148 
149 /**
150  * @brief In the rasterization process, according to the coordinate height value of ey,
151  * x1 to x2 in 1 / 256 pixel horizontally,
152  * The filling process of cell cells longitudinally from sub-pixel mask y1 to sub-pixel mask y2.
153  * @since 1.0
154  * @version 1.0
155  */
RenderHorizonline(int32_t ey,int32_t x1,int32_t polySubpixelMaskY1,int32_t x2,int32_t polySubpixelMaskY2)156 void RasterizerCellsAntiAlias::RenderHorizonline(
157     int32_t ey, int32_t x1, int32_t polySubpixelMaskY1, int32_t x2, int32_t polySubpixelMaskY2)
158 {
159     /**
160      * Take out the mask value of the last 8 bits, namely the color mask,
161      * from the points in units of 1 / 256 pixels
162      */
163     int32_t submaskFlagsX1 = x1 & POLY_SUBPIXEL_MASK;
164     int32_t submaskFlagsX2 = x2 & POLY_SUBPIXEL_MASK;
165     /**
166      * The coordinates of the first 24 bits are extracted from the points in units of 1 / 256 pixels
167      */
168     int32_t pixelX1 = x1 >> POLY_SUBPIXEL_SHIFT;
169     int32_t pixelX2 = x2 >> POLY_SUBPIXEL_SHIFT;
170 
171     int32_t delta, deltayMask, first;
172     int64_t dx;
173     int32_t increase, modDxMask;
174     /**
175      * The color mask of the two points is the same. Add the settings directly and return.
176      */
177     if (polySubpixelMaskY2 == polySubpixelMaskY1) {
178         SetCurrentCell(pixelX2, ey);
179         return;
180     }
181 
182     // The pixel coordinates of the two points are the same and are directly calculated as a cell.
183     if (pixelX1 == pixelX2) {
184         delta = polySubpixelMaskY2 - polySubpixelMaskY1;
185         currCell_.cover += delta;
186         currCell_.area += (submaskFlagsX1 + submaskFlagsX2) * delta;
187         return;
188     }
189     // hline At the beginning of the process, the cells area adjacent to the same organization is rendered
190     first = POLY_SUBPIXEL_SCALE;
191     increase = 1;
192     /**  Convert from submaskFlagsX1 to POLY_SUBPIXEL_SCALE to calculate deltax * deltay */
193     deltayMask = (POLY_SUBPIXEL_SCALE - submaskFlagsX1) * (polySubpixelMaskY2 - polySubpixelMaskY1);
194     dx = (long long)x2 - (long long)x1;
195     if (dx < 0) {
196         first = 0;
197         increase = -1;
198         dx = -dx;
199         deltayMask = submaskFlagsX1 * (polySubpixelMaskY2 - polySubpixelMaskY1);
200     }
201     delta = static_cast<int32_t>(deltayMask / dx);
202     modDxMask = static_cast<int32_t>(deltayMask % dx);
203     if (modDxMask < 0) {
204         modDxMask += dx;
205         delta--;
206     }
207     /* submaskFlagsX1+ (0->first) */
208     currCell_.area += (submaskFlagsX1 + first) * delta;
209     currCell_.cover += delta;
210     pixelX1 += increase;
211     SetCurrentCell(pixelX1, ey);
212     polySubpixelMaskY1 += delta;
213     if (pixelX1 != pixelX2) {
214         /* delta_subpixel x( 0 to POLY_SUBPIXEL_SCALE)  to ( delta_subpixel_scale_y + delta) */
215         deltayMask = POLY_SUBPIXEL_SCALE * (polySubpixelMaskY2 - polySubpixelMaskY1 + delta);
216         int32_t remDxMask = static_cast<int32_t>(deltayMask % dx);
217         int32_t liftDxMask = static_cast<int32_t>(deltayMask / dx);
218         if (remDxMask < 0) {
219             liftDxMask--;
220             remDxMask += dx;
221         }
222         modDxMask -= dx;
223         while (pixelX1 != pixelX2) {
224             delta = liftDxMask;
225             modDxMask += remDxMask;
226             if (modDxMask >= 0) {
227                 modDxMask -= dx;
228                 delta++;
229             }
230             currCell_.area += POLY_SUBPIXEL_SCALE * delta;
231             currCell_.cover += delta;
232             polySubpixelMaskY1 += delta;
233             pixelX1 += increase;
234             SetCurrentCell(pixelX1, ey);
235         }
236     }
237     delta = polySubpixelMaskY2 - polySubpixelMaskY1;
238     currCell_.cover += delta;
239     /* From first to POLY_SUBPIXEL_SCALE procedure */
240     currCell_.area += (submaskFlagsX2 + POLY_SUBPIXEL_SCALE - first) * delta;
241 }
242 
SetStyle(const CellBuildAntiAlias & styleCell)243 inline void RasterizerCellsAntiAlias::SetStyle(const CellBuildAntiAlias& styleCell)
244 {
245     styleCell_.Style(styleCell);
246 }
247 
248 /**
249  * @brief According to the incoming 2 coordinate points (both with sub pixels),
250  * The process of constructing rasterized cell points is from y to X.
251  * @since 1.0
252  * @version 1.0
253  */
LineOperate(int32_t x1,int32_t y1,int32_t x2,int32_t y2)254 void RasterizerCellsAntiAlias::LineOperate(int32_t x1, int32_t y1, int32_t x2, int32_t y2)
255 {
256     int64_t dx = static_cast<int64_t>(x2) - static_cast<int64_t>(x1);
257     /**
258      * If dx exceeds the limit, a compromise is adopted to calculate the line.
259      */
260     if (dx >= DX_LIMIT || dx <= -DX_LIMIT) {
261         int32_t cx = static_cast<int32_t>(((int64_t)x1 + (int64_t)x2) >> 1);
262         int32_t cy = static_cast<int32_t>(((int64_t)y1 + (int64_t)y2) >> 1);
263         LineOperate(x1, y1, cx, cy);
264         LineOperate(cx, cy, x2, y2);
265         return;
266     }
267     /**
268      * The coordinates of the first 24 bits are extracted from the points in units of 1 / 256 pixels
269      */
270     int64_t dy = (int64_t)y2 - (int64_t)y1;
271     int32_t ex1 = x1 >> POLY_SUBPIXEL_SHIFT;
272     int32_t ex2 = x2 >> POLY_SUBPIXEL_SHIFT;
273     int32_t ey1 = y1 >> POLY_SUBPIXEL_SHIFT;
274     int32_t ey2 = y2 >> POLY_SUBPIXEL_SHIFT;
275     /**
276      * Take out the mask value of the last 8 bits from
277      * the points with 1 / 256 pixel as the unit, that is, the color mask
278      */
279     int32_t submaskFlagsY1 = y1 & POLY_SUBPIXEL_MASK;
280     int32_t submaskFlagsY2 = y2 & POLY_SUBPIXEL_MASK;
281 
282     int32_t xFrom;
283     int32_t modDyMask, delta, first, increase;
284     int64_t deltaxMask;
285 
286     OutLineLegal(ex1, ey1, ex2, ey2);
287     SetCurrentCell(ex1, ey1);
288 
289     /**
290      * If the Y values of the two points are the same, they will be directly rendered horizontally,
291      * The horizontal coordinate spacing is from X1 - > x2 in 1 / 256 pixels,
292      * Color mask spacing is from submaskFlagsY1 to submaskFlagsY2
293      */
294     if (ey1 == ey2) {
295         RenderHorizonline(ey1, x1, submaskFlagsY1, x2, submaskFlagsY2);
296         return;
297     }
298     /**
299      * For the processing of vertical lines, start - > end cells are calculated, and then the line is calculated
300      * The above general attribute area - > cover is for each y value,
301      * There is only one cell, so it is no longer called RenderHorizonline()
302      */
303     increase = 1;
304     if (dx == 0) {
305         RenderVerticalLine(x1, ex1, dy, first, increase, xFrom, submaskFlagsY1, submaskFlagsY2, ey1, ey2, delta);
306         return;
307     }
308     /**
309      * The color mask is from the color mask to submaskFlagsY1 to POLY_SUBPIXEL_SCALE Process of scale
310      */
311     deltaxMask = (POLY_SUBPIXEL_SCALE - submaskFlagsY1) * dx;
312     first = POLY_SUBPIXEL_SCALE;
313     if (dy < 0) {
314         deltaxMask = submaskFlagsY1 * dx;
315         first = 0;
316         increase = -1;
317         dy = -dy;
318     }
319     delta = static_cast<int32_t>(deltaxMask / dy);
320     modDyMask = static_cast<int32_t>(deltaxMask % dy);
321     if (modDyMask < 0) {
322         delta--;
323     }
324     xFrom = x1 + delta;
325     RenderHorizonline(ey1, x1, submaskFlagsY1, xFrom, first);
326     ey1 += increase;
327     SetCurrentCell(xFrom >> POLY_SUBPIXEL_SHIFT, ey1);
328     if (ey1 != ey2) {
329         RenderObliqueLine(dx, dy, first, increase, xFrom, deltaxMask, ey1, ey2, delta);
330     }
331     RenderHorizonline(ey1, xFrom, POLY_SUBPIXEL_SCALE - first, x2, submaskFlagsY2);
332 }
333 
RenderVerticalLine(int32_t & x1,int32_t & ex1,int64_t & dy,int32_t & first,int32_t & increase,int32_t & xFrom,int32_t & submaskFlagsY1,int32_t & submaskFlagsY2,int32_t & ey1,int32_t & ey2,int32_t & delta)334 void RasterizerCellsAntiAlias::RenderVerticalLine(int32_t& x1, int32_t& ex1, int64_t& dy, int32_t& first,
335                                                   int32_t& increase, int32_t& xFrom, int32_t& submaskFlagsY1,
336                                                   int32_t& submaskFlagsY2, int32_t& ey1, int32_t& ey2, int32_t& delta)
337 {
338     /**
339      * The coordinates of the first 24 bits are extracted from the points in units of 1 / 256 pixels
340      */
341     /* Take out the number of decimal points and occupy 2 spaces */
342     int32_t twoFx = (x1 - (ex1 << POLY_SUBPIXEL_SHIFT)) << 1;
343     int32_t area;
344     /* 256 */
345     first = POLY_SUBPIXEL_SCALE;
346     if (dy < 0) {
347         first = 0;
348         increase = -1;
349     }
350     xFrom = x1;
351     /* From submaskFlagsY1 to first process */
352     /* The color mask is from submaskFlagsY1->first */
353     delta = first - submaskFlagsY1;
354     currCell_.cover += delta;
355     currCell_.area += twoFx * delta;
356     ey1 += increase;
357     SetCurrentCell(ex1, ey1);
358     /* The color mask is from (poly_subpixel_scale - first) -> first */
359     delta = first + first - POLY_SUBPIXEL_SCALE;
360     area = twoFx * delta;
361     while (ey1 != ey2) {
362         /* from poly_subpixel_scale - first to  first */
363         currCell_.cover = delta;
364         currCell_.area = area;
365         ey1 += increase;
366         SetCurrentCell(ex1, ey1);
367     }
368     /* The color mask is from poly_subpixel_scale - first to  submaskFlagsY2 */
369     delta = submaskFlagsY2 - POLY_SUBPIXEL_SCALE + first;
370     currCell_.cover += delta;
371     currCell_.area += twoFx * delta;
372 }
373 
RenderObliqueLine(int64_t & dx,int64_t & dy,int32_t & first,int32_t & increase,int32_t & xFrom,int64_t & deltaxMask,int32_t & ey1,int32_t & ey2,int32_t & delta)374 void RasterizerCellsAntiAlias::RenderObliqueLine(int64_t& dx, int64_t& dy, int32_t& first,
375                                                  int32_t& increase, int32_t& xFrom, int64_t& deltaxMask,
376                                                  int32_t& ey1, int32_t& ey2, int32_t& delta)
377 {
378     int32_t remDyMask, liftDyMask;
379     deltaxMask = POLY_SUBPIXEL_SCALE * dx;
380     liftDyMask = static_cast<int32_t>(deltaxMask / dy);
381     remDyMask = static_cast<int32_t>(deltaxMask % dy);
382     if (remDyMask < 0) {
383         liftDyMask--;
384         remDyMask += dy;
385     }
386     int32_t modDyMask = -dy;
387     while (ey1 != ey2) {
388         delta = liftDyMask;
389         modDyMask += remDyMask;
390         if (modDyMask >= 0) {
391             modDyMask -= dy;
392             delta++;
393         }
394         int32_t xTo = xFrom + delta;
395         RenderHorizonline(ey1, xFrom, POLY_SUBPIXEL_SCALE - first, xTo, first);
396         xFrom = xTo;
397         ey1 += increase;
398         SetCurrentCell(xFrom >> POLY_SUBPIXEL_SHIFT, ey1);
399     }
400 }
401 
402 /**
403  * @brief Allocate array space for cells during rasterization.
404  * @since 1.0
405  * @version 1.0
406  */
AllocateBlock()407 void RasterizerCellsAntiAlias::AllocateBlock()
408 {
409     if (currBlock_ >= numBlocks_) {
410         if (numBlocks_ >= maxBlocks_) {
411             CellBuildAntiAlias** newCells =
412                 GeometryArrayAllocator<CellBuildAntiAlias*>::Allocate(maxBlocks_ +
413                                                             CELL_BLOCK_POOL);
414             if (newCells == nullptr) {
415                 return;
416             }
417             if (cells_) {
418                 if (memcpy_s(newCells, maxBlocks_ * sizeof(CellBuildAntiAlias*),
419                              cells_, maxBlocks_ * sizeof(CellBuildAntiAlias*)) != EOK) {
420                     GRAPHIC_LOGE("RasterizerCellsAntiAlias::AllocateBlock memcpy_s fail\n");
421                     return;
422                 }
423                 GeometryArrayAllocator<CellBuildAntiAlias*>::Deallocate(cells_, maxBlocks_);
424             }
425             cells_ = newCells;
426             maxBlocks_ += CELL_BLOCK_POOL;
427         }
428         cells_[numBlocks_++] = GeometryArrayAllocator<CellBuildAntiAlias>::Allocate(CELL_BLOCK_SIZE);
429     }
430 
431     currCellPtr_ = cells_[currBlock_++];
432 }
433 /**
434  * @brief In the rasterization process, all cells are rasterized according to
435  * Sort from left to right and from top to bottom.
436  * @since 1.0
437  * @version 1.0
438  */
SortAllCells()439 void RasterizerCellsAntiAlias::SortAllCells()
440 {
441     if (sorted_) {
442         return; // Perform sort only the first time.
443     }
444 
445     AddCurrentCell();
446     currCell_.x = INT32_MAX;
447     currCell_.y = INT32_MAX;
448     currCell_.cover = 0;
449     currCell_.area = 0;
450     if (numCells_ == 0) {
451         return;
452     }
453 
454     // Allocate the array of cell pointers
455     sortedCells_ = GeometryArrayAllocator<CellBuildAntiAlias*>::Allocate(numCells_ + CELLS_SIZE);
456 
457     // Allocate and zero the Y array
458     uint32_t sortedYSize = maxY_ - minY_ + 1;
459     sortedY_ = GeometryArrayAllocator<SortedYLevel>::Allocate(sortedYSize + CELLS_SIZE);
460     if (sortedYSize > INT32_MIN) {
461         GRAPHIC_LOGE("sortedYSize size fail");
462     }
463     if (memset_s(sortedY_, sizeof(SortedYLevel) * sortedYSize, 0, sizeof(SortedYLevel) * sortedYSize) != EOK) {
464         GRAPHIC_LOGE("CleanData fail");
465     }
466 
467     // Create the Y-histogram (count the numbers of cells for each Y)
468     CellBuildAntiAlias** blockPtr = cells_;
469     CellBuildAntiAlias* cellPtr = nullptr;
470     uint32_t nb = numCells_;
471     uint32_t i = 0;
472     while (nb) {
473         cellPtr = *blockPtr++;
474         i = (nb > CELL_BLOCK_SIZE) ? uint32_t(CELL_BLOCK_SIZE) : nb;
475         nb -= i;
476         if (((cellPtr->y - minY_) < 0) || ((cellPtr->y - minY_) > (sortedYSize + CELLS_SIZE))) {
477             continue;
478         }
479 
480         while (i--) {
481             sortedY_[cellPtr->y - minY_].start++;
482             ++cellPtr;
483         }
484     }
485 
486     // Convert the Y-histogram into the array of starting indexes
487     uint32_t start = 0;
488     for (i = 0; i < sortedYSize; i++) {
489         uint32_t v = sortedY_[i].start;
490         sortedY_[i].start = start;
491         start += v;
492     }
493 
494     // Fill the cell pointer array sorted by Y
495     blockPtr = cells_;
496     nb = numCells_;
497     while (nb) {
498         cellPtr = *blockPtr++;
499         i = (nb > CELL_BLOCK_SIZE) ? uint32_t(CELL_BLOCK_SIZE) : nb;
500         nb -= i;
501         while (i--) {
502             SortedYLevel& currY = sortedY_[cellPtr->y - minY_];
503             sortedCells_[currY.start + currY.num] = cellPtr;
504             ++currY.num;
505             ++cellPtr;
506         }
507     }
508 
509     // Finally arrange the X-arrays
510     for (i = 0; i < sortedYSize; i++) {
511         const SortedYLevel& currY = sortedY_[i];
512         if (currY.num) {
513             QsortCells(sortedCells_ + currY.start, currY.num);
514         }
515     }
516     sorted_ = true;
517 }
518 
QsortCellsSweep(CellBuildAntiAlias *** base,CellBuildAntiAlias *** iIndex,CellBuildAntiAlias *** jIndex)519 void QsortCellsSweep(CellBuildAntiAlias*** base, CellBuildAntiAlias*** iIndex, CellBuildAntiAlias*** jIndex)
520 {
521     /**
522      * Sorting guarantees the value of * i < = * the value of base < = * the value of j
523      */
524     if ((**jIndex)->x < (**iIndex)->x) {
525         SwapCells(*iIndex, *jIndex);
526     }
527 
528     if ((**base)->x < (**iIndex)->x) {
529         SwapCells(*base, *iIndex);
530     }
531 
532     if ((**jIndex)->x < (**base)->x) {
533         SwapCells(*base, *jIndex);
534     }
535 
536     while (true) {
537         int32_t x = (**base)->x;
538         do {
539             (*iIndex)++;
540         } while ((**iIndex)->x < x);
541         do {
542             (*jIndex)--;
543         } while (x < (**jIndex)->x);
544 
545         if ((*iIndex) > (*jIndex)) {
546             break;
547         }
548         SwapCells(*iIndex, *jIndex);
549     }
550 }
551 
QsortCells(CellBuildAntiAlias ** start,uint32_t num)552 void QsortCells(CellBuildAntiAlias** start, uint32_t num)
553 {
554     const int32_t QSORT_THRESHOLD = 9;
555     const int32_t stackSize = 80;
556     CellBuildAntiAlias** stack[stackSize];
557     CellBuildAntiAlias*** top;
558     CellBuildAntiAlias** limit;
559     CellBuildAntiAlias** base;
560 
561     limit = start + num;
562     base = start;
563     top = stack;
564 
565     while (true) {
566         int32_t len = int32_t(limit - base);
567 
568         CellBuildAntiAlias** iIndex;
569         CellBuildAntiAlias** jIndex;
570 
571         if (len > QSORT_THRESHOLD) {
572             /**
573              * First exchange base + len / 2 as the pivot
574              */
575             CellBuildAntiAlias** pivot = base + len / TWO_TIMES;
576             SwapCells(base, pivot);
577 
578             iIndex = base + 1;
579             jIndex = limit - 1;
580 
581             QsortCellsSweep(&base, &iIndex, &jIndex);
582             SwapCells(base, jIndex);
583             if (jIndex - base > limit - iIndex) {
584                 top[0] = base;
585                 top[1] = jIndex;
586                 base = iIndex;
587             } else {
588                 top[0] = iIndex;
589                 top[1] = limit;
590                 limit = jIndex;
591             }
592             top += TWO_STEP;
593         } else {
594             /**
595              * When the sub-array becomes smaller, insert sort is performed using
596              */
597             jIndex = base;
598             iIndex = jIndex + 1;
599             QsortCellsFor(&iIndex, &jIndex, &limit, &base);
600             if (top > stack) {
601                 top -= TWO_STEP;
602                 base = top[0];
603                 limit = top[1];
604             } else {
605                 break;
606             }
607         }
608     }
609 }
610 
QsortCellsFor(CellBuildAntiAlias *** iIndex,CellBuildAntiAlias *** jIndex,CellBuildAntiAlias *** limit,CellBuildAntiAlias *** base)611 void QsortCellsFor(CellBuildAntiAlias*** iIndex, CellBuildAntiAlias*** jIndex,
612                    CellBuildAntiAlias*** limit, CellBuildAntiAlias*** base)
613 {
614     for (; *iIndex < *limit; (*iIndex)++) {
615         for (; (*jIndex)[1]->x < (**jIndex)->x; (*jIndex)--) {
616             SwapCells((*jIndex) + 1, *jIndex);
617             if ((*jIndex) == (*base)) {
618                 break;
619             }
620         }
621         *jIndex = *iIndex;
622     }
623 }
624 } // namespace OHOS
625