blob: 6cbf5d6d404333a564b2c738090fa44add2b6438 [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
65 // TODO: allow clients to pass an external fontmgr.
66 SkFont font(SkTypeface::MakeFromName(family.c_str(), style), size);
67 font.setHinting(SkFontHinting::kNone);
68 font.setSubpixel(true);
69 font.setLinearMetrics(true);
70 font.setBaselineSnap(false);
71 font.setEdging(SkFont::Edging::kAntiAlias);
72
73 return font;
74}
75
76void SkSVGText::onRender(const SkSVGRenderContext& ctx) const {
77 const auto font = this->resolveFont(ctx);
78
Florin Malita056385b2020-10-27 22:57:56 -040079 const auto text_align = [](const SkSVGTextAnchor& anchor) {
80 switch (anchor.type()) {
81 case SkSVGTextAnchor::Type::kStart : return SkTextUtils::Align::kLeft_Align;
82 case SkSVGTextAnchor::Type::kMiddle: return SkTextUtils::Align::kCenter_Align;
83 case SkSVGTextAnchor::Type::kEnd : return SkTextUtils::Align::kRight_Align;
84 case SkSVGTextAnchor::Type::kInherit:
85 SkASSERT(false);
86 return SkTextUtils::Align::kLeft_Align;
87 }
88 SkUNREACHABLE;
89 };
90
91 const auto align = text_align(*ctx.presentationContext().fInherited.fTextAnchor);
Florin Malita39fe8c82020-10-20 10:43:03 -040092 if (const SkPaint* fillPaint = ctx.fillPaint()) {
93 SkTextUtils::DrawString(ctx.canvas(), fText.c_str(), fX.value(), fY.value(), font,
Florin Malita056385b2020-10-27 22:57:56 -040094 *fillPaint, align);
Florin Malita39fe8c82020-10-20 10:43:03 -040095 }
96
97 if (const SkPaint* strokePaint = ctx.strokePaint()) {
98 SkTextUtils::DrawString(ctx.canvas(), fText.c_str(), fX.value(), fY.value(), font,
Florin Malita056385b2020-10-27 22:57:56 -040099 *strokePaint, align);
Florin Malita39fe8c82020-10-20 10:43:03 -0400100 }
101}
102
103void SkSVGText::appendChild(sk_sp<SkSVGNode>) {
104 // TODO
Xavier Phane29cdaf2020-03-26 16:15:14 +0000105}
106
107SkPath SkSVGText::onAsPath(const SkSVGRenderContext& ctx) const {
108 SkPath path;
109 return path;
110}
111
Florin Malitaf4403e72020-04-10 14:14:04 +0000112void SkSVGText::onSetAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
Xavier Phane29cdaf2020-03-26 16:15:14 +0000113 switch (attr) {
114 case SkSVGAttribute::kX:
Florin Malitaf4403e72020-04-10 14:14:04 +0000115 if (const auto* x = v.as<SkSVGLengthValue>()) {
Xavier Phane29cdaf2020-03-26 16:15:14 +0000116 this->setX(*x);
117 }
118 break;
119 case SkSVGAttribute::kY:
Florin Malitaf4403e72020-04-10 14:14:04 +0000120 if (const auto* y = v.as<SkSVGLengthValue>()) {
Xavier Phane29cdaf2020-03-26 16:15:14 +0000121 this->setY(*y);
122 }
123 break;
124 case SkSVGAttribute::kText:
Florin Malitaf4403e72020-04-10 14:14:04 +0000125 if (const auto* text = v.as<SkSVGStringValue>()) {
Xavier Phane29cdaf2020-03-26 16:15:14 +0000126 this->setText(*text);
127 }
128 break;
Xavier Phane29cdaf2020-03-26 16:15:14 +0000129 default:
130 this->INHERITED::onSetAttribute(attr, v);
131 }
132}