OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkLinearBitmapPipeline.h" | 8 #include "SkLinearBitmapPipeline.h" |
9 | 9 |
10 struct X { | 10 struct X { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
48 Sk4f newYs = ys; | 48 Sk4f newYs = ys; |
49 fStrategy.processPoints(&newXs, &newYs); | 49 fStrategy.processPoints(&newXs, &newYs); |
50 fNext->pointList4(newXs, newYs); | 50 fNext->pointList4(newXs, newYs); |
51 } | 51 } |
52 | 52 |
53 private: | 53 private: |
54 Next* const fNext; | 54 Next* const fNext; |
55 Strategy fStrategy; | 55 Strategy fStrategy; |
56 }; | 56 }; |
57 | 57 |
58 class SkippedStage final : public PointProcessorInterface { | 58 template<typename Strategy, typename Next> |
59 class BilerpProcessor : public BilerpProcessorInterface { | |
mtklein
2016/02/17 20:25:09
final (and PointProcessor too)?
herb_g
2016/02/17 23:40:43
Done.
| |
60 public: | |
61 template <typename... Args> | |
62 BilerpProcessor(Next* next, Args&&... args) | |
63 : fNext{next} | |
64 , fStrategy{std::forward<Args>(args)...}{ } | |
65 | |
59 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { | 66 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { |
60 SkFAIL("Abort tiler."); | 67 Sk4f newXs = xs; |
mtklein
2016/02/17 20:25:09
This is so sad. :(
herb_g
2016/02/17 23:40:44
Acknowledged.
| |
68 Sk4f newYs = ys; | |
69 fStrategy.processPoints(&newXs, &newYs); | |
70 fNext->pointListFew(n, newXs, newYs); | |
71 } | |
72 | |
73 void pointList4(Sk4fArg xs, Sk4fArg ys) override { | |
74 Sk4f newXs = xs; | |
75 Sk4f newYs = ys; | |
76 fStrategy.processPoints(&newXs, &newYs); | |
77 fNext->pointList4(newXs, newYs); | |
78 } | |
79 | |
80 void bilerpList(Sk4fArg xs, Sk4fArg ys) override { | |
81 Sk4f newXs = xs; | |
82 Sk4f newYs = ys; | |
83 fStrategy.processPoints(&newXs, &newYs); | |
84 fNext->bilerpList(newXs, newYs); | |
85 } | |
86 | |
87 private: | |
88 Next* const fNext; | |
89 Strategy fStrategy; | |
90 }; | |
91 | |
92 class SkippedStage final : public BilerpProcessorInterface { | |
93 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { | |
94 SkFAIL("Skipped stage."); | |
61 } | 95 } |
62 void pointList4(Sk4fArg Xs, Sk4fArg Ys) override { | 96 void pointList4(Sk4fArg Xs, Sk4fArg Ys) override { |
63 SkFAIL("Abort point processor."); | 97 SkFAIL("Skipped stage."); |
98 } | |
99 virtual void bilerpList(Sk4fArg xs, Sk4fArg ys) override { | |
mtklein
2016/02/17 20:25:09
I think override's plenty.
herb_g
2016/02/17 23:40:44
Done.
| |
100 SkFAIL("Skipped stage."); | |
64 } | 101 } |
65 }; | 102 }; |
66 | 103 |
67 class TranslateMatrixStrategy { | 104 class TranslateMatrixStrategy { |
68 public: | 105 public: |
69 TranslateMatrixStrategy(SkVector offset) | 106 TranslateMatrixStrategy(SkVector offset) |
70 : fXOffset{X(offset)} | 107 : fXOffset{X(offset)} |
71 , fYOffset{Y(offset)} { } | 108 , fYOffset{Y(offset)} { } |
72 void processPoints(Sk4f* xs, Sk4f* ys) { | 109 void processPoints(Sk4f* xs, Sk4f* ys) { |
73 *xs = *xs + fXOffset; | 110 *xs = *xs + fXOffset; |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
140 matrixProc->Initialize<TranslateMatrix<>>( | 177 matrixProc->Initialize<TranslateMatrix<>>( |
141 next, | 178 next, |
142 SkVector{inverse.getTranslateX(), inverse.getTranslateY()}); | 179 SkVector{inverse.getTranslateX(), inverse.getTranslateY()}); |
143 } else { | 180 } else { |
144 matrixProc->Initialize<SkippedStage>(); | 181 matrixProc->Initialize<SkippedStage>(); |
145 return next; | 182 return next; |
146 } | 183 } |
147 return matrixProc->get(); | 184 return matrixProc->get(); |
148 } | 185 } |
149 | 186 |
187 template <typename Next = BilerpProcessorInterface> | |
188 class ExpandBilerp final : public PointProcessorInterface { | |
189 public: | |
190 ExpandBilerp(Next* next) : fNext{next} { } | |
191 | |
192 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { | |
193 SkASSERT(n > 0 && n <= 4); | |
mtklein
2016/02/17 20:25:09
This seems awkward. It's a bug if we call pointLi
herb_g
2016/02/17 23:40:43
Done.
| |
194 if (n >= 1) fNext->bilerpList(Sk4f{xs[0]} + kXOffsets, Sk4f{ys[0]} + kYO ffsets); | |
195 if (n >= 2) fNext->bilerpList(Sk4f{xs[1]} + kXOffsets, Sk4f{ys[1]} + kYO ffsets); | |
196 if (n >= 3) fNext->bilerpList(Sk4f{xs[2]} + kXOffsets, Sk4f{ys[2]} + kYO ffsets); | |
197 if (n == 4) fNext->bilerpList(Sk4f{xs[3]} + kXOffsets, Sk4f{ys[3]} + kYO ffsets); | |
198 } | |
199 | |
200 void pointList4(Sk4fArg xs, Sk4fArg ys) override { | |
201 pointListFew(4, xs, ys); | |
mtklein
2016/02/17 20:25:09
self calls usually have a this->
herb_g
2016/02/17 23:40:44
Removed
| |
202 } | |
mtklein
2016/02/17 20:25:09
Is this why we distinguish PointProcessor and Bile
herb_g
2016/02/17 23:40:44
There is no sensible bilerp here or at the matrix
| |
203 | |
204 private: | |
205 static const Sk4f kXOffsets; | |
206 static const Sk4f kYOffsets; | |
207 Next* const fNext; | |
208 }; | |
209 | |
210 template <typename Next> | |
211 const Sk4f ExpandBilerp<Next>::kXOffsets = {0.0f, 1.0f, 0.0f, 1.0f}; | |
mtklein
2016/02/17 20:25:09
This is all sort of awkward and boilerplate-y.
Le
herb_g
2016/02/17 23:40:43
Done.
| |
212 template <typename Next> | |
213 const Sk4f ExpandBilerp<Next>::kYOffsets = {0.0f, 0.0f, 1.0f, 1.0f}; | |
214 | |
215 static PointProcessorInterface* choose_filter( | |
216 BilerpProcessorInterface* next, | |
217 SkFilterQuality filterQuailty, | |
218 SkLinearBitmapPipeline::FilterStage* filterProc) { | |
219 if (filterQuailty >= SkFilterQuality::kLow_SkFilterQuality) { | |
mtklein
2016/02/17 20:25:09
Might wanna write as:
none -> skipped
else -
herb_g
2016/02/17 23:40:43
Done.
| |
220 filterProc->Initialize<ExpandBilerp<>>(next); | |
221 return filterProc->get(); | |
222 } else { | |
223 filterProc->Initialize<SkippedStage>(); | |
224 return next; | |
225 } | |
226 } | |
227 | |
150 class ClampStrategy { | 228 class ClampStrategy { |
151 public: | 229 public: |
152 ClampStrategy(X max) | 230 ClampStrategy(X max) |
153 : fXMin{0.0f} | 231 : fXMin{0.0f} |
154 , fXMax{max - 1.0f} { } | 232 , fXMax{max - 1.0f} { } |
155 ClampStrategy(Y max) | 233 ClampStrategy(Y max) |
156 : fYMin{0.0f} | 234 : fYMin{0.0f} |
157 , fYMax{max - 1.0f} { } | 235 , fYMax{max - 1.0f} { } |
158 ClampStrategy(SkSize max) | 236 ClampStrategy(SkSize max) |
159 : fXMin{0.0f} | 237 : fXMin{0.0f} |
160 , fYMin{0.0f} | 238 , fYMin{0.0f} |
161 , fXMax{X(max) - 1.0f} | 239 , fXMax{X(max) - 1.0f} |
162 , fYMax{Y(max) - 1.0f} { } | 240 , fYMax{Y(max) - 1.0f} { } |
163 | 241 |
164 void processPoints(Sk4f* xs, Sk4f* ys) { | 242 void processPoints(Sk4f* xs, Sk4f* ys) { |
165 *xs = Sk4f::Min(Sk4f::Max(*xs, fXMin), fXMax); | 243 *xs = Sk4f::Min(Sk4f::Max(*xs, fXMin), fXMax); |
166 *ys = Sk4f::Min(Sk4f::Max(*ys, fYMin), fYMax); | 244 *ys = Sk4f::Min(Sk4f::Max(*ys, fYMin), fYMax); |
167 } | 245 } |
168 | 246 |
169 private: | 247 private: |
170 const Sk4f fXMin{SK_FloatNegativeInfinity}; | 248 const Sk4f fXMin{SK_FloatNegativeInfinity}; |
171 const Sk4f fYMin{SK_FloatNegativeInfinity}; | 249 const Sk4f fYMin{SK_FloatNegativeInfinity}; |
172 const Sk4f fXMax{SK_FloatInfinity}; | 250 const Sk4f fXMax{SK_FloatInfinity}; |
173 const Sk4f fYMax{SK_FloatInfinity}; | 251 const Sk4f fYMax{SK_FloatInfinity}; |
174 }; | 252 }; |
175 template <typename Next = PointProcessorInterface> | 253 template <typename Next = BilerpProcessorInterface> |
176 using Clamp = PointProcessor<ClampStrategy, Next>; | 254 using Clamp = BilerpProcessor<ClampStrategy, Next>; |
177 | 255 |
178 class RepeatStrategy { | 256 class RepeatStrategy { |
179 public: | 257 public: |
180 RepeatStrategy(X max) : fXMax{max}, fXInvMax{1.0f/max} { } | 258 RepeatStrategy(X max) : fXMax{max}, fXInvMax{1.0f/max} { } |
181 RepeatStrategy(Y max) : fYMax{max}, fYInvMax{1.0f/max} { } | 259 RepeatStrategy(Y max) : fYMax{max}, fYInvMax{1.0f/max} { } |
182 RepeatStrategy(SkSize max) | 260 RepeatStrategy(SkSize max) |
183 : fXMax{X(max)} | 261 : fXMax{X(max)} |
184 , fXInvMax{1.0f / X(max)} | 262 , fXInvMax{1.0f / X(max)} |
185 , fYMax{Y(max)} | 263 , fYMax{Y(max)} |
186 , fYInvMax{1.0f / Y(max)} { } | 264 , fYInvMax{1.0f / Y(max)} { } |
187 | 265 |
188 void processPoints(Sk4f* xs, Sk4f* ys) { | 266 void processPoints(Sk4f* xs, Sk4f* ys) { |
189 Sk4f divX = (*xs * fXInvMax).floor(); | 267 Sk4f divX = (*xs * fXInvMax).floor(); |
190 Sk4f divY = (*ys * fYInvMax).floor(); | 268 Sk4f divY = (*ys * fYInvMax).floor(); |
191 Sk4f baseX = (divX * fXMax); | 269 Sk4f baseX = (divX * fXMax); |
192 Sk4f baseY = (divY * fYMax); | 270 Sk4f baseY = (divY * fYMax); |
193 *xs = *xs - baseX; | 271 *xs = *xs - baseX; |
194 *ys = *ys - baseY; | 272 *ys = *ys - baseY; |
195 } | 273 } |
196 | 274 |
197 private: | 275 private: |
198 const Sk4f fXMax{0.0f}; | 276 const Sk4f fXMax{0.0f}; |
199 const Sk4f fXInvMax{0.0f}; | 277 const Sk4f fXInvMax{0.0f}; |
200 const Sk4f fYMax{0.0f}; | 278 const Sk4f fYMax{0.0f}; |
201 const Sk4f fYInvMax{0.0f}; | 279 const Sk4f fYInvMax{0.0f}; |
202 }; | 280 }; |
203 | 281 |
204 template <typename Next = PointProcessorInterface> | 282 template <typename Next = BilerpProcessorInterface> |
205 using Repeat = PointProcessor<RepeatStrategy, Next>; | 283 using Repeat = BilerpProcessor<RepeatStrategy, Next>; |
206 | 284 |
207 static PointProcessorInterface* choose_tiler( | 285 static BilerpProcessorInterface* choose_tiler( |
208 PointProcessorInterface* next, | 286 BilerpProcessorInterface* next, |
209 SkSize dimensions, | 287 SkSize dimensions, |
210 SkShader::TileMode xMode, | 288 SkShader::TileMode xMode, |
211 SkShader::TileMode yMode, | 289 SkShader::TileMode yMode, |
212 SkLinearBitmapPipeline::TileStage* tileProcXOrBoth, | 290 SkLinearBitmapPipeline::TileStage* tileProcXOrBoth, |
213 SkLinearBitmapPipeline::TileStage* tileProcY) { | 291 SkLinearBitmapPipeline::TileStage* tileProcY) { |
214 if (xMode == yMode) { | 292 if (xMode == yMode) { |
215 switch (xMode) { | 293 switch (xMode) { |
216 case SkShader::kClamp_TileMode: | 294 case SkShader::kClamp_TileMode: |
217 tileProcXOrBoth->Initialize<Clamp<>>(next, dimensions); | 295 tileProcXOrBoth->Initialize<Clamp<>>(next, dimensions); |
218 break; | 296 break; |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
300 pixel = pixel * Sk4f{1.0f/255.0f}; | 378 pixel = pixel * Sk4f{1.0f/255.0f}; |
301 if (colorProfile == kSRGB_SkColorProfileType) { | 379 if (colorProfile == kSRGB_SkColorProfileType) { |
302 pixel = sRGBFast::sRGBToLinear(pixel); | 380 pixel = sRGBFast::sRGBToLinear(pixel); |
303 } | 381 } |
304 return pixel; | 382 return pixel; |
305 } | 383 } |
306 const uint32_t* const fSrc; | 384 const uint32_t* const fSrc; |
307 const Sk4i fWidth; | 385 const Sk4i fWidth; |
308 }; | 386 }; |
309 | 387 |
388 inline Sk4f bilerp4(SkPoint pt, Sk4f pixel00, Sk4f pixel01, | |
mtklein
2016/02/17 20:25:09
It's a good habit to get into writing static on al
herb_g
2016/02/17 23:40:44
Done.
| |
389 Sk4f pixel10, Sk4f pixel11) { | |
390 Sk4f Xs{X(pt) - std::floor(X(pt))}; | |
mtklein
2016/02/17 20:25:09
If we're using std:: stuff, might want to consider
herb_g
2016/02/17 23:40:43
Redid whole function.
| |
391 Sk4f Ys{Y(pt) - std::floor(Y(pt))}; | |
392 Sk4f XYs{Xs * Ys}; | |
393 Sk4f sum = pixel11 * XYs; | |
394 sum = sum + pixel01 * (Xs - XYs); | |
395 sum = sum + pixel10 * (Ys - XYs); | |
396 sum = sum + pixel00 * (Sk4f{1.0f} - Xs - Ys + XYs); | |
mtklein
2016/02/17 20:25:09
This would be a really great place for an ASCII ar
herb_g
2016/02/17 23:40:43
Done.
| |
397 return sum; | |
398 } | |
399 | |
310 template <typename SourceStrategy> | 400 template <typename SourceStrategy> |
311 class Sampler final : public PointProcessorInterface { | 401 class Sampler final : public BilerpProcessorInterface { |
312 public: | 402 public: |
313 template <typename... Args> | 403 template <typename... Args> |
314 Sampler(PixelPlacerInterface* next, Args&&... args) | 404 Sampler(PixelPlacerInterface* next, Args&&... args) |
315 : fNext{next} | 405 : fNext{next} |
316 , fStrategy{std::forward<Args>(args)...} { } | 406 , fStrategy{std::forward<Args>(args)...} { } |
317 | 407 |
318 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { | 408 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { |
319 SkASSERT(0 < n && n < 4); | 409 SkASSERT(0 < n && n < 4); |
320 Sk4f px0, px1, px2; | 410 Sk4f px0, px1, px2; |
321 fStrategy.getFewPixels(n, xs, ys, &px0, &px1, &px2); | 411 fStrategy.getFewPixels(n, xs, ys, &px0, &px1, &px2); |
322 if (n >= 1) fNext->placePixel(px0); | 412 if (n >= 1) fNext->placePixel(px0); |
323 if (n >= 2) fNext->placePixel(px1); | 413 if (n >= 2) fNext->placePixel(px1); |
324 if (n >= 3) fNext->placePixel(px2); | 414 if (n >= 3) fNext->placePixel(px2); |
325 } | 415 } |
326 | 416 |
327 void pointList4(Sk4fArg xs, Sk4fArg ys) override { | 417 void pointList4(Sk4fArg xs, Sk4fArg ys) override { |
328 Sk4f px0, px1, px2, px3; | 418 Sk4f px0, px1, px2, px3; |
329 fStrategy.get4Pixels(xs, ys, &px0, &px1, &px2, &px3); | 419 fStrategy.get4Pixels(xs, ys, &px0, &px1, &px2, &px3); |
330 fNext->place4Pixels(px0, px1, px2, px3); | 420 fNext->place4Pixels(px0, px1, px2, px3); |
331 } | 421 } |
332 | 422 |
423 void bilerpList(Sk4fArg xs, Sk4fArg ys) override { | |
424 SkPoint referencePoint{xs[0], ys[0]}; | |
mtklein
2016/02/17 20:25:09
Do these all have the same fractional parts? I'm
herb_g
2016/02/17 23:40:43
Done.
| |
425 Sk4f px0, px1, px2, px3; | |
426 fStrategy.get4Pixels(xs, ys, &px0, &px1, &px2, &px3); | |
427 Sk4f pixel = bilerp4(referencePoint, px0, px1, px2, px3); | |
428 fNext->placePixel(pixel); | |
429 } | |
430 | |
333 private: | 431 private: |
334 PixelPlacerInterface* const fNext; | 432 PixelPlacerInterface* const fNext; |
335 SourceStrategy fStrategy; | 433 SourceStrategy fStrategy; |
336 }; | 434 }; |
337 | 435 |
338 static PointProcessorInterface* choose_pixel_sampler( | 436 static BilerpProcessorInterface* choose_pixel_sampler( |
339 PixelPlacerInterface* next, | 437 PixelPlacerInterface* next, |
340 const SkImageInfo& imageInfo, | 438 const SkImageInfo& imageInfo, |
341 const void* imageData, | 439 const void* imageData, |
342 SkLinearBitmapPipeline::SampleStage* sampleStage) { | 440 SkLinearBitmapPipeline::SampleStage* sampleStage) { |
343 switch (imageInfo.colorType()) { | 441 switch (imageInfo.colorType()) { |
344 case kRGBA_8888_SkColorType: | 442 case kRGBA_8888_SkColorType: |
345 case kBGRA_8888_SkColorType: | 443 case kBGRA_8888_SkColorType: |
346 if (kN32_SkColorType == imageInfo.colorType()) { | 444 if (kN32_SkColorType == imageInfo.colorType()) { |
347 if (imageInfo.profileType() == kSRGB_SkColorProfileType) { | 445 if (imageInfo.profileType() == kSRGB_SkColorProfileType) { |
348 sampleStage->Initialize<Sampler<Passthrough8888<kSRGB_SkColo rProfileType>>>( | 446 sampleStage->Initialize<Sampler<Passthrough8888<kSRGB_SkColo rProfileType>>>( |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
408 placerStage->Initialize<PlaceFPPixel<kUnpremul_SkAlphaType>>(); | 506 placerStage->Initialize<PlaceFPPixel<kUnpremul_SkAlphaType>>(); |
409 } else { | 507 } else { |
410 // kOpaque_SkAlphaType is treated the same as kPremul_SkAlphaType | 508 // kOpaque_SkAlphaType is treated the same as kPremul_SkAlphaType |
411 placerStage->Initialize<PlaceFPPixel<kPremul_SkAlphaType>>(); | 509 placerStage->Initialize<PlaceFPPixel<kPremul_SkAlphaType>>(); |
412 } | 510 } |
413 return placerStage->get(); | 511 return placerStage->get(); |
414 } | 512 } |
415 | 513 |
416 SkLinearBitmapPipeline::SkLinearBitmapPipeline( | 514 SkLinearBitmapPipeline::SkLinearBitmapPipeline( |
417 const SkMatrix& inverse, | 515 const SkMatrix& inverse, |
516 SkFilterQuality filterQuality, | |
418 SkShader::TileMode xTile, SkShader::TileMode yTile, | 517 SkShader::TileMode xTile, SkShader::TileMode yTile, |
419 const SkImageInfo& srcImageInfo, | 518 const SkImageInfo& srcImageInfo, |
420 const void* srcImageData) { | 519 const void* srcImageData) { |
421 SkSize size; | 520 SkSize size; |
422 size = srcImageInfo.dimensions(); | 521 size = srcImageInfo.dimensions(); |
423 | 522 |
424 // As the stages are built, the chooser function may skip a stage. For examp le, with the | 523 // As the stages are built, the chooser function may skip a stage. For examp le, with the |
425 // identity matrix, the matrix stage is skipped, and the tilerStage is the f irst stage. | 524 // identity matrix, the matrix stage is skipped, and the tilerStage is the f irst stage. |
426 auto placementStage = choose_pixel_placer(srcImageInfo.alphaType(), &fPixelS tage); | 525 auto placementStage = choose_pixel_placer(srcImageInfo.alphaType(), &fPixelS tage); |
427 auto samplerStage = choose_pixel_sampler(placementStage, srcImageInfo, | 526 auto samplerStage = choose_pixel_sampler(placementStage, srcImageInfo, |
428 srcImageData, &fSampleStage); | 527 srcImageData, &fSampleStage); |
429 auto tilerStage = choose_tiler(samplerStage, size, xTile, yTile, &fTileX OrBothStage, | 528 auto tilerStage = choose_tiler(samplerStage, size, xTile, yTile, &fTileX OrBothStage, |
430 &fTileYStage); | 529 &fTileYStage); |
431 fFirstStage = choose_matrix(tilerStage, inverse, &fMatrixStage); | 530 auto filterStage = choose_filter(tilerStage, filterQuality, &fFilterStage ); |
531 fFirstStage = choose_matrix(filterStage, inverse, &fMatrixStage); | |
432 } | 532 } |
433 | 533 |
434 void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) { | 534 void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) { |
435 fPixelStage->setDestination(dst); | 535 fPixelStage->setDestination(dst); |
436 | 536 |
437 Sk4f Xs = Sk4f(x) + Sk4f{0.5f, 1.5f, 2.5f, 3.5f}; | 537 Sk4f Xs = Sk4f(x) + Sk4f{0.5f, 1.5f, 2.5f, 3.5f}; |
438 Sk4f Ys(y); | 538 Sk4f Ys(y); |
439 Sk4f fours{4.0f}; | 539 Sk4f fours{4.0f}; |
440 | 540 |
441 while (count >= 4) { | 541 while (count >= 4) { |
442 fFirstStage->pointList4(Xs, Ys); | 542 fFirstStage->pointList4(Xs, Ys); |
443 Xs = Xs + fours; | 543 Xs = Xs + fours; |
444 count -= 4; | 544 count -= 4; |
445 } | 545 } |
446 if (count > 0) { | 546 if (count > 0) { |
447 fFirstStage->pointListFew(count, Xs, Ys); | 547 fFirstStage->pointListFew(count, Xs, Ys); |
448 } | 548 } |
449 } | 549 } |
OLD | NEW |