2012-07-27 20:39:19 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2012 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "gm/gm.h"
|
|
|
|
#include "include/core/SkBlurTypes.h"
|
|
|
|
#include "include/core/SkCanvas.h"
|
2019-05-01 21:28:53 +00:00
|
|
|
#include "include/core/SkFont.h"
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "include/core/SkFontStyle.h"
|
2019-05-01 21:28:53 +00:00
|
|
|
#include "include/core/SkFontTypes.h"
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "include/core/SkMaskFilter.h"
|
2019-05-01 21:28:53 +00:00
|
|
|
#include "include/core/SkPaint.h"
|
|
|
|
#include "include/core/SkPoint.h"
|
|
|
|
#include "include/core/SkRefCnt.h"
|
|
|
|
#include "include/core/SkScalar.h"
|
|
|
|
#include "include/core/SkSize.h"
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "include/core/SkString.h"
|
|
|
|
#include "include/core/SkTextBlob.h"
|
|
|
|
#include "include/core/SkTypeface.h"
|
|
|
|
#include "include/core/SkTypes.h"
|
2019-05-01 21:28:53 +00:00
|
|
|
#include "include/private/SkTemplates.h"
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "tools/Resources.h"
|
2019-05-01 21:28:53 +00:00
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include <utility>
|
2012-07-27 20:39:19 +00:00
|
|
|
|
2018-12-24 19:52:46 +00:00
|
|
|
static void getGlyphPositions(const SkFont& font, const uint16_t glyphs[],
|
2013-10-30 15:07:03 +00:00
|
|
|
int count, SkScalar x, SkScalar y, SkPoint pos[]) {
|
|
|
|
SkAutoSTMalloc<128, SkScalar> widthStorage(count);
|
|
|
|
SkScalar* widths = widthStorage.get();
|
2018-12-24 19:52:46 +00:00
|
|
|
font.getWidths(glyphs, count, widths);
|
2013-10-31 07:01:53 +00:00
|
|
|
|
2013-10-30 15:07:03 +00:00
|
|
|
for (int i = 0; i < count; ++i) {
|
|
|
|
pos[i].set(x, y);
|
|
|
|
x += widths[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void applyKerning(SkPoint pos[], const int32_t adjustments[], int count,
|
2018-12-24 19:52:46 +00:00
|
|
|
const SkFont& font) {
|
2019-01-22 19:45:16 +00:00
|
|
|
SkScalar scale = font.getSize() / font.getTypefaceOrDefault()->getUnitsPerEm();
|
2013-10-30 15:07:03 +00:00
|
|
|
|
|
|
|
SkScalar globalAdj = 0;
|
|
|
|
for (int i = 0; i < count - 1; ++i) {
|
|
|
|
globalAdj += adjustments[i] * scale;
|
|
|
|
pos[i + 1].fX += globalAdj;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void drawKernText(SkCanvas* canvas, const void* text, size_t len,
|
2018-12-24 19:52:46 +00:00
|
|
|
SkScalar x, SkScalar y, const SkFont& font, const SkPaint& paint) {
|
2019-01-22 19:45:16 +00:00
|
|
|
SkTypeface* face = font.getTypefaceOrDefault();
|
2013-10-30 15:07:03 +00:00
|
|
|
if (!face) {
|
2019-05-07 19:38:46 +00:00
|
|
|
canvas->drawSimpleText(text, len, SkTextEncoding::kUTF8, x, y, font, paint);
|
2013-10-30 15:07:03 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SkAutoSTMalloc<128, uint16_t> glyphStorage(len);
|
|
|
|
uint16_t* glyphs = glyphStorage.get();
|
2019-05-07 19:38:46 +00:00
|
|
|
int glyphCount = font.textToGlyphs(text, len, SkTextEncoding::kUTF8, glyphs, len);
|
2013-10-30 15:07:03 +00:00
|
|
|
if (glyphCount < 1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SkAutoSTMalloc<128, int32_t> adjustmentStorage(glyphCount - 1);
|
|
|
|
int32_t* adjustments = adjustmentStorage.get();
|
|
|
|
if (!face->getKerningPairAdjustments(glyphs, glyphCount, adjustments)) {
|
2019-05-07 19:38:46 +00:00
|
|
|
canvas->drawSimpleText(text, len, SkTextEncoding::kUTF8, x, y, font, paint);
|
2013-10-30 15:07:03 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-12-24 19:52:46 +00:00
|
|
|
SkTextBlobBuilder builder;
|
|
|
|
auto rec = builder.allocRunPos(font, glyphCount);
|
|
|
|
memcpy(rec.glyphs, glyphs, glyphCount * sizeof(SkGlyphID));
|
2019-01-01 20:40:28 +00:00
|
|
|
getGlyphPositions(font, glyphs, glyphCount, x, y, rec.points());
|
|
|
|
applyKerning(rec.points(), adjustments, glyphCount, font);
|
2013-10-30 15:07:03 +00:00
|
|
|
|
2018-12-24 19:52:46 +00:00
|
|
|
canvas->drawTextBlob(builder.make(), 0, 0, paint);
|
2013-10-30 15:07:03 +00:00
|
|
|
}
|
|
|
|
|
2017-11-14 15:45:32 +00:00
|
|
|
static constexpr SkFontStyle gStyles[] = {
|
|
|
|
SkFontStyle::Normal(),
|
|
|
|
SkFontStyle::Bold(),
|
|
|
|
SkFontStyle::Italic(),
|
|
|
|
SkFontStyle::BoldItalic(),
|
2012-07-27 20:39:19 +00:00
|
|
|
};
|
|
|
|
|
2017-11-14 15:45:32 +00:00
|
|
|
constexpr int gStylesCount = SK_ARRAY_COUNT(gStyles);
|
2013-02-26 16:57:16 +00:00
|
|
|
|
|
|
|
class TypefaceStylesGM : public skiagm::GM {
|
2017-11-14 15:45:32 +00:00
|
|
|
sk_sp<SkTypeface> fFaces[gStylesCount];
|
2013-10-30 15:07:03 +00:00
|
|
|
bool fApplyKerning;
|
2013-02-27 07:10:10 +00:00
|
|
|
|
2013-02-26 16:57:16 +00:00
|
|
|
public:
|
2018-07-10 23:40:15 +00:00
|
|
|
TypefaceStylesGM(bool applyKerning) : fApplyKerning(applyKerning) {}
|
2013-02-27 07:10:10 +00:00
|
|
|
|
2013-02-26 16:57:16 +00:00
|
|
|
protected:
|
2015-05-21 13:15:28 +00:00
|
|
|
void onOnceBeforeDraw() override {
|
2017-11-14 15:45:32 +00:00
|
|
|
for (int i = 0; i < gStylesCount; i++) {
|
|
|
|
fFaces[i] = SkTypeface::MakeFromName(nullptr, gStyles[i]);
|
2015-05-21 13:15:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-26 01:17:31 +00:00
|
|
|
SkString onShortName() override {
|
2013-10-30 15:07:03 +00:00
|
|
|
SkString name("typefacestyles");
|
|
|
|
if (fApplyKerning) {
|
|
|
|
name.append("_kerning");
|
|
|
|
}
|
|
|
|
return name;
|
2013-02-26 16:57:16 +00:00
|
|
|
}
|
2013-02-27 07:10:10 +00:00
|
|
|
|
2015-03-26 01:17:31 +00:00
|
|
|
SkISize onISize() override {
|
2013-02-26 16:57:16 +00:00
|
|
|
return SkISize::Make(640, 480);
|
|
|
|
}
|
2013-02-27 07:10:10 +00:00
|
|
|
|
2015-03-26 01:17:31 +00:00
|
|
|
void onDraw(SkCanvas* canvas) override {
|
2018-12-24 19:52:46 +00:00
|
|
|
SkFont font;
|
|
|
|
font.setSize(30);
|
2013-02-27 07:10:10 +00:00
|
|
|
|
2013-10-30 15:07:03 +00:00
|
|
|
const char* text = fApplyKerning ? "Type AWAY" : "Hamburgefons";
|
2013-02-26 16:57:16 +00:00
|
|
|
const size_t textLen = strlen(text);
|
2013-02-27 07:10:10 +00:00
|
|
|
|
2013-02-26 16:57:16 +00:00
|
|
|
SkScalar x = SkIntToScalar(10);
|
2018-12-24 19:52:46 +00:00
|
|
|
SkScalar dy = font.getMetrics(nullptr);
|
2013-02-26 16:57:16 +00:00
|
|
|
SkScalar y = dy;
|
2013-02-27 07:10:10 +00:00
|
|
|
|
2013-10-30 15:07:03 +00:00
|
|
|
if (fApplyKerning) {
|
2018-12-24 19:52:46 +00:00
|
|
|
font.setSubpixel(true);
|
2013-10-30 15:07:03 +00:00
|
|
|
} else {
|
2018-12-24 19:52:46 +00:00
|
|
|
font.setLinearMetrics(true);
|
2013-10-30 15:07:03 +00:00
|
|
|
}
|
2018-12-24 19:52:46 +00:00
|
|
|
|
|
|
|
SkPaint paint;
|
2017-11-14 15:45:32 +00:00
|
|
|
for (int i = 0; i < gStylesCount; i++) {
|
2018-12-24 19:52:46 +00:00
|
|
|
font.setTypeface(fFaces[i]);
|
2019-05-07 19:38:46 +00:00
|
|
|
canvas->drawSimpleText(text, textLen, SkTextEncoding::kUTF8, x, y, font, paint);
|
2013-10-30 15:07:03 +00:00
|
|
|
if (fApplyKerning) {
|
2018-12-24 19:52:46 +00:00
|
|
|
drawKernText(canvas, text, textLen, x + 240, y, font, paint);
|
2013-10-30 15:07:03 +00:00
|
|
|
}
|
2013-02-26 16:57:16 +00:00
|
|
|
y += dy;
|
|
|
|
}
|
|
|
|
}
|
2013-02-27 07:10:10 +00:00
|
|
|
|
2013-02-26 16:57:16 +00:00
|
|
|
private:
|
2020-09-03 02:42:33 +00:00
|
|
|
using INHERITED = skiagm::GM;
|
2013-02-26 16:57:16 +00:00
|
|
|
};
|
2013-02-27 07:10:10 +00:00
|
|
|
|
2016-09-20 20:11:01 +00:00
|
|
|
DEF_GM( return new TypefaceStylesGM(false); )
|
|
|
|
DEF_GM( return new TypefaceStylesGM(true); )
|
2016-07-06 18:55:05 +00:00
|
|
|
|
2016-09-20 20:11:01 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2016-07-06 18:55:05 +00:00
|
|
|
|
2020-05-01 01:13:51 +00:00
|
|
|
static void draw_typeface_rendering_gm(SkCanvas* canvas, sk_sp<SkTypeface> face, SkGlyphID glyph) {
|
2018-05-10 19:24:20 +00:00
|
|
|
struct AliasType {
|
2019-02-22 16:34:49 +00:00
|
|
|
SkFont::Edging edging;
|
2018-05-10 19:24:20 +00:00
|
|
|
bool inLayer;
|
|
|
|
} constexpr aliasTypes[] {
|
2016-07-13 21:00:39 +00:00
|
|
|
#ifndef SK_BUILD_FOR_IOS
|
2018-05-10 19:24:20 +00:00
|
|
|
// This gm crashes on iOS when drawing an embedded bitmap when requesting aliased rendering.
|
|
|
|
// The crash looks like
|
|
|
|
// libTrueTypeScaler.dylib`<redacted> + 80
|
|
|
|
// stop reason = EXC_BAD_ACCESS (code=EXC_ARM_DA_ALIGN, address=...)
|
|
|
|
// -> 0x330b19d0 <+80>: strd r2, r3, [r5, #36]
|
|
|
|
// 0x330b19d4 <+84>: movs r3, #0x0
|
|
|
|
// 0x330b19d6 <+86>: add r2, sp, #0x28
|
|
|
|
// 0x330b19d8 <+88>: ldr r0, [r4, #0x4]
|
|
|
|
// Disable testing embedded bitmaps on iOS for now.
|
|
|
|
// See https://bug.skia.org/5530 .
|
2019-02-22 16:34:49 +00:00
|
|
|
{ SkFont::Edging::kAlias , false },
|
2016-07-13 21:00:39 +00:00
|
|
|
#endif
|
2019-02-22 16:34:49 +00:00
|
|
|
{ SkFont::Edging::kAntiAlias , false },
|
|
|
|
{ SkFont::Edging::kSubpixelAntiAlias, false },
|
|
|
|
{ SkFont::Edging::kAntiAlias , true },
|
|
|
|
{ SkFont::Edging::kSubpixelAntiAlias, true },
|
2019-01-02 17:21:01 +00:00
|
|
|
};
|
|
|
|
|
2018-05-10 19:24:20 +00:00
|
|
|
// The hintgasp.ttf is designed for the following sizes to be different.
|
|
|
|
// GASP_DOGRAY 0x0002 0<=ppem<=10
|
|
|
|
// GASP_SYMMETRIC_SMOOTHING 0x0008 0<=ppem<=10
|
|
|
|
// GASP_GRIDFIT 0x0001 11<=ppem<=12
|
|
|
|
// GASP_SYMMETRIC_GRIDFIT 0x0004 11<=ppem<=12
|
|
|
|
// GASP_DOGRAY|GASP_GRIDFIT 0x0003 13<=ppem<=14
|
|
|
|
// GASP_SYMMETRIC_SMOOTHING|GASP_SYMMETRIC_GRIDFIT 0x000C 13<=ppem<=14
|
|
|
|
// (neither) 0x0000 15<=ppem
|
|
|
|
// Odd sizes have embedded bitmaps.
|
|
|
|
constexpr SkScalar textSizes[] = { 9, 10, 11, 12, 13, 14, 15, 16 };
|
|
|
|
|
2018-11-08 00:54:33 +00:00
|
|
|
constexpr SkFontHinting hintingTypes[] = {
|
2019-05-07 20:50:29 +00:00
|
|
|
SkFontHinting::kNone,
|
|
|
|
SkFontHinting::kSlight,
|
|
|
|
SkFontHinting::kNormal,
|
|
|
|
SkFontHinting::kFull
|
2018-11-08 00:54:33 +00:00
|
|
|
};
|
2018-05-10 19:24:20 +00:00
|
|
|
|
|
|
|
struct SubpixelType {
|
|
|
|
bool requested;
|
|
|
|
SkVector offset;
|
|
|
|
} constexpr subpixelTypes[] = {
|
|
|
|
{ false, { 0.00, 0.00 } },
|
|
|
|
{ true , { 0.00, 0.00 } },
|
|
|
|
{ true , { 0.25, 0.00 } },
|
|
|
|
{ true , { 0.25, 0.25 } },
|
|
|
|
};
|
|
|
|
|
|
|
|
constexpr bool rotateABitTypes[] = { false, true };
|
|
|
|
|
|
|
|
SkScalar y = 0; // The baseline of the previous output
|
|
|
|
{
|
2016-07-06 18:55:05 +00:00
|
|
|
SkPaint paint;
|
2019-01-02 17:21:01 +00:00
|
|
|
|
|
|
|
SkFont font(face);
|
|
|
|
font.setEmbeddedBitmaps(true);
|
2016-07-12 13:55:25 +00:00
|
|
|
|
2016-07-06 18:55:05 +00:00
|
|
|
SkScalar x = 0;
|
|
|
|
SkScalar xMax = x;
|
|
|
|
SkScalar xBase = 0;
|
|
|
|
for (const SubpixelType subpixel : subpixelTypes) {
|
|
|
|
y = 0;
|
2019-01-02 17:21:01 +00:00
|
|
|
font.setSubpixel(subpixel.requested);
|
2016-07-06 18:55:05 +00:00
|
|
|
|
|
|
|
for (const AliasType& alias : aliasTypes) {
|
2019-02-22 16:34:49 +00:00
|
|
|
font.setEdging(alias.edging);
|
2021-08-02 17:26:38 +00:00
|
|
|
SkAutoCanvasRestore acr1(canvas, false);
|
2016-07-06 18:55:05 +00:00
|
|
|
if (alias.inLayer) {
|
|
|
|
canvas->saveLayer(nullptr, &paint);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const SkScalar& textSize : textSizes) {
|
|
|
|
x = xBase + 5;
|
2019-01-02 17:21:01 +00:00
|
|
|
font.setSize(textSize);
|
2016-07-06 18:55:05 +00:00
|
|
|
|
2019-01-02 17:21:01 +00:00
|
|
|
SkScalar dy = SkScalarCeilToScalar(font.getMetrics(nullptr));
|
2016-07-06 18:55:05 +00:00
|
|
|
y += dy;
|
2018-11-08 00:54:33 +00:00
|
|
|
for (const SkFontHinting& hinting : hintingTypes) {
|
2019-01-02 17:21:01 +00:00
|
|
|
font.setHinting(hinting);
|
2016-07-06 18:55:05 +00:00
|
|
|
|
|
|
|
for (const bool& rotateABit : rotateABitTypes) {
|
2021-08-02 17:26:38 +00:00
|
|
|
SkAutoCanvasRestore acr2(canvas, true);
|
2016-07-06 18:55:05 +00:00
|
|
|
if (rotateABit) {
|
2016-07-12 22:01:19 +00:00
|
|
|
canvas->rotate(2, x + subpixel.offset.x(),
|
|
|
|
y + subpixel.offset.y());
|
2016-07-06 18:55:05 +00:00
|
|
|
}
|
2020-05-01 01:13:51 +00:00
|
|
|
canvas->drawSimpleText(&glyph, sizeof(glyph), SkTextEncoding::kGlyphID,
|
2019-01-02 17:21:01 +00:00
|
|
|
x + subpixel.offset.x(),
|
|
|
|
y + subpixel.offset.y(), font, paint);
|
2016-07-06 18:55:05 +00:00
|
|
|
|
2020-05-01 01:13:51 +00:00
|
|
|
SkScalar dx = SkScalarCeilToScalar(font.measureText(
|
|
|
|
&glyph, sizeof(glyph), SkTextEncoding::kGlyphID)) + 5;
|
2016-07-06 18:55:05 +00:00
|
|
|
x += dx;
|
2020-02-07 15:36:46 +00:00
|
|
|
xMax = std::max(x, xMax);
|
2016-07-06 18:55:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
y += 10;
|
|
|
|
}
|
|
|
|
xBase = xMax;
|
|
|
|
}
|
2018-05-10 19:24:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
constexpr struct StyleTests {
|
|
|
|
SkPaint::Style style;
|
|
|
|
SkScalar strokeWidth;
|
|
|
|
} styleTypes[] = {
|
|
|
|
{ SkPaint::kFill_Style, 0.0f},
|
|
|
|
{ SkPaint::kStroke_Style, 0.0f},
|
|
|
|
{ SkPaint::kStroke_Style, 0.5f},
|
|
|
|
{ SkPaint::kStrokeAndFill_Style, 1.0f},
|
|
|
|
};
|
|
|
|
|
|
|
|
constexpr bool fakeBoldTypes[] = { false, true };
|
|
|
|
|
|
|
|
{
|
|
|
|
SkPaint paint;
|
2019-01-02 17:21:01 +00:00
|
|
|
|
|
|
|
SkFont font(face, 16);
|
2018-05-10 19:24:20 +00:00
|
|
|
|
|
|
|
SkScalar x = 0;
|
|
|
|
for (const bool& fakeBold : fakeBoldTypes) {
|
2019-01-02 17:21:01 +00:00
|
|
|
SkScalar dy = SkScalarCeilToScalar(font.getMetrics(nullptr));
|
2018-05-10 19:24:20 +00:00
|
|
|
y += dy;
|
|
|
|
x = 5;
|
|
|
|
|
2019-01-02 17:21:01 +00:00
|
|
|
font.setEmbolden(fakeBold);
|
2018-05-10 19:24:20 +00:00
|
|
|
for (const AliasType& alias : aliasTypes) {
|
2019-02-22 16:34:49 +00:00
|
|
|
font.setEdging(alias.edging);
|
2018-05-10 19:24:20 +00:00
|
|
|
SkAutoCanvasRestore acr(canvas, false);
|
|
|
|
if (alias.inLayer) {
|
|
|
|
canvas->saveLayer(nullptr, &paint);
|
|
|
|
}
|
|
|
|
for (const StyleTests& style : styleTypes) {
|
|
|
|
paint.setStyle(style.style);
|
|
|
|
paint.setStrokeWidth(style.strokeWidth);
|
2020-05-01 01:13:51 +00:00
|
|
|
canvas->drawSimpleText(&glyph, sizeof(glyph), SkTextEncoding::kGlyphID,
|
|
|
|
x, y, font, paint);
|
2018-05-10 19:24:20 +00:00
|
|
|
|
2020-05-01 01:13:51 +00:00
|
|
|
SkScalar dx = SkScalarCeilToScalar(font.measureText(
|
|
|
|
&glyph, sizeof(glyph), SkTextEncoding::kGlyphID)) + 5;
|
2018-05-10 19:24:20 +00:00
|
|
|
x += dx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
y += 10;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
constexpr struct MaskTests {
|
|
|
|
SkBlurStyle style;
|
|
|
|
SkScalar sigma;
|
|
|
|
} maskTypes[] = {
|
|
|
|
{ SkBlurStyle::kNormal_SkBlurStyle, 0.0f},
|
|
|
|
{ SkBlurStyle::kSolid_SkBlurStyle, 0.0f},
|
|
|
|
{ SkBlurStyle::kOuter_SkBlurStyle, 0.0f},
|
|
|
|
{ SkBlurStyle::kInner_SkBlurStyle, 0.0f},
|
|
|
|
|
|
|
|
{ SkBlurStyle::kNormal_SkBlurStyle, 0.5f},
|
|
|
|
{ SkBlurStyle::kSolid_SkBlurStyle, 0.5f},
|
|
|
|
{ SkBlurStyle::kOuter_SkBlurStyle, 0.5f},
|
|
|
|
{ SkBlurStyle::kInner_SkBlurStyle, 0.5f},
|
|
|
|
|
|
|
|
{ SkBlurStyle::kNormal_SkBlurStyle, 2.0f},
|
|
|
|
{ SkBlurStyle::kSolid_SkBlurStyle, 2.0f},
|
|
|
|
{ SkBlurStyle::kOuter_SkBlurStyle, 2.0f},
|
|
|
|
{ SkBlurStyle::kInner_SkBlurStyle, 2.0f},
|
|
|
|
};
|
|
|
|
|
|
|
|
{
|
|
|
|
SkPaint paint;
|
2019-01-02 17:21:01 +00:00
|
|
|
|
|
|
|
SkFont font(face, 16);
|
2018-05-10 19:24:20 +00:00
|
|
|
|
|
|
|
SkScalar x = 0;
|
|
|
|
{
|
|
|
|
for (const AliasType& alias : aliasTypes) {
|
2019-01-02 17:21:01 +00:00
|
|
|
SkScalar dy = SkScalarCeilToScalar(font.getMetrics(nullptr));
|
2018-05-10 19:24:20 +00:00
|
|
|
y += dy;
|
|
|
|
x = 5;
|
|
|
|
|
2019-02-22 16:34:49 +00:00
|
|
|
font.setEdging(alias.edging);
|
2018-05-10 19:24:20 +00:00
|
|
|
SkAutoCanvasRestore acr(canvas, false);
|
|
|
|
if (alias.inLayer) {
|
|
|
|
canvas->saveLayer(nullptr, &paint);
|
|
|
|
}
|
|
|
|
for (const MaskTests& mask : maskTypes) {
|
|
|
|
paint.setMaskFilter(SkMaskFilter::MakeBlur(mask.style, mask.sigma));
|
2020-05-01 01:13:51 +00:00
|
|
|
canvas->drawSimpleText(&glyph, sizeof(glyph), SkTextEncoding::kGlyphID,
|
|
|
|
x, y, font, paint);
|
2018-05-10 19:24:20 +00:00
|
|
|
|
2020-05-01 01:13:51 +00:00
|
|
|
SkScalar dx = SkScalarCeilToScalar(font.measureText(
|
|
|
|
&glyph, sizeof(glyph), SkTextEncoding::kGlyphID)) + 5;
|
2018-05-10 19:24:20 +00:00
|
|
|
x += dx;
|
|
|
|
}
|
|
|
|
paint.setMaskFilter(nullptr);
|
|
|
|
}
|
|
|
|
y += 10;
|
|
|
|
}
|
|
|
|
}
|
2016-09-20 20:11:01 +00:00
|
|
|
}
|
|
|
|
|
2021-08-10 18:54:56 +00:00
|
|
|
DEF_SIMPLE_GM_CAN_FAIL(typefacerendering, canvas, errMsg, 640, 840) {
|
|
|
|
sk_sp<SkTypeface> face = MakeResourceAsTypeface("fonts/hintgasp.ttf");
|
|
|
|
if (!face) {
|
|
|
|
return skiagm::DrawResult::kSkip;
|
|
|
|
}
|
|
|
|
draw_typeface_rendering_gm(canvas, face, face->unicharToGlyph('A'));
|
|
|
|
|
|
|
|
// Should draw nothing and not do anything undefined.
|
|
|
|
draw_typeface_rendering_gm(canvas, face, 0xFFFF);
|
|
|
|
return skiagm::DrawResult::kOk;
|
|
|
|
}
|
2020-05-01 01:13:51 +00:00
|
|
|
|
2021-08-10 18:54:56 +00:00
|
|
|
// Type1 fonts don't currently work in Skia on Windows.
|
|
|
|
#ifndef SK_BUILD_FOR_WIN
|
|
|
|
|
|
|
|
DEF_SIMPLE_GM_CAN_FAIL(typefacerendering_pfa, canvas, errMsg, 640, 840) {
|
|
|
|
sk_sp<SkTypeface> face = MakeResourceAsTypeface("fonts/Roboto2-Regular.pfa");
|
|
|
|
if (!face) {
|
|
|
|
return skiagm::DrawResult::kSkip;
|
2016-07-06 18:55:05 +00:00
|
|
|
}
|
2021-08-10 18:54:56 +00:00
|
|
|
draw_typeface_rendering_gm(canvas, face, face->unicharToGlyph('O'));
|
|
|
|
return skiagm::DrawResult::kOk;
|
2016-09-20 20:11:01 +00:00
|
|
|
}
|
2016-07-06 18:55:05 +00:00
|
|
|
|
2021-08-10 18:54:56 +00:00
|
|
|
DEF_SIMPLE_GM_CAN_FAIL(typefacerendering_pfb, canvas, errMsg, 640, 840) {
|
|
|
|
sk_sp<SkTypeface> face = MakeResourceAsTypeface("fonts/Roboto2-Regular.pfb");
|
|
|
|
if (!face) {
|
|
|
|
return skiagm::DrawResult::kSkip;
|
|
|
|
}
|
|
|
|
draw_typeface_rendering_gm(canvas, face, face->unicharToGlyph('O'));
|
|
|
|
return skiagm::DrawResult::kOk;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2021-07-31 18:31:15 +00:00
|
|
|
#include "include/effects/SkStrokeAndFillPathEffect.h"
|
|
|
|
|
|
|
|
// Exercise different paint styles and embolden, and compare with strokeandfill patheffect
|
|
|
|
DEF_SIMPLE_GM(typeface_styling, canvas, 710, 360) {
|
2021-08-10 18:54:56 +00:00
|
|
|
sk_sp<SkTypeface> face = MakeResourceAsTypeface("fonts/Roboto-Regular.ttf");
|
|
|
|
SkFont font;
|
|
|
|
font.setTypeface(face);
|
|
|
|
font.setSize(100);
|
|
|
|
font.setEdging(SkFont::Edging::kAntiAlias);
|
2021-07-31 18:31:15 +00:00
|
|
|
|
2021-08-10 18:54:56 +00:00
|
|
|
uint16_t glyphs[1] = { font.unicharToGlyph('A') };
|
|
|
|
SkPoint pos[1] = { {0, 0} };
|
2021-07-31 18:31:15 +00:00
|
|
|
|
2021-08-10 18:54:56 +00:00
|
|
|
auto draw = [&](SkPaint::Style style, float width, sk_sp<SkPathEffect> pe) {
|
|
|
|
// Draws 3 rows:
|
|
|
|
// 1. normal
|
|
|
|
// 2. emboldened
|
|
|
|
// 3. normal(white) on top of emboldened (to show the delta)
|
2021-07-31 18:31:15 +00:00
|
|
|
|
2021-08-10 18:54:56 +00:00
|
|
|
SkPaint paint;
|
|
|
|
paint.setStyle(style);
|
|
|
|
paint.setStrokeWidth(width);
|
|
|
|
paint.setPathEffect(pe);
|
|
|
|
|
|
|
|
font.setEmbolden(true);
|
|
|
|
canvas->drawGlyphs(1, glyphs, pos, {20, 120*2}, font, paint);
|
|
|
|
canvas->drawGlyphs(1, glyphs, pos, {20, 120*3}, font, paint);
|
|
|
|
|
|
|
|
font.setEmbolden(false);
|
|
|
|
canvas->drawGlyphs(1, glyphs, pos, {20, 120*1}, font, paint);
|
|
|
|
paint.setColor(SK_ColorYELLOW);
|
|
|
|
canvas->drawGlyphs(1, glyphs, pos, {20, 120*3}, font, paint);
|
|
|
|
};
|
2016-09-20 20:11:01 +00:00
|
|
|
|
2021-08-10 18:54:56 +00:00
|
|
|
const struct {
|
|
|
|
SkPaint::Style style;
|
|
|
|
float width;
|
|
|
|
bool usePE;
|
|
|
|
} recs[] = {
|
|
|
|
{ SkPaint::kFill_Style, 0, false },
|
|
|
|
{ SkPaint::kStroke_Style, 0, false },
|
|
|
|
{ SkPaint::kStroke_Style, 3, false },
|
|
|
|
{ SkPaint::kStrokeAndFill_Style, 0, false },
|
|
|
|
{ SkPaint::kStrokeAndFill_Style, 3, false },
|
|
|
|
{ SkPaint::kStroke_Style, 0, true },
|
|
|
|
{ SkPaint::kStroke_Style, 3, true },
|
|
|
|
};
|
2016-07-06 18:55:05 +00:00
|
|
|
|
2021-08-10 18:54:56 +00:00
|
|
|
canvas->translate(0, -20);
|
|
|
|
auto pe = SkStrokeAndFillPathEffect::Make();
|
|
|
|
for (auto r : recs) {
|
|
|
|
draw(r.style, r.width, r.usePE ? pe : nullptr);
|
|
|
|
canvas->translate(100, 0);
|
2016-09-20 20:11:01 +00:00
|
|
|
}
|
|
|
|
}
|