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