blob: 4dde8b8f1b8a59d699db5172da0b5cb312fd06d8 [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
19void SkSVGText::setX(const SkSVGLength& x) { fX = x; }
20
21void SkSVGText::setY(const SkSVGLength& y) { fY = y; }
22
Xavier Phane29cdaf2020-03-26 16:15:14 +000023void SkSVGText::setText(const SkSVGStringType& text) { fText = text; }
24
25void SkSVGText::setTextAnchor(const SkSVGStringType& text_anchor) {
Florin Malitaa3626692020-04-09 14:36:45 -040026 if (strcmp(text_anchor.c_str(), "start") == 0) {
Xavier Phane29cdaf2020-03-26 16:15:14 +000027 fTextAlign = SkTextUtils::Align::kLeft_Align;
Florin Malitaa3626692020-04-09 14:36:45 -040028 } else if (strcmp(text_anchor.c_str(), "middle") == 0) {
Xavier Phane29cdaf2020-03-26 16:15:14 +000029 fTextAlign = SkTextUtils::Align::kCenter_Align;
Florin Malitaa3626692020-04-09 14:36:45 -040030 } else if (strcmp(text_anchor.c_str(), "end") == 0) {
Xavier Phane29cdaf2020-03-26 16:15:14 +000031 fTextAlign = SkTextUtils::Align::kRight_Align;
32 }
33}
34
Florin Malita39fe8c82020-10-20 10:43:03 -040035SkFont SkSVGText::resolveFont(const SkSVGRenderContext& ctx) const {
36 auto weight = [](const SkSVGFontWeight& w) {
37 switch (w.type()) {
38 case SkSVGFontWeight::Type::k100: return SkFontStyle::kThin_Weight;
39 case SkSVGFontWeight::Type::k200: return SkFontStyle::kExtraLight_Weight;
40 case SkSVGFontWeight::Type::k300: return SkFontStyle::kLight_Weight;
41 case SkSVGFontWeight::Type::k400: return SkFontStyle::kNormal_Weight;
42 case SkSVGFontWeight::Type::k500: return SkFontStyle::kMedium_Weight;
43 case SkSVGFontWeight::Type::k600: return SkFontStyle::kSemiBold_Weight;
44 case SkSVGFontWeight::Type::k700: return SkFontStyle::kBold_Weight;
45 case SkSVGFontWeight::Type::k800: return SkFontStyle::kExtraBold_Weight;
46 case SkSVGFontWeight::Type::k900: return SkFontStyle::kBlack_Weight;
47 case SkSVGFontWeight::Type::kNormal: return SkFontStyle::kNormal_Weight;
48 case SkSVGFontWeight::Type::kBold: return SkFontStyle::kBold_Weight;
49 case SkSVGFontWeight::Type::kBolder: return SkFontStyle::kExtraBold_Weight;
50 case SkSVGFontWeight::Type::kLighter: return SkFontStyle::kLight_Weight;
51 case SkSVGFontWeight::Type::kInherit: {
52 SkASSERT(false);
53 return SkFontStyle::kNormal_Weight;
54 }
55 }
56 SkUNREACHABLE;
57 };
58
59 auto slant = [](const SkSVGFontStyle& s) {
60 switch (s.type()) {
61 case SkSVGFontStyle::Type::kNormal: return SkFontStyle::kUpright_Slant;
62 case SkSVGFontStyle::Type::kItalic: return SkFontStyle::kItalic_Slant;
63 case SkSVGFontStyle::Type::kOblique: return SkFontStyle::kOblique_Slant;
64 case SkSVGFontStyle::Type::kInherit: {
65 SkASSERT(false);
66 return SkFontStyle::kUpright_Slant;
67 }
68 }
69 SkUNREACHABLE;
70 };
71
72 const auto& family = ctx.presentationContext().fInherited.fFontFamily->family();
73 const SkFontStyle style(weight(*ctx.presentationContext().fInherited.fFontWeight),
74 SkFontStyle::kNormal_Width,
75 slant(*ctx.presentationContext().fInherited.fFontStyle));
76
77 const auto size =
78 ctx.lengthContext().resolve(ctx.presentationContext().fInherited.fFontSize->size(),
79 SkSVGLengthContext::LengthType::kVertical);
80
81 // TODO: allow clients to pass an external fontmgr.
82 SkFont font(SkTypeface::MakeFromName(family.c_str(), style), size);
83 font.setHinting(SkFontHinting::kNone);
84 font.setSubpixel(true);
85 font.setLinearMetrics(true);
86 font.setBaselineSnap(false);
87 font.setEdging(SkFont::Edging::kAntiAlias);
88
89 return font;
90}
91
92void SkSVGText::onRender(const SkSVGRenderContext& ctx) const {
93 const auto font = this->resolveFont(ctx);
94
95 if (const SkPaint* fillPaint = ctx.fillPaint()) {
96 SkTextUtils::DrawString(ctx.canvas(), fText.c_str(), fX.value(), fY.value(), font,
97 *fillPaint, fTextAlign);
98 }
99
100 if (const SkPaint* strokePaint = ctx.strokePaint()) {
101 SkTextUtils::DrawString(ctx.canvas(), fText.c_str(), fX.value(), fY.value(), font,
102 *strokePaint, fTextAlign);
103 }
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;
132 case SkSVGAttribute::kTextAnchor:
Florin Malitaf4403e72020-04-10 14:14:04 +0000133 if (const auto* text_anchor = v.as<SkSVGStringValue>()) {
Xavier Phane29cdaf2020-03-26 16:15:14 +0000134 this->setTextAnchor(*text_anchor);
135 }
136 break;
Tyler Freemane9663db2020-04-14 14:37:13 -0700137 break;
Xavier Phane29cdaf2020-03-26 16:15:14 +0000138 default:
139 this->INHERITED::onSetAttribute(attr, v);
140 }
141}