• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 (cells_) {
415                 if (memcpy_s(newCells, maxBlocks_ * sizeof(CellBuildAntiAlias*),
416                              cells_, maxBlocks_ * sizeof(CellBuildAntiAlias*)) != EOK) {
417                     GRAPHIC_LOGE("RasterizerCellsAntiAlias::AllocateBlock memcpy_s fail\n");
418                     return;
419                 }
420                 GeometryArrayAllocator<CellBuildAntiAlias*>::Deallocate(cells_, maxBlocks_);
421             }
422             cells_ = newCells;
423             maxBlocks_ += CELL_BLOCK_POOL;
424         }
425         cells_[numBlocks_++] = GeometryArrayAllocator<CellBuildAntiAlias>::Allocate(CELL_BLOCK_SIZE);
426     }
427 
428     currCellPtr_ = cells_[currBlock_++];
429 }
430 /**
431  * @brief In the rasterization process, all cells are rasterized according to
432  * Sort from left to right and from top to bottom.
433  * @since 1.0
434  * @version 1.0
435  */
SortAllCells()436 void RasterizerCellsAntiAlias::SortAllCells()
437 {
438     if (sorted_) {
439         return; // Perform sort only the first time.
440     }
441 
442     AddCurrentCell();
443     currCell_.x = INT32_MAX;
444     currCell_.y = INT32_MAX;
445     currCell_.cover = 0;
446     currCell_.area = 0;
447     if (numCells_ == 0) {
448         return;
449     }
450 
451     // Allocate the array of cell pointers
452     sortedCells_ = GeometryArrayAllocator<CellBuildAntiAlias*>::Allocate(numCells_ + CELLS_SIZE);
453 
454     // Allocate and zero the Y array
455     uint32_t sortedYSize = maxY_ - minY_ + 1;
456     sortedY_ = GeometryArrayAllocator<SortedYLevel>::Allocate(sortedYSize + CELLS_SIZE);
457     if (memset_s(sortedY_, sizeof(SortedYLevel) * sortedYSize, 0, sizeof(SortedYLevel) * sortedYSize) != EOK) {
458         GRAPHIC_LOGE("CleanData fail");
459     }
460 
461     // Create the Y-histogram (count the numbers of cells for each Y)
462     CellBuildAntiAlias** blockPtr = cells_;
463     CellBuildAntiAlias* cellPtr = nullptr;
464     uint32_t nb = numCells_;
465     uint32_t i = 0;
466     while (nb) {
467         cellPtr = *blockPtr++;
468         i = (nb > CELL_BLOCK_SIZE) ? uint32_t(CELL_BLOCK_SIZE) : nb;
469         nb -= i;
470         while (i--) {
471             sortedY_[cellPtr->y - minY_].start++;
472             ++cellPtr;
473         }
474     }
475 
476     // Convert the Y-histogram into the array of starting indexes
477     uint32_t start = 0;
478     for (i = 0; i < sortedYSize; i++) {
479         uint32_t v = sortedY_[i].start;
480         sortedY_[i].start = start;
481         start += v;
482     }
483 
484     // Fill the cell pointer array sorted by Y
485     blockPtr = cells_;
486     nb = numCells_;
487     while (nb) {
488         cellPtr = *blockPtr++;
489         i = (nb > CELL_BLOCK_SIZE) ? uint32_t(CELL_BLOCK_SIZE) : nb;
490         nb -= i;
491         while (i--) {
492             SortedYLevel& currY = sortedY_[cellPtr->y - minY_];
493             sortedCells_[currY.start + currY.num] = cellPtr;
494             ++currY.num;
495             ++cellPtr;
496         }
497     }
498 
499     // Finally arrange the X-arrays
500     for (i = 0; i < sortedYSize; i++) {
501         const SortedYLevel& currY = sortedY_[i];
502         if (currY.num) {
503             QsortCells(sortedCells_ + currY.start, currY.num);
504         }
505     }
506     sorted_ = true;
507 }
508 
QsortCellsSweep(CellBuildAntiAlias *** base,CellBuildAntiAlias *** iIndex,CellBuildAntiAlias *** jIndex)509 void QsortCellsSweep(CellBuildAntiAlias*** base, CellBuildAntiAlias*** iIndex, CellBuildAntiAlias*** jIndex)
510 {
511     /**
512      * Sorting guarantees the value of * i < = * the value of base < = * the value of j
513      */
514     if ((**jIndex)->x < (**iIndex)->x) {
515         SwapCells(*iIndex, *jIndex);
516     }
517 
518     if ((**base)->x < (**iIndex)->x) {
519         SwapCells(*base, *iIndex);
520     }
521 
522     if ((**jIndex)->x < (**base)->x) {
523         SwapCells(*base, *jIndex);
524     }
525 
526     while (true) {
527         int32_t x = (**base)->x;
528         do {
529             (*iIndex)++;
530         } while ((**iIndex)->x < x);
531         do {
532             (*jIndex)--;
533         } while (x < (**jIndex)->x);
534 
535         if ((*iIndex) > (*jIndex)) {
536             break;
537         }
538         SwapCells(*iIndex, *jIndex);
539     }
540 }
541 
QsortCells(CellBuildAntiAlias ** start,uint32_t num)542 void QsortCells(CellBuildAntiAlias** start, uint32_t num)
543 {
544     const int32_t QSORT_THRESHOLD = 9;
545     const int32_t stackSize = 80;
546     CellBuildAntiAlias** stack[stackSize];
547     CellBuildAntiAlias*** top;
548     CellBuildAntiAlias** limit;
549     CellBuildAntiAlias** base;
550 
551     limit = start + num;
552     base = start;
553     top = stack;
554 
555     while (true) {
556         int32_t len = int32_t(limit - base);
557 
558         CellBuildAntiAlias** iIndex;
559         CellBuildAntiAlias** jIndex;
560 
561         if (len > QSORT_THRESHOLD) {
562             /**
563              * First exchange base + len / 2 as the pivot
564              */
565             CellBuildAntiAlias** pivot = base + len / TWO_TIMES;
566             SwapCells(base, pivot);
567 
568             iIndex = base + 1;
569             jIndex = limit - 1;
570 
571             QsortCellsSweep(&base, &iIndex, &jIndex);
572             SwapCells(base, jIndex);
573             if (jIndex - base > limit - iIndex) {
574                 top[0] = base;
575                 top[1] = jIndex;
576                 base = iIndex;
577             } else {
578                 top[0] = iIndex;
579                 top[1] = limit;
580                 limit = jIndex;
581             }
582             top += TWO_STEP;
583         } else {
584             /**
585              * When the sub-array becomes smaller, insert sort is performed using
586              */
587             jIndex = base;
588             iIndex = jIndex + 1;
589             QsortCellsFor(&iIndex, &jIndex, &limit, &base);
590             if (top > stack) {
591                 top -= TWO_STEP;
592                 base = top[0];
593                 limit = top[1];
594             } else {
595                 break;
596             }
597         }
598     }
599 }
600 
QsortCellsFor(CellBuildAntiAlias *** iIndex,CellBuildAntiAlias *** jIndex,CellBuildAntiAlias *** limit,CellBuildAntiAlias *** base)601 void QsortCellsFor(CellBuildAntiAlias*** iIndex, CellBuildAntiAlias*** jIndex,
602                    CellBuildAntiAlias*** limit, CellBuildAntiAlias*** base)
603 {
604     for (; *iIndex < *limit; (*iIndex)++) {
605         for (; (*jIndex)[1]->x < (**jIndex)->x; (*jIndex)--) {
606             SwapCells((*jIndex) + 1, *jIndex);
607             if ((*jIndex) == (*base)) {
608                 break;
609             }
610         }
611         *jIndex = *iIndex;
612     }
613 }
614 } // namespace OHOS
615