blob: 357e77881bb158194ef325293b6add33ab9ed4a1 [file] [log] [blame]
Xavier Phane29cdaf2020-03-26 16:15:14 +00001/*
2 * Copyright 2019 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Florin Malitab3418102020-10-15 18:10:29 -04008#include "modules/svg/include/SkSVGText.h"
Xavier Phane29cdaf2020-03-26 16:15:14 +00009
Xavier Phane29cdaf2020-03-26 16:15:14 +000010#include "include/core/SkCanvas.h"
Florin Malita39fe8c82020-10-20 10:43:03 -040011#include "include/core/SkFontMgr.h"
Tyler Freemane9663db2020-04-14 14:37:13 -070012#include "include/core/SkFontStyle.h"
13#include "include/core/SkString.h"
Florin Malitab3418102020-10-15 18:10:29 -040014#include "modules/svg/include/SkSVGRenderContext.h"
15#include "modules/svg/include/SkSVGValue.h"
Xavier Phane29cdaf2020-03-26 16:15:14 +000016
17SkSVGText::SkSVGText() : INHERITED(SkSVGTag::kText) {}
18
Florin Malita39fe8c82020-10-20 10:43:03 -040019SkFont SkSVGText::resolveFont(const SkSVGRenderContext& ctx) const {
20 auto weight = [](const SkSVGFontWeight& w) {
21 switch (w.type()) {
22 case SkSVGFontWeight::Type::k100: return SkFontStyle::kThin_Weight;
23 case SkSVGFontWeight::Type::k200: return SkFontStyle::kExtraLight_Weight;
24 case SkSVGFontWeight::Type::k300: return SkFontStyle::kLight_Weight;
25 case SkSVGFontWeight::Type::k400: return SkFontStyle::kNormal_Weight;
26 case SkSVGFontWeight::Type::k500: return SkFontStyle::kMedium_Weight;
27 case SkSVGFontWeight::Type::k600: return SkFontStyle::kSemiBold_Weight;
28 case SkSVGFontWeight::Type::k700: return SkFontStyle::kBold_Weight;
29 case SkSVGFontWeight::Type::k800: return SkFontStyle::kExtraBold_Weight;
30 case SkSVGFontWeight::Type::k900: return SkFontStyle::kBlack_Weight;
31 case SkSVGFontWeight::Type::kNormal: return SkFontStyle::kNormal_Weight;
32 case SkSVGFontWeight::Type::kBold: return SkFontStyle::kBold_Weight;
33 case SkSVGFontWeight::Type::kBolder: return SkFontStyle::kExtraBold_Weight;
34 case SkSVGFontWeight::Type::kLighter: return SkFontStyle::kLight_Weight;
35 case SkSVGFontWeight::Type::kInherit: {
36 SkASSERT(false);
37 return SkFontStyle::kNormal_Weight;
38 }
39 }
40 SkUNREACHABLE;
41 };
42
43 auto slant = [](const SkSVGFontStyle& s) {
44 switch (s.type()) {
45 case SkSVGFontStyle::Type::kNormal: return SkFontStyle::kUpright_Slant;
46 case SkSVGFontStyle::Type::kItalic: return SkFontStyle::kItalic_Slant;
47 case SkSVGFontStyle::Type::kOblique: return SkFontStyle::kOblique_Slant;
48 case SkSVGFontStyle::Type::kInherit: {
49 SkASSERT(false);
50 return SkFontStyle::kUpright_Slant;
51 }
52 }
53 SkUNREACHABLE;
54 };
55
56 const auto& family = ctx.presentationContext().fInherited.fFontFamily->family();
57 const SkFontStyle style(weight(*ctx.presentationContext().fInherited.fFontWeight),
58 SkFontStyle::kNormal_Width,
59 slant(*ctx.presentationContext().fInherited.fFontStyle));
60
61 const auto size =
62 ctx.lengthContext().resolve(ctx.presentationContext().fInherited.fFontSize->size(),
63 SkSVGLengthContext::LengthType::kVertical);
64
Florin Malita7006e152020-11-10 15:24:59 -050065 // TODO: we likely want matchFamilyStyle here, but switching away from legacyMakeTypeface
66 // changes all the results when using the default fontmgr.
67 auto tf = ctx.fontMgr()->legacyMakeTypeface(family.c_str(), style);
68
69 SkFont font(std::move(tf), size);
Florin Malita39fe8c82020-10-20 10:43:03 -040070 font.setHinting(SkFontHinting::kNone);
71 font.setSubpixel(true);
72 font.setLinearMetrics(true);
73 font.setBaselineSnap(false);
74 font.setEdging(SkFont::Edging::kAntiAlias);
75
76 return font;
77}
78
79void SkSVGText::onRender(const SkSVGRenderContext& ctx) const {
80 const auto font = this->resolveFont(ctx);
81
Florin Malita056385b2020-10-27 22:57:56 -040082 const auto text_align = [](const SkSVGTextAnchor& anchor) {
83 switch (anchor.type()) {
84 case SkSVGTextAnchor::Type::kStart : return SkTextUtils::Align::kLeft_Align;
85 case SkSVGTextAnchor::Type::kMiddle: return SkTextUtils::Align::kCenter_Align;
86 case SkSVGTextAnchor::Type::kEnd : return SkTextUtils::Align::kRight_Align;
87 case SkSVGTextAnchor::Type::kInherit:
88 SkASSERT(false);
89 return SkTextUtils::Align::kLeft_Align;
90 }
91 SkUNREACHABLE;
92 };
93
94 const auto align = text_align(*ctx.presentationContext().fInherited.fTextAnchor);
Florin Malita39fe8c82020-10-20 10:43:03 -040095 if (const SkPaint* fillPaint = ctx.fillPaint()) {
96 SkTextUtils::DrawString(ctx.canvas(), fText.c_str(), fX.value(), fY.value(), font,
Florin Malita056385b2020-10-27 22:57:56 -040097 *fillPaint, align);
Florin Malita39fe8c82020-10-20 10:43:03 -040098 }
99
100 if (const SkPaint* strokePaint = ctx.strokePaint()) {
101 SkTextUtils::DrawString(ctx.canvas(), fText.c_str(), fX.value(), fY.value(), font,
Florin Malita056385b2020-10-27 22:57:56 -0400102 *strokePaint, align);
Florin Malita39fe8c82020-10-20 10:43:03 -0400103 }
104}
105
106void SkSVGText::appendChild(sk_sp<SkSVGNode>) {
107 // TODO
Xavier Phane29cdaf2020-03-26 16:15:14 +0000108}
109
110SkPath SkSVGText::onAsPath(const SkSVGRenderContext& ctx) const {
111 SkPath path;
112 return path;
113}
114
Florin Malitaf4403e72020-04-10 14:14:04 +0000115void SkSVGText::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
Xavier Phane29cdaf2020-03-26 16:15:14 +0000116 switch (attr) {
117 case SkSVGAttribute::kX:
Florin Malitaf4403e72020-04-10 14:14:04 +0000118 if (const auto* x = v.as<SkSVGLengthValue>()) {
Xavier Phane29cdaf2020-03-26 16:15:14 +0000119 this->setX(*x);
120 }
121 break;
122 case SkSVGAttribute::kY:
Florin Malitaf4403e72020-04-10 14:14:04 +0000123 if (const auto* y = v.as<SkSVGLengthValue>()) {
Xavier Phane29cdaf2020-03-26 16:15:14 +0000124 this->setY(*y);
125 }
126 break;
127 case SkSVGAttribute::kText:
Florin Malitaf4403e72020-04-10 14:14:04 +0000128 if (const auto* text = v.as<SkSVGStringValue>()) {
Xavier Phane29cdaf2020-03-26 16:15:14 +0000129 this->setText(*text);
130 }
131 break;
Xavier Phane29cdaf2020-03-26 16:15:14 +0000132 default:
133 this->INHERITED::onSetAttribute(attr, v);
134 }
135}