90 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			90 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C++
		
	
	
	
| /*
 | |
|  * Copyright 2021 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/SkFont.h"
 | |
| #include "include/core/SkPaint.h"
 | |
| #include "include/core/SkRSXform.h"
 | |
| #include "include/core/SkSpan.h"
 | |
| #include "include/private/SkTDArray.h"
 | |
| #include "src/core/SkZip.h"
 | |
| #include "tools/ToolUtils.h"
 | |
| 
 | |
| static const char gText[] = "Call me Ishmael. Some years ago—never mind how long precisely";
 | |
| 
 | |
| class DrawGlyphsGM : public skiagm::GM {
 | |
| public:
 | |
|     void onOnceBeforeDraw() override {
 | |
|         fTypeface = ToolUtils::create_portable_typeface("serif", SkFontStyle());
 | |
|         fFont = SkFont(fTypeface);
 | |
|         fFont.setSubpixel(true);
 | |
|         fFont.setSize(18);
 | |
|         const size_t txtLen = strlen(gText);
 | |
|         fGlyphCount = fFont.countText(gText, txtLen, SkTextEncoding::kUTF8);
 | |
| 
 | |
|         fGlyphs.append(fGlyphCount);
 | |
|         fFont.textToGlyphs(gText, txtLen, SkTextEncoding::kUTF8, fGlyphs.begin(), fGlyphCount);
 | |
| 
 | |
|         fPositions.append(fGlyphCount);
 | |
|         fFont.getPos(fGlyphs.begin(), fGlyphCount, fPositions.begin());
 | |
|         auto positions = SkMakeSpan(fPositions.begin(), fGlyphCount);
 | |
| 
 | |
|         fLength = positions.back().x() - positions.front().x();
 | |
|         fRadius = fLength / SK_FloatPI;
 | |
|         fXforms.append(fGlyphCount);
 | |
| 
 | |
|         for (auto [xform, pos] : SkMakeZip(fXforms.begin(), positions)) {
 | |
|             const SkScalar lengthToGlyph = pos.x() - positions.front().x();
 | |
|             const SkScalar angle = SK_FloatPI * (fLength - lengthToGlyph) / fLength;
 | |
|             const SkScalar cos = std::cos(angle);
 | |
|             const SkScalar sin = std::sin(angle);
 | |
|             xform = SkRSXform::Make(sin, cos, fRadius*cos, -fRadius*sin);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     SkString onShortName() override {
 | |
|         return SkString("drawglyphs");
 | |
|     }
 | |
| 
 | |
|     SkISize onISize() override {
 | |
|         return SkISize::Make(640, 480);
 | |
|     }
 | |
| 
 | |
|     void onDraw(SkCanvas* canvas) override {
 | |
|         canvas->drawGlyphs(fGlyphCount, fGlyphs.begin(), fPositions.begin(), {50, 100}, fFont,
 | |
|                            SkPaint{});
 | |
| 
 | |
|         canvas->drawGlyphs(fGlyphCount, fGlyphs.begin(), fPositions.begin(), {50, 120}, fFont,
 | |
|                            SkPaint{});
 | |
| 
 | |
|         // Check bounding box calculation.
 | |
|         for (auto& pos : fPositions) {
 | |
|             pos += {0, -500};
 | |
|         }
 | |
|         canvas->drawGlyphs(fGlyphCount, fGlyphs.begin(), fPositions.begin(), {50, 640}, fFont,
 | |
|                            SkPaint{});
 | |
| 
 | |
|         canvas->drawGlyphs(fGlyphCount, fGlyphs.begin(), fXforms.begin(),
 | |
|                            {50 + fLength / 2, 160 + fRadius}, fFont, SkPaint{});
 | |
| 
 | |
|         // TODO: add tests for cluster versions of drawGlyphs.
 | |
|     }
 | |
| 
 | |
| private:
 | |
|     sk_sp<SkTypeface>   fTypeface;
 | |
|     SkFont fFont;
 | |
|     SkTDArray<SkGlyphID> fGlyphs;
 | |
|     SkTDArray<SkPoint>   fPositions;
 | |
|     SkTDArray<SkRSXform> fXforms;
 | |
|     int fGlyphCount;
 | |
|     SkScalar fRadius;
 | |
|     SkScalar fLength;
 | |
| };
 | |
| 
 | |
| DEF_GM(return new DrawGlyphsGM{};)
 |