152 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			152 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C++
		
	
	
	
| /*
 | |
|  * Copyright 2013 Google Inc.
 | |
|  *
 | |
|  * Use of this source code is governed by a BSD-style license that can be
 | |
|  * found in the LICENSE file.
 | |
|  */
 | |
| 
 | |
| #include "gm/gm.h"
 | |
| #include "include/core/SkCanvas.h"
 | |
| #include "include/core/SkPaint.h"
 | |
| #include "include/core/SkPathBuilder.h"
 | |
| #include "include/core/SkScalar.h"
 | |
| #include "include/core/SkSize.h"
 | |
| #include "include/core/SkString.h"
 | |
| #include "include/core/SkTypes.h"
 | |
| 
 | |
| namespace skiagm {
 | |
| 
 | |
| // This GM tests a grab-bag of non-closed paths. All these paths look like
 | |
| // closed rects, but they don't call path.close(). Depending on the stroke
 | |
| // settings these slightly different paths give widely different results.
 | |
| class NonClosedPathsGM: public GM {
 | |
| public:
 | |
|     NonClosedPathsGM() {}
 | |
| 
 | |
|     enum ClosureType {
 | |
|         TotallyNonClosed,  // The last point doesn't coincide with the first one in the contour.
 | |
|                            // The path looks not closed at all.
 | |
| 
 | |
|         FakeCloseCorner,   // The last point coincides with the first one at a corner.
 | |
|                            // The path looks closed, but final rendering has 2 ends with cap.
 | |
| 
 | |
|         FakeCloseMiddle,   // The last point coincides with the first one in the middle of a line.
 | |
|                            // The path looks closed, and the final rendering looks closed too.
 | |
| 
 | |
|         kClosureTypeCount
 | |
|     };
 | |
| 
 | |
| protected:
 | |
| 
 | |
|     SkString onShortName() override {
 | |
|         return SkString("nonclosedpaths");
 | |
|     }
 | |
| 
 | |
|     // 12 * 18 + 3 cases, every case is 100 * 100 pixels.
 | |
|     SkISize onISize() override {
 | |
|         return SkISize::Make(1220, 1920);
 | |
|     }
 | |
| 
 | |
|     // Use rect-like geometry for non-closed path, for right angles make it
 | |
|     // easier to show the visual difference of lineCap and lineJoin.
 | |
|     static SkPath MakePath(ClosureType type) {
 | |
|         SkPathBuilder path;
 | |
|         if (FakeCloseMiddle == type) {
 | |
|             path.moveTo(30, 50);
 | |
|             path.lineTo(30, 30);
 | |
|         } else {
 | |
|             path.moveTo(30, 30);
 | |
|         }
 | |
|         path.lineTo(70, 30);
 | |
|         path.lineTo(70, 70);
 | |
|         path.lineTo(30, 70);
 | |
|         path.lineTo(30, 50);
 | |
|         if (FakeCloseCorner == type) {
 | |
|             path.lineTo(30, 30);
 | |
|         }
 | |
|         return path.detach();
 | |
|     }
 | |
| 
 | |
|     // Set the location for the current test on the canvas
 | |
|     static void SetLocation(SkCanvas* canvas, int counter, int lineNum) {
 | |
|         SkScalar x = SK_Scalar1 * 100 * (counter % lineNum) + 10 + SK_Scalar1 / 4;
 | |
|         SkScalar y = SK_Scalar1 * 100 * (counter / lineNum) + 10 + 3 * SK_Scalar1 / 4;
 | |
|         canvas->translate(x, y);
 | |
|     }
 | |
| 
 | |
|     void onDraw(SkCanvas* canvas) override {
 | |
|         // Stroke widths are:
 | |
|         // 0(may use hairline rendering), 10(common case for stroke-style)
 | |
|         // 40 and 50(>= geometry width/height, make the contour filled in fact)
 | |
|         constexpr int kStrokeWidth[] = {0, 10, 40, 50};
 | |
|         int numWidths = SK_ARRAY_COUNT(kStrokeWidth);
 | |
| 
 | |
|         constexpr SkPaint::Style kStyle[] = {
 | |
|             SkPaint::kStroke_Style, SkPaint::kStrokeAndFill_Style
 | |
|         };
 | |
| 
 | |
|         constexpr SkPaint::Cap kCap[] = {
 | |
|             SkPaint::kButt_Cap, SkPaint::kRound_Cap, SkPaint::kSquare_Cap
 | |
|         };
 | |
| 
 | |
|         constexpr SkPaint::Join kJoin[] = {
 | |
|             SkPaint::kMiter_Join, SkPaint::kRound_Join, SkPaint::kBevel_Join
 | |
|         };
 | |
| 
 | |
|         constexpr ClosureType kType[] = {
 | |
|             TotallyNonClosed, FakeCloseCorner, FakeCloseMiddle
 | |
|         };
 | |
| 
 | |
|         int counter = 0;
 | |
|         SkPaint paint;
 | |
|         paint.setAntiAlias(true);
 | |
| 
 | |
|         // For stroke style painter and fill-and-stroke style painter
 | |
|         for (size_t type = 0; type < kClosureTypeCount; ++type) {
 | |
|             for (size_t style = 0; style < SK_ARRAY_COUNT(kStyle); ++style) {
 | |
|                 for (size_t cap = 0; cap < SK_ARRAY_COUNT(kCap); ++cap) {
 | |
|                     for (size_t join = 0; join < SK_ARRAY_COUNT(kJoin); ++join) {
 | |
|                         for (int width = 0; width < numWidths; ++width) {
 | |
|                             canvas->save();
 | |
|                             SetLocation(canvas, counter, SkPaint::kJoinCount * numWidths);
 | |
| 
 | |
|                             SkPath path = MakePath(kType[type]);
 | |
| 
 | |
|                             paint.setStyle(kStyle[style]);
 | |
|                             paint.setStrokeCap(kCap[cap]);
 | |
|                             paint.setStrokeJoin(kJoin[join]);
 | |
|                             paint.setStrokeWidth(SkIntToScalar(kStrokeWidth[width]));
 | |
| 
 | |
|                             canvas->drawPath(path, paint);
 | |
|                             canvas->restore();
 | |
|                             ++counter;
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         // For fill style painter
 | |
|         paint.setStyle(SkPaint::kFill_Style);
 | |
|         for (size_t type = 0; type < kClosureTypeCount; ++type) {
 | |
|             canvas->save();
 | |
|             SetLocation(canvas, counter, SkPaint::kJoinCount * numWidths);
 | |
| 
 | |
|             SkPath path = MakePath(kType[type]);
 | |
| 
 | |
|             canvas->drawPath(path, paint);
 | |
|             canvas->restore();
 | |
|             ++counter;
 | |
|         }
 | |
|     }
 | |
| 
 | |
| private:
 | |
|     using INHERITED = GM;
 | |
| };
 | |
| 
 | |
| //////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| DEF_GM(return new NonClosedPathsGM;)
 | |
| 
 | |
| }  // namespace skiagm
 |