TestSVGTypeface.cpp 58 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442
  1. /*
  2. * Copyright 2014 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. #include "tools/fonts/TestSVGTypeface.h"
  8. #ifdef SK_XML
  9. #include "experimental/svg/model/SkSVGDOM.h"
  10. #include "include/core/SkBitmap.h"
  11. #include "include/core/SkCanvas.h"
  12. #include "include/core/SkColor.h"
  13. #include "include/core/SkData.h"
  14. #include "include/core/SkEncodedImageFormat.h"
  15. #include "include/core/SkFontStyle.h"
  16. #include "include/core/SkImage.h"
  17. #include "include/core/SkImageInfo.h"
  18. #include "include/core/SkMatrix.h"
  19. #include "include/core/SkPath.h"
  20. #include "include/core/SkPathEffect.h"
  21. #include "include/core/SkPixmap.h"
  22. #include "include/core/SkRRect.h"
  23. #include "include/core/SkSize.h"
  24. #include "include/core/SkStream.h"
  25. #include "include/core/SkSurface.h"
  26. #include "include/pathops/SkPathOps.h"
  27. #include "include/private/SkTDArray.h"
  28. #include "include/private/SkTemplates.h"
  29. #include "include/utils/SkNoDrawCanvas.h"
  30. #include "src/core/SkAdvancedTypefaceMetrics.h"
  31. #include "src/core/SkFontDescriptor.h"
  32. #include "src/core/SkFontPriv.h"
  33. #include "src/core/SkGeometry.h"
  34. #include "src/core/SkGlyph.h"
  35. #include "src/core/SkMask.h"
  36. #include "src/core/SkPaintPriv.h"
  37. #include "src/core/SkPathPriv.h"
  38. #include "src/core/SkPointPriv.h"
  39. #include "src/core/SkScalerContext.h"
  40. #include "src/core/SkUtils.h"
  41. #include "src/sfnt/SkOTUtils.h"
  42. #include "tools/Resources.h"
  43. #include <utility>
  44. class SkDescriptor;
  45. TestSVGTypeface::TestSVGTypeface(const char* name,
  46. int upem,
  47. const SkFontMetrics& fontMetrics,
  48. SkSpan<const SkSVGTestTypefaceGlyphData> data,
  49. const SkFontStyle& style)
  50. : SkTypeface(style, false)
  51. , fName(name)
  52. , fUpem(upem)
  53. , fFontMetrics(fontMetrics)
  54. , fGlyphs(new Glyph[data.size()])
  55. , fGlyphCount(data.size()) {
  56. for (size_t i = 0; i < data.size(); ++i) {
  57. const SkSVGTestTypefaceGlyphData& datum = data[i];
  58. fCMap.set(datum.fUnicode, i);
  59. fGlyphs[i].fAdvance = datum.fAdvance;
  60. fGlyphs[i].fOrigin = datum.fOrigin;
  61. fGlyphs[i].fResourcePath = datum.fSvgResourcePath;
  62. }
  63. }
  64. template <typename Fn>
  65. void TestSVGTypeface::Glyph::withSVG(Fn&& fn) const {
  66. SkAutoMutexExclusive lock(fSvgMutex);
  67. if (!fParsedSvg) {
  68. fParsedSvg = true;
  69. std::unique_ptr<SkStreamAsset> stream = GetResourceAsStream(fResourcePath);
  70. if (!stream) {
  71. return;
  72. }
  73. sk_sp<SkSVGDOM> svg = SkSVGDOM::MakeFromStream(*stream.get());
  74. if (!svg) {
  75. return;
  76. }
  77. if (svg->containerSize().isEmpty()) {
  78. return;
  79. }
  80. fSvg = std::move(svg);
  81. }
  82. if (fSvg) {
  83. fn(*fSvg);
  84. }
  85. }
  86. SkSize TestSVGTypeface::Glyph::size() const {
  87. SkSize size = SkSize::MakeEmpty();
  88. this->withSVG([&](const SkSVGDOM& svg){
  89. size = svg.containerSize();
  90. });
  91. return size;
  92. }
  93. void TestSVGTypeface::Glyph::render(SkCanvas* canvas) const {
  94. this->withSVG([&](const SkSVGDOM& svg){
  95. svg.render(canvas);
  96. });
  97. }
  98. TestSVGTypeface::~TestSVGTypeface() {}
  99. TestSVGTypeface::Glyph::Glyph() : fOrigin{0, 0}, fAdvance(0) {}
  100. TestSVGTypeface::Glyph::~Glyph() {}
  101. void TestSVGTypeface::getAdvance(SkGlyph* glyph) const {
  102. SkGlyphID glyphID = glyph->getGlyphID();
  103. glyphID = glyphID < fGlyphCount ? glyphID : 0;
  104. glyph->fAdvanceX = fGlyphs[glyphID].fAdvance;
  105. glyph->fAdvanceY = 0;
  106. }
  107. void TestSVGTypeface::getFontMetrics(SkFontMetrics* metrics) const { *metrics = fFontMetrics; }
  108. void TestSVGTypeface::onFilterRec(SkScalerContextRec* rec) const {
  109. rec->setHinting(SkFontHinting::kNone);
  110. }
  111. void TestSVGTypeface::getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const {
  112. SkDEBUGCODE(unsigned glyphCount = this->countGlyphs());
  113. fCMap.foreach ([=](const SkUnichar& c, const SkGlyphID& g) {
  114. SkASSERT(g < glyphCount);
  115. glyphToUnicode[g] = c;
  116. });
  117. }
  118. std::unique_ptr<SkAdvancedTypefaceMetrics> TestSVGTypeface::onGetAdvancedMetrics() const {
  119. std::unique_ptr<SkAdvancedTypefaceMetrics> info(new SkAdvancedTypefaceMetrics);
  120. info->fFontName = fName;
  121. return info;
  122. }
  123. void TestSVGTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
  124. desc->setFamilyName(fName.c_str());
  125. desc->setStyle(this->fontStyle());
  126. *isLocal = false;
  127. }
  128. void TestSVGTypeface::onCharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const {
  129. for (int i = 0; i < count; i++) {
  130. SkGlyphID* g = fCMap.find(uni[i]);
  131. glyphs[i] = g ? *g : 0;
  132. }
  133. }
  134. void TestSVGTypeface::onGetFamilyName(SkString* familyName) const { *familyName = fName; }
  135. SkTypeface::LocalizedStrings* TestSVGTypeface::onCreateFamilyNameIterator() const {
  136. SkString familyName(fName);
  137. SkString language("und"); // undetermined
  138. return new SkOTUtils::LocalizedStrings_SingleName(familyName, language);
  139. }
  140. class SkTestSVGScalerContext : public SkScalerContext {
  141. public:
  142. SkTestSVGScalerContext(sk_sp<TestSVGTypeface> face,
  143. const SkScalerContextEffects& effects,
  144. const SkDescriptor* desc)
  145. : SkScalerContext(std::move(face), effects, desc) {
  146. fRec.getSingleMatrix(&fMatrix);
  147. SkScalar upem = this->getTestSVGTypeface()->fUpem;
  148. fMatrix.preScale(1.f / upem, 1.f / upem);
  149. }
  150. protected:
  151. TestSVGTypeface* getTestSVGTypeface() const {
  152. return static_cast<TestSVGTypeface*>(this->getTypeface());
  153. }
  154. unsigned generateGlyphCount() override { return this->getTestSVGTypeface()->countGlyphs(); }
  155. bool generateAdvance(SkGlyph* glyph) override {
  156. this->getTestSVGTypeface()->getAdvance(glyph);
  157. const SkVector advance =
  158. fMatrix.mapXY(SkFloatToScalar(glyph->fAdvanceX), SkFloatToScalar(glyph->fAdvanceY));
  159. glyph->fAdvanceX = SkScalarToFloat(advance.fX);
  160. glyph->fAdvanceY = SkScalarToFloat(advance.fY);
  161. return true;
  162. }
  163. void generateMetrics(SkGlyph* glyph) override {
  164. SkGlyphID glyphID = glyph->getGlyphID();
  165. glyphID = glyphID < this->getTestSVGTypeface()->fGlyphCount ? glyphID : 0;
  166. glyph->zeroMetrics();
  167. glyph->fMaskFormat = SkMask::kARGB32_Format;
  168. this->generateAdvance(glyph);
  169. TestSVGTypeface::Glyph& glyphData = this->getTestSVGTypeface()->fGlyphs[glyphID];
  170. SkSize containerSize = glyphData.size();
  171. SkRect newBounds = SkRect::MakeXYWH(glyphData.fOrigin.fX,
  172. -glyphData.fOrigin.fY,
  173. containerSize.fWidth,
  174. containerSize.fHeight);
  175. fMatrix.mapRect(&newBounds);
  176. SkScalar dx = SkFixedToScalar(glyph->getSubXFixed());
  177. SkScalar dy = SkFixedToScalar(glyph->getSubYFixed());
  178. newBounds.offset(dx, dy);
  179. SkIRect ibounds;
  180. newBounds.roundOut(&ibounds);
  181. glyph->fLeft = ibounds.fLeft;
  182. glyph->fTop = ibounds.fTop;
  183. glyph->fWidth = ibounds.width();
  184. glyph->fHeight = ibounds.height();
  185. }
  186. void generateImage(const SkGlyph& glyph) override {
  187. SkGlyphID glyphID = glyph.getGlyphID();
  188. glyphID = glyphID < this->getTestSVGTypeface()->fGlyphCount ? glyphID : 0;
  189. SkBitmap bm;
  190. // TODO: this should be SkImageInfo::MakeS32 when that passes all the tests.
  191. bm.installPixels(SkImageInfo::MakeN32(glyph.fWidth, glyph.fHeight, kPremul_SkAlphaType),
  192. glyph.fImage,
  193. glyph.rowBytes());
  194. bm.eraseColor(0);
  195. TestSVGTypeface::Glyph& glyphData = this->getTestSVGTypeface()->fGlyphs[glyphID];
  196. SkScalar dx = SkFixedToScalar(glyph.getSubXFixed());
  197. SkScalar dy = SkFixedToScalar(glyph.getSubYFixed());
  198. SkCanvas canvas(bm);
  199. canvas.translate(-glyph.fLeft, -glyph.fTop);
  200. canvas.translate(dx, dy);
  201. canvas.concat(fMatrix);
  202. canvas.translate(glyphData.fOrigin.fX, -glyphData.fOrigin.fY);
  203. glyphData.render(&canvas);
  204. }
  205. bool generatePath(SkGlyphID glyph, SkPath* path) override {
  206. path->reset();
  207. return false;
  208. }
  209. void generateFontMetrics(SkFontMetrics* metrics) override {
  210. this->getTestSVGTypeface()->getFontMetrics(metrics);
  211. SkFontPriv::ScaleFontMetrics(metrics, fMatrix.getScaleY());
  212. }
  213. private:
  214. SkMatrix fMatrix;
  215. };
  216. SkScalerContext* TestSVGTypeface::onCreateScalerContext(const SkScalerContextEffects& e,
  217. const SkDescriptor* desc) const {
  218. return new SkTestSVGScalerContext(sk_ref_sp(const_cast<TestSVGTypeface*>(this)), e, desc);
  219. }
  220. sk_sp<TestSVGTypeface> TestSVGTypeface::Default() {
  221. // Recommended that the first four be .notdef, .null, CR, space
  222. constexpr const static SkSVGTestTypefaceGlyphData glyphs[] = {
  223. {"fonts/svg/notdef.svg", {100, 800}, 800, 0x0}, // .notdef
  224. {"fonts/svg/empty.svg", {0, 0}, 800, 0x0020}, // space
  225. {"fonts/svg/diamond.svg", {100, 800}, 800, 0x2662}, // ♢
  226. {"fonts/svg/smile.svg", {0, 800}, 800, 0x1F600}, // 😀
  227. };
  228. SkFontMetrics metrics;
  229. metrics.fFlags = SkFontMetrics::kUnderlineThicknessIsValid_Flag |
  230. SkFontMetrics::kUnderlinePositionIsValid_Flag |
  231. SkFontMetrics::kStrikeoutThicknessIsValid_Flag |
  232. SkFontMetrics::kStrikeoutPositionIsValid_Flag;
  233. metrics.fTop = -800;
  234. metrics.fAscent = -800;
  235. metrics.fDescent = 200;
  236. metrics.fBottom = 200;
  237. metrics.fLeading = 100;
  238. metrics.fAvgCharWidth = 1000;
  239. metrics.fMaxCharWidth = 1000;
  240. metrics.fXMin = 0;
  241. metrics.fXMax = 1000;
  242. metrics.fXHeight = 500;
  243. metrics.fCapHeight = 700;
  244. metrics.fUnderlineThickness = 40;
  245. metrics.fUnderlinePosition = 20;
  246. metrics.fStrikeoutThickness = 20;
  247. metrics.fStrikeoutPosition = -400;
  248. class DefaultTypeface : public TestSVGTypeface {
  249. using TestSVGTypeface::TestSVGTypeface;
  250. bool getPathOp(SkColor color, SkPathOp* op) const override {
  251. if ((SkColorGetR(color) + SkColorGetG(color) + SkColorGetB(color)) / 3 > 0x20) {
  252. *op = SkPathOp::kDifference_SkPathOp;
  253. } else {
  254. *op = SkPathOp::kUnion_SkPathOp;
  255. }
  256. return true;
  257. }
  258. };
  259. return sk_make_sp<DefaultTypeface>("Emoji",
  260. 1000,
  261. metrics,
  262. SkMakeSpan(glyphs),
  263. SkFontStyle::Normal());
  264. }
  265. sk_sp<TestSVGTypeface> TestSVGTypeface::Planets() {
  266. // Recommended that the first four be .notdef, .null, CR, space
  267. constexpr const static SkSVGTestTypefaceGlyphData glyphs[] = {
  268. {"fonts/svg/planets/pluto.svg", {0, 20}, 60, 0x0}, // .notdef
  269. {"fonts/svg/empty.svg", {0, 0}, 400, 0x0020}, // space
  270. {"fonts/svg/planets/mercury.svg", {0, 45}, 120, 0x263F}, // ☿
  271. {"fonts/svg/planets/venus.svg", {0, 100}, 240, 0x2640}, // ♀
  272. {"fonts/svg/planets/earth.svg", {0, 100}, 240, 0x2641}, // ♁
  273. {"fonts/svg/planets/mars.svg", {0, 50}, 130, 0x2642}, // ♂
  274. {"fonts/svg/planets/jupiter.svg", {0, 1000}, 2200, 0x2643}, // ♃
  275. {"fonts/svg/planets/saturn.svg", {-300, 1500}, 2600, 0x2644}, // ♄
  276. {"fonts/svg/planets/uranus.svg", {0, 375}, 790, 0x2645}, // ♅
  277. {"fonts/svg/planets/neptune.svg", {0, 350}, 740, 0x2646}, // ♆
  278. };
  279. SkFontMetrics metrics;
  280. metrics.fFlags = SkFontMetrics::kUnderlineThicknessIsValid_Flag |
  281. SkFontMetrics::kUnderlinePositionIsValid_Flag |
  282. SkFontMetrics::kStrikeoutThicknessIsValid_Flag |
  283. SkFontMetrics::kStrikeoutPositionIsValid_Flag;
  284. metrics.fTop = -1500;
  285. metrics.fAscent = -200;
  286. metrics.fDescent = 50;
  287. metrics.fBottom = 1558;
  288. metrics.fLeading = 10;
  289. metrics.fAvgCharWidth = 200;
  290. metrics.fMaxCharWidth = 200;
  291. metrics.fXMin = -300;
  292. metrics.fXMax = 2566;
  293. metrics.fXHeight = 100;
  294. metrics.fCapHeight = 180;
  295. metrics.fUnderlineThickness = 8;
  296. metrics.fUnderlinePosition = 2;
  297. metrics.fStrikeoutThickness = 2;
  298. metrics.fStrikeoutPosition = -80;
  299. class PlanetTypeface : public TestSVGTypeface {
  300. using TestSVGTypeface::TestSVGTypeface;
  301. bool getPathOp(SkColor color, SkPathOp* op) const override {
  302. *op = SkPathOp::kUnion_SkPathOp;
  303. return true;
  304. }
  305. };
  306. return sk_make_sp<PlanetTypeface>("Planets",
  307. 200,
  308. metrics,
  309. SkMakeSpan(glyphs),
  310. SkFontStyle::Normal());
  311. }
  312. void TestSVGTypeface::exportTtxCommon(SkWStream* out,
  313. const char* type,
  314. const SkTArray<GlyfInfo>* glyfInfo) const {
  315. int totalGlyphs = fGlyphCount;
  316. out->writeText(" <GlyphOrder>\n");
  317. for (int i = 0; i < fGlyphCount; ++i) {
  318. out->writeText(" <GlyphID name=\"glyf");
  319. out->writeHexAsText(i, 4);
  320. out->writeText("\"/>\n");
  321. }
  322. if (glyfInfo) {
  323. for (int i = 0; i < fGlyphCount; ++i) {
  324. for (int j = 0; j < (*glyfInfo)[i].fLayers.count(); ++j) {
  325. out->writeText(" <GlyphID name=\"glyf");
  326. out->writeHexAsText(i, 4);
  327. out->writeText("l");
  328. out->writeHexAsText(j, 4);
  329. out->writeText("\"/>\n");
  330. ++totalGlyphs;
  331. }
  332. }
  333. }
  334. out->writeText(" </GlyphOrder>\n");
  335. out->writeText(" <head>\n");
  336. out->writeText(" <tableVersion value=\"1.0\"/>\n");
  337. out->writeText(" <fontRevision value=\"1.0\"/>\n");
  338. out->writeText(" <checkSumAdjustment value=\"0xa9c3274\"/>\n");
  339. out->writeText(" <magicNumber value=\"0x5f0f3cf5\"/>\n");
  340. out->writeText(" <flags value=\"00000000 00011011\"/>\n");
  341. out->writeText(" <unitsPerEm value=\"");
  342. out->writeDecAsText(fUpem);
  343. out->writeText("\"/>\n");
  344. out->writeText(" <created value=\"Thu Feb 15 12:55:49 2018\"/>\n");
  345. out->writeText(" <modified value=\"Thu Feb 15 12:55:49 2018\"/>\n");
  346. // TODO: not recalculated for bitmap fonts?
  347. out->writeText(" <xMin value=\"");
  348. out->writeScalarAsText(fFontMetrics.fXMin);
  349. out->writeText("\"/>\n");
  350. out->writeText(" <yMin value=\"");
  351. out->writeScalarAsText(-fFontMetrics.fBottom);
  352. out->writeText("\"/>\n");
  353. out->writeText(" <xMax value=\"");
  354. out->writeScalarAsText(fFontMetrics.fXMax);
  355. out->writeText("\"/>\n");
  356. out->writeText(" <yMax value=\"");
  357. out->writeScalarAsText(-fFontMetrics.fTop);
  358. out->writeText("\"/>\n");
  359. char macStyle[16] = {
  360. '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'};
  361. if (this->fontStyle().weight() >= SkFontStyle::Bold().weight()) {
  362. macStyle[0xF - 0x0] = '1'; // Bold
  363. }
  364. switch (this->fontStyle().slant()) {
  365. case SkFontStyle::kUpright_Slant: break;
  366. case SkFontStyle::kItalic_Slant:
  367. macStyle[0xF - 0x1] = '1'; // Italic
  368. break;
  369. case SkFontStyle::kOblique_Slant:
  370. macStyle[0xF - 0x1] = '1'; // Italic
  371. break;
  372. default: SK_ABORT("Unknown slant.");
  373. }
  374. if (this->fontStyle().width() <= SkFontStyle::kCondensed_Width) {
  375. macStyle[0xF - 0x5] = '1'; // Condensed
  376. } else if (this->fontStyle().width() >= SkFontStyle::kExpanded_Width) {
  377. macStyle[0xF - 0x6] = '1'; // Extended
  378. }
  379. out->writeText(" <macStyle value=\"");
  380. out->write(macStyle, 8);
  381. out->writeText(" ");
  382. out->write(macStyle + 8, 8);
  383. out->writeText("\"/>\n");
  384. out->writeText(" <lowestRecPPEM value=\"8\"/>\n");
  385. out->writeText(" <fontDirectionHint value=\"2\"/>\n");
  386. out->writeText(" <indexToLocFormat value=\"0\"/>\n");
  387. out->writeText(" <glyphDataFormat value=\"0\"/>\n");
  388. out->writeText(" </head>\n");
  389. out->writeText(" <hhea>\n");
  390. out->writeText(" <tableVersion value=\"0x00010000\"/>\n");
  391. out->writeText(" <ascent value=\"");
  392. out->writeDecAsText(-fFontMetrics.fAscent);
  393. out->writeText("\"/>\n");
  394. out->writeText(" <descent value=\"");
  395. out->writeDecAsText(-fFontMetrics.fDescent);
  396. out->writeText("\"/>\n");
  397. out->writeText(" <lineGap value=\"");
  398. out->writeDecAsText(fFontMetrics.fLeading);
  399. out->writeText("\"/>\n");
  400. out->writeText(" <advanceWidthMax value=\"0\"/>\n");
  401. out->writeText(" <minLeftSideBearing value=\"0\"/>\n");
  402. out->writeText(" <minRightSideBearing value=\"0\"/>\n");
  403. out->writeText(" <xMaxExtent value=\"");
  404. out->writeScalarAsText(fFontMetrics.fXMax - fFontMetrics.fXMin);
  405. out->writeText("\"/>\n");
  406. out->writeText(" <caretSlopeRise value=\"1\"/>\n");
  407. out->writeText(" <caretSlopeRun value=\"0\"/>\n");
  408. out->writeText(" <caretOffset value=\"0\"/>\n");
  409. out->writeText(" <reserved0 value=\"0\"/>\n");
  410. out->writeText(" <reserved1 value=\"0\"/>\n");
  411. out->writeText(" <reserved2 value=\"0\"/>\n");
  412. out->writeText(" <reserved3 value=\"0\"/>\n");
  413. out->writeText(" <metricDataFormat value=\"0\"/>\n");
  414. out->writeText(" <numberOfHMetrics value=\"0\"/>\n");
  415. out->writeText(" </hhea>\n");
  416. // Some of this table is going to be re-calculated, but we have to write it out anyway.
  417. out->writeText(" <maxp>\n");
  418. out->writeText(" <tableVersion value=\"0x10000\"/>\n");
  419. out->writeText(" <numGlyphs value=\"");
  420. out->writeDecAsText(totalGlyphs);
  421. out->writeText("\"/>\n");
  422. out->writeText(" <maxPoints value=\"4\"/>\n");
  423. out->writeText(" <maxContours value=\"1\"/>\n");
  424. out->writeText(" <maxCompositePoints value=\"0\"/>\n");
  425. out->writeText(" <maxCompositeContours value=\"0\"/>\n");
  426. out->writeText(" <maxZones value=\"1\"/>\n");
  427. out->writeText(" <maxTwilightPoints value=\"0\"/>\n");
  428. out->writeText(" <maxStorage value=\"0\"/>\n");
  429. out->writeText(" <maxFunctionDefs value=\"10\"/>\n");
  430. out->writeText(" <maxInstructionDefs value=\"0\"/>\n");
  431. out->writeText(" <maxStackElements value=\"512\"/>\n");
  432. out->writeText(" <maxSizeOfInstructions value=\"24\"/>\n");
  433. out->writeText(" <maxComponentElements value=\"0\"/>\n");
  434. out->writeText(" <maxComponentDepth value=\"0\"/>\n");
  435. out->writeText(" </maxp>\n");
  436. out->writeText(" <OS_2>\n");
  437. out->writeText(" <version value=\"4\"/>\n");
  438. out->writeText(" <xAvgCharWidth value=\"");
  439. out->writeScalarAsText(fFontMetrics.fAvgCharWidth);
  440. out->writeText("\"/>\n");
  441. out->writeText(" <usWeightClass value=\"");
  442. out->writeDecAsText(this->fontStyle().weight());
  443. out->writeText("\"/>\n");
  444. out->writeText(" <usWidthClass value=\"");
  445. out->writeDecAsText(this->fontStyle().width());
  446. out->writeText("\"/>\n");
  447. out->writeText(" <fsType value=\"00000000 00000000\"/>\n");
  448. out->writeText(" <ySubscriptXSize value=\"665\"/>\n");
  449. out->writeText(" <ySubscriptYSize value=\"716\"/>\n");
  450. out->writeText(" <ySubscriptXOffset value=\"0\"/>\n");
  451. out->writeText(" <ySubscriptYOffset value=\"143\"/>\n");
  452. out->writeText(" <ySuperscriptXSize value=\"665\"/>\n");
  453. out->writeText(" <ySuperscriptYSize value=\"716\"/>\n");
  454. out->writeText(" <ySuperscriptXOffset value=\"0\"/>\n");
  455. out->writeText(" <ySuperscriptYOffset value=\"491\"/>\n");
  456. out->writeText(" <yStrikeoutSize value=\"");
  457. out->writeScalarAsText(fFontMetrics.fStrikeoutThickness);
  458. out->writeText("\"/>\n");
  459. out->writeText(" <yStrikeoutPosition value=\"");
  460. out->writeScalarAsText(-fFontMetrics.fStrikeoutPosition);
  461. out->writeText("\"/>\n");
  462. out->writeText(" <sFamilyClass value=\"0\"/>\n");
  463. out->writeText(" <panose>\n");
  464. out->writeText(" <bFamilyType value=\"0\"/>\n");
  465. out->writeText(" <bSerifStyle value=\"0\"/>\n");
  466. out->writeText(" <bWeight value=\"0\"/>\n");
  467. out->writeText(" <bProportion value=\"0\"/>\n");
  468. out->writeText(" <bContrast value=\"0\"/>\n");
  469. out->writeText(" <bStrokeVariation value=\"0\"/>\n");
  470. out->writeText(" <bArmStyle value=\"0\"/>\n");
  471. out->writeText(" <bLetterForm value=\"0\"/>\n");
  472. out->writeText(" <bMidline value=\"0\"/>\n");
  473. out->writeText(" <bXHeight value=\"0\"/>\n");
  474. out->writeText(" </panose>\n");
  475. out->writeText(" <ulUnicodeRange1 value=\"00000000 00000000 00000000 00000001\"/>\n");
  476. out->writeText(" <ulUnicodeRange2 value=\"00010000 00000000 00000000 00000000\"/>\n");
  477. out->writeText(" <ulUnicodeRange3 value=\"00000000 00000000 00000000 00000000\"/>\n");
  478. out->writeText(" <ulUnicodeRange4 value=\"00000000 00000000 00000000 00000000\"/>\n");
  479. out->writeText(" <achVendID value=\"Skia\"/>\n");
  480. char fsSelection[16] = {
  481. '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'};
  482. fsSelection[0xF - 0x7] = '1'; // Use typo metrics
  483. if (this->fontStyle().weight() >= SkFontStyle::Bold().weight()) {
  484. fsSelection[0xF - 0x5] = '1'; // Bold
  485. }
  486. switch (this->fontStyle().slant()) {
  487. case SkFontStyle::kUpright_Slant:
  488. if (this->fontStyle().weight() < SkFontStyle::Bold().weight()) {
  489. fsSelection[0xF - 0x6] = '1'; // Not bold or italic, is regular
  490. }
  491. break;
  492. case SkFontStyle::kItalic_Slant:
  493. fsSelection[0xF - 0x0] = '1'; // Italic
  494. break;
  495. case SkFontStyle::kOblique_Slant:
  496. fsSelection[0xF - 0x0] = '1'; // Italic
  497. fsSelection[0xF - 0x9] = '1'; // Oblique
  498. break;
  499. default: SK_ABORT("Unknown slant.");
  500. }
  501. out->writeText(" <fsSelection value=\"");
  502. out->write(fsSelection, 8);
  503. out->writeText(" ");
  504. out->write(fsSelection + 8, 8);
  505. out->writeText("\"/>\n");
  506. out->writeText(" <usFirstCharIndex value=\"0\"/>\n");
  507. out->writeText(" <usLastCharIndex value=\"0\"/>\n");
  508. out->writeText(" <sTypoAscender value=\"");
  509. out->writeScalarAsText(-fFontMetrics.fAscent);
  510. out->writeText("\"/>\n");
  511. out->writeText(" <sTypoDescender value=\"");
  512. out->writeScalarAsText(-fFontMetrics.fDescent);
  513. out->writeText("\"/>\n");
  514. out->writeText(" <sTypoLineGap value=\"");
  515. out->writeScalarAsText(fFontMetrics.fLeading);
  516. out->writeText("\"/>\n");
  517. out->writeText(" <usWinAscent value=\"");
  518. out->writeScalarAsText(-fFontMetrics.fAscent);
  519. out->writeText("\"/>\n");
  520. out->writeText(" <usWinDescent value=\"");
  521. out->writeScalarAsText(fFontMetrics.fDescent);
  522. out->writeText("\"/>\n");
  523. out->writeText(" <ulCodePageRange1 value=\"00000000 00000000 00000000 00000000\"/>\n");
  524. out->writeText(" <ulCodePageRange2 value=\"00000000 00000000 00000000 00000000\"/>\n");
  525. out->writeText(" <sxHeight value=\"");
  526. out->writeScalarAsText(fFontMetrics.fXHeight);
  527. out->writeText("\"/>\n");
  528. out->writeText(" <sCapHeight value=\"");
  529. out->writeScalarAsText(fFontMetrics.fCapHeight);
  530. out->writeText("\"/>\n");
  531. out->writeText(" <usDefaultChar value=\"0\"/>\n");
  532. out->writeText(" <usBreakChar value=\"32\"/>\n");
  533. out->writeText(" <usMaxContext value=\"0\"/>\n");
  534. out->writeText(" </OS_2>\n");
  535. out->writeText(" <hmtx>\n");
  536. for (int i = 0; i < fGlyphCount; ++i) {
  537. out->writeText(" <mtx name=\"glyf");
  538. out->writeHexAsText(i, 4);
  539. out->writeText("\" width=\"");
  540. out->writeDecAsText(fGlyphs[i].fAdvance);
  541. out->writeText("\" lsb=\"");
  542. int lsb = fGlyphs[i].fOrigin.fX;
  543. if (glyfInfo) {
  544. lsb += (*glyfInfo)[i].fBounds.fLeft;
  545. }
  546. out->writeDecAsText(lsb);
  547. out->writeText("\"/>\n");
  548. }
  549. if (glyfInfo) {
  550. for (int i = 0; i < fGlyphCount; ++i) {
  551. for (int j = 0; j < (*glyfInfo)[i].fLayers.count(); ++j) {
  552. out->writeText(" <mtx name=\"glyf");
  553. out->writeHexAsText(i, 4);
  554. out->writeText("l");
  555. out->writeHexAsText(j, 4);
  556. out->writeText("\" width=\"");
  557. out->writeDecAsText(fGlyphs[i].fAdvance);
  558. out->writeText("\" lsb=\"");
  559. int32_t lsb = fGlyphs[i].fOrigin.fX + (*glyfInfo)[i].fLayers[j].fBounds.fLeft;
  560. out->writeDecAsText(lsb);
  561. out->writeText("\"/>\n");
  562. }
  563. }
  564. }
  565. out->writeText(" </hmtx>\n");
  566. bool hasNonBMP = false;
  567. out->writeText(" <cmap>\n");
  568. out->writeText(" <tableVersion version=\"0\"/>\n");
  569. out->writeText(" <cmap_format_4 platformID=\"3\" platEncID=\"1\" language=\"0\">\n");
  570. fCMap.foreach ([&out, &hasNonBMP](const SkUnichar& c, const SkGlyphID& g) {
  571. if (0xFFFF < c) {
  572. hasNonBMP = true;
  573. return;
  574. }
  575. out->writeText(" <map code=\"0x");
  576. out->writeHexAsText(c, 4);
  577. out->writeText("\" name=\"glyf");
  578. out->writeHexAsText(g, 4);
  579. out->writeText("\"/>\n");
  580. });
  581. out->writeText(" </cmap_format_4>\n");
  582. if (hasNonBMP) {
  583. out->writeText(
  584. " <cmap_format_12 platformID=\"3\" platEncID=\"10\" format=\"12\" "
  585. "reserved=\"0\" length=\"1\" language=\"0\" nGroups=\"0\">\n");
  586. fCMap.foreach ([&out](const SkUnichar& c, const SkGlyphID& g) {
  587. out->writeText(" <map code=\"0x");
  588. out->writeHexAsText(c, 6);
  589. out->writeText("\" name=\"glyf");
  590. out->writeHexAsText(g, 4);
  591. out->writeText("\"/>\n");
  592. });
  593. out->writeText(" </cmap_format_12>\n");
  594. }
  595. out->writeText(" </cmap>\n");
  596. out->writeText(" <name>\n");
  597. out->writeText(
  598. " <namerecord nameID=\"1\" platformID=\"3\" platEncID=\"1\" langID=\"0x409\">\n");
  599. out->writeText(" ");
  600. out->writeText(fName.c_str());
  601. out->writeText(" ");
  602. out->writeText(type);
  603. out->writeText("\n");
  604. out->writeText(" </namerecord>\n");
  605. out->writeText(
  606. " <namerecord nameID=\"2\" platformID=\"3\" platEncID=\"1\" langID=\"0x409\">\n");
  607. out->writeText(" Regular\n");
  608. out->writeText(" </namerecord>\n");
  609. out->writeText(" </name>\n");
  610. out->writeText(" <post>\n");
  611. out->writeText(" <formatType value=\"3.0\"/>\n");
  612. out->writeText(" <italicAngle value=\"0.0\"/>\n");
  613. out->writeText(" <underlinePosition value=\"");
  614. out->writeScalarAsText(fFontMetrics.fUnderlinePosition);
  615. out->writeText("\"/>\n");
  616. out->writeText(" <underlineThickness value=\"");
  617. out->writeScalarAsText(fFontMetrics.fUnderlineThickness);
  618. out->writeText("\"/>\n");
  619. out->writeText(" <isFixedPitch value=\"0\"/>\n");
  620. out->writeText(" <minMemType42 value=\"0\"/>\n");
  621. out->writeText(" <maxMemType42 value=\"0\"/>\n");
  622. out->writeText(" <minMemType1 value=\"0\"/>\n");
  623. out->writeText(" <maxMemType1 value=\"0\"/>\n");
  624. out->writeText(" </post>\n");
  625. }
  626. void TestSVGTypeface::exportTtxCbdt(SkWStream* out, SkSpan<unsigned> strikeSizes) const {
  627. SkPaint paint;
  628. SkFont font;
  629. font.setTypeface(sk_ref_sp(const_cast<TestSVGTypeface*>(this)));
  630. SkString name;
  631. this->getFamilyName(&name);
  632. // The CBDT/CBLC format is quite restrictive. Only write strikes which fully fit.
  633. SkSTArray<8, int> goodStrikeSizes;
  634. for (size_t strikeIndex = 0; strikeIndex < strikeSizes.size(); ++strikeIndex) {
  635. font.setSize(strikeSizes[strikeIndex]);
  636. // CBLC limits
  637. SkFontMetrics fm;
  638. font.getMetrics(&fm);
  639. if (!SkTFitsIn<int8_t>((int)(-fm.fTop)) || !SkTFitsIn<int8_t>((int)(-fm.fBottom)) ||
  640. !SkTFitsIn<uint8_t>((int)(fm.fXMax - fm.fXMin))) {
  641. SkDebugf("Metrics too big cbdt font size %f for %s.\n", font.getSize(), name.c_str());
  642. continue;
  643. }
  644. // CBDT limits
  645. auto exceedsCbdtLimits = [&]() {
  646. for (int i = 0; i < fGlyphCount; ++i) {
  647. SkGlyphID gid = i;
  648. SkScalar advance;
  649. SkRect bounds;
  650. font.getWidthsBounds(&gid, 1, &advance, &bounds, nullptr);
  651. SkIRect ibounds = bounds.roundOut();
  652. if (!SkTFitsIn<int8_t>(ibounds.fLeft) || !SkTFitsIn<int8_t>(ibounds.fTop) ||
  653. !SkTFitsIn<uint8_t>(ibounds.width()) || !SkTFitsIn<uint8_t>(ibounds.height()) ||
  654. !SkTFitsIn<uint8_t>((int)advance)) {
  655. return true;
  656. }
  657. }
  658. return false;
  659. };
  660. if (exceedsCbdtLimits()) {
  661. SkDebugf("Glyphs too big cbdt font size %f for %s.\n", font.getSize(), name.c_str());
  662. continue;
  663. }
  664. goodStrikeSizes.emplace_back(strikeSizes[strikeIndex]);
  665. }
  666. if (goodStrikeSizes.empty()) {
  667. SkDebugf("No strike size fit for cbdt font for %s.\n", name.c_str());
  668. return;
  669. }
  670. out->writeText("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
  671. out->writeText("<ttFont sfntVersion=\"\\x00\\x01\\x00\\x00\" ttLibVersion=\"3.19\">\n");
  672. this->exportTtxCommon(out, "CBDT");
  673. out->writeText(" <CBDT>\n");
  674. out->writeText(" <header version=\"2.0\"/>\n");
  675. for (size_t strikeIndex = 0; strikeIndex < goodStrikeSizes.size(); ++strikeIndex) {
  676. font.setSize(goodStrikeSizes[strikeIndex]);
  677. out->writeText(" <strikedata index=\"");
  678. out->writeDecAsText(strikeIndex);
  679. out->writeText("\">\n");
  680. for (int i = 0; i < fGlyphCount; ++i) {
  681. SkGlyphID gid = i;
  682. SkScalar advance;
  683. SkRect bounds;
  684. font.getWidthsBounds(&gid, 1, &advance, &bounds, nullptr);
  685. SkIRect ibounds = bounds.roundOut();
  686. if (ibounds.isEmpty()) {
  687. continue;
  688. }
  689. SkImageInfo image_info = SkImageInfo::MakeN32Premul(ibounds.width(), ibounds.height());
  690. sk_sp<SkSurface> surface(SkSurface::MakeRaster(image_info));
  691. SkASSERT(surface);
  692. SkCanvas* canvas = surface->getCanvas();
  693. canvas->clear(0);
  694. SkPixmap pix;
  695. surface->peekPixels(&pix);
  696. canvas->drawSimpleText(&gid,
  697. sizeof(gid),
  698. SkTextEncoding::kGlyphID,
  699. -bounds.fLeft,
  700. -bounds.fTop,
  701. font,
  702. paint);
  703. surface->flush();
  704. sk_sp<SkImage> image = surface->makeImageSnapshot();
  705. sk_sp<SkData> data = image->encodeToData(SkEncodedImageFormat::kPNG, 100);
  706. out->writeText(" <cbdt_bitmap_format_17 name=\"glyf");
  707. out->writeHexAsText(i, 4);
  708. out->writeText("\">\n");
  709. out->writeText(" <SmallGlyphMetrics>\n");
  710. out->writeText(" <height value=\"");
  711. out->writeDecAsText(image->height());
  712. out->writeText("\"/>\n");
  713. out->writeText(" <width value=\"");
  714. out->writeDecAsText(image->width());
  715. out->writeText("\"/>\n");
  716. out->writeText(" <BearingX value=\"");
  717. out->writeDecAsText(ibounds.fLeft);
  718. out->writeText("\"/>\n");
  719. out->writeText(" <BearingY value=\"");
  720. out->writeDecAsText(-ibounds.fTop);
  721. out->writeText("\"/>\n");
  722. out->writeText(" <Advance value=\"");
  723. out->writeDecAsText((int)advance);
  724. out->writeText("\"/>\n");
  725. out->writeText(" </SmallGlyphMetrics>\n");
  726. out->writeText(" <rawimagedata>");
  727. uint8_t const* bytes = data->bytes();
  728. for (size_t i = 0; i < data->size(); ++i) {
  729. if ((i % 0x10) == 0x0) {
  730. out->writeText("\n ");
  731. } else if (((i - 1) % 0x4) == 0x3) {
  732. out->writeText(" ");
  733. }
  734. out->writeHexAsText(bytes[i], 2);
  735. }
  736. out->writeText("\n");
  737. out->writeText(" </rawimagedata>\n");
  738. out->writeText(" </cbdt_bitmap_format_17>\n");
  739. }
  740. out->writeText(" </strikedata>\n");
  741. }
  742. out->writeText(" </CBDT>\n");
  743. SkFontMetrics fm;
  744. out->writeText(" <CBLC>\n");
  745. out->writeText(" <header version=\"2.0\"/>\n");
  746. for (size_t strikeIndex = 0; strikeIndex < goodStrikeSizes.size(); ++strikeIndex) {
  747. font.setSize(goodStrikeSizes[strikeIndex]);
  748. font.getMetrics(&fm);
  749. out->writeText(" <strike index=\"");
  750. out->writeDecAsText(strikeIndex);
  751. out->writeText("\">\n");
  752. out->writeText(" <bitmapSizeTable>\n");
  753. out->writeText(" <sbitLineMetrics direction=\"hori\">\n");
  754. out->writeText(" <ascender value=\"");
  755. out->writeDecAsText((int)(-fm.fTop));
  756. out->writeText("\"/>\n");
  757. out->writeText(" <descender value=\"");
  758. out->writeDecAsText((int)(-fm.fBottom));
  759. out->writeText("\"/>\n");
  760. out->writeText(" <widthMax value=\"");
  761. out->writeDecAsText((int)(fm.fXMax - fm.fXMin));
  762. out->writeText("\"/>\n");
  763. out->writeText(" <caretSlopeNumerator value=\"0\"/>\n");
  764. out->writeText(" <caretSlopeDenominator value=\"0\"/>\n");
  765. out->writeText(" <caretOffset value=\"0\"/>\n");
  766. out->writeText(" <minOriginSB value=\"0\"/>\n");
  767. out->writeText(" <minAdvanceSB value=\"0\"/>\n");
  768. out->writeText(" <maxBeforeBL value=\"0\"/>\n");
  769. out->writeText(" <minAfterBL value=\"0\"/>\n");
  770. out->writeText(" <pad1 value=\"0\"/>\n");
  771. out->writeText(" <pad2 value=\"0\"/>\n");
  772. out->writeText(" </sbitLineMetrics>\n");
  773. out->writeText(" <sbitLineMetrics direction=\"vert\">\n");
  774. out->writeText(" <ascender value=\"");
  775. out->writeDecAsText((int)(-fm.fTop));
  776. out->writeText("\"/>\n");
  777. out->writeText(" <descender value=\"");
  778. out->writeDecAsText((int)(-fm.fBottom));
  779. out->writeText("\"/>\n");
  780. out->writeText(" <widthMax value=\"");
  781. out->writeDecAsText((int)(fm.fXMax - fm.fXMin));
  782. out->writeText("\"/>\n");
  783. out->writeText(" <caretSlopeNumerator value=\"0\"/>\n");
  784. out->writeText(" <caretSlopeDenominator value=\"0\"/>\n");
  785. out->writeText(" <caretOffset value=\"0\"/>\n");
  786. out->writeText(" <minOriginSB value=\"0\"/>\n");
  787. out->writeText(" <minAdvanceSB value=\"0\"/>\n");
  788. out->writeText(" <maxBeforeBL value=\"0\"/>\n");
  789. out->writeText(" <minAfterBL value=\"0\"/>\n");
  790. out->writeText(" <pad1 value=\"0\"/>\n");
  791. out->writeText(" <pad2 value=\"0\"/>\n");
  792. out->writeText(" </sbitLineMetrics>\n");
  793. out->writeText(" <colorRef value=\"0\"/>\n");
  794. out->writeText(" <startGlyphIndex value=\"1\"/>\n");
  795. out->writeText(" <endGlyphIndex value=\"1\"/>\n");
  796. out->writeText(" <ppemX value=\"");
  797. out->writeDecAsText(goodStrikeSizes[strikeIndex]);
  798. out->writeText("\"/>\n");
  799. out->writeText(" <ppemY value=\"");
  800. out->writeDecAsText(goodStrikeSizes[strikeIndex]);
  801. out->writeText("\"/>\n");
  802. out->writeText(" <bitDepth value=\"32\"/>\n");
  803. out->writeText(" <flags value=\"1\"/>\n");
  804. out->writeText(" </bitmapSizeTable>\n");
  805. out->writeText(
  806. " <eblc_index_sub_table_1 imageFormat=\"17\" firstGlyphIndex=\"1\" "
  807. "lastGlyphIndex=\"1\">\n");
  808. for (int i = 0; i < fGlyphCount; ++i) {
  809. SkGlyphID gid = i;
  810. SkRect bounds;
  811. font.getBounds(&gid, 1, &bounds, nullptr);
  812. if (bounds.isEmpty()) {
  813. continue;
  814. }
  815. out->writeText(" <glyphLoc name=\"glyf");
  816. out->writeHexAsText(i, 4);
  817. out->writeText("\"/>\n");
  818. }
  819. out->writeText(" </eblc_index_sub_table_1>\n");
  820. out->writeText(" </strike>\n");
  821. }
  822. out->writeText(" </CBLC>\n");
  823. out->writeText("</ttFont>\n");
  824. }
  825. /**
  826. * UnitsPerEm is generally 1000 here. Versions of macOS older than 10.13
  827. * have problems in CoreText determining the glyph bounds of bitmap glyphs
  828. * with unitsPerEm set to 1024 or numbers not divisible by 100 when the
  829. * contour is not closed. The bounds of sbix fonts on macOS appear to be those
  830. * of the outline in the 'glyf' table. If this countour is closed it will be
  831. * drawn, as the 'glyf' outline is to be drawn on top of any bitmap. (There is
  832. * a bit which is supposed to control this, but it cannot be relied on.) So
  833. * make the glyph contour a degenerate line with points at the edge of the
  834. * bounding box of the glyph.
  835. */
  836. void TestSVGTypeface::exportTtxSbix(SkWStream* out, SkSpan<unsigned> strikeSizes) const {
  837. out->writeText("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
  838. out->writeText("<ttFont sfntVersion=\"\\x00\\x01\\x00\\x00\" ttLibVersion=\"3.19\">\n");
  839. this->exportTtxCommon(out, "sbix");
  840. SkPaint paint;
  841. SkFont font;
  842. font.setTypeface(sk_ref_sp(const_cast<TestSVGTypeface*>(this)));
  843. out->writeText(" <glyf>\n");
  844. for (int i = 0; i < fGlyphCount; ++i) {
  845. const TestSVGTypeface::Glyph& glyphData = this->fGlyphs[i];
  846. SkSize containerSize = glyphData.size();
  847. SkRect bounds = SkRect::MakeXYWH(glyphData.fOrigin.fX,
  848. -glyphData.fOrigin.fY,
  849. containerSize.fWidth,
  850. containerSize.fHeight);
  851. SkIRect ibounds = bounds.roundOut();
  852. out->writeText(" <TTGlyph name=\"glyf");
  853. out->writeHexAsText(i, 4);
  854. out->writeText("\" xMin=\"");
  855. out->writeDecAsText(ibounds.fLeft);
  856. out->writeText("\" yMin=\"");
  857. out->writeDecAsText(-ibounds.fBottom);
  858. out->writeText("\" xMax=\"");
  859. out->writeDecAsText(ibounds.fRight);
  860. out->writeText("\" yMax=\"");
  861. out->writeDecAsText(-ibounds.fTop);
  862. out->writeText("\">\n");
  863. out->writeText(" <contour>\n");
  864. out->writeText(" <pt x=\"");
  865. out->writeDecAsText(ibounds.fLeft);
  866. out->writeText("\" y=\"");
  867. out->writeDecAsText(-ibounds.fBottom);
  868. out->writeText("\" on=\"1\"/>\n");
  869. out->writeText(" </contour>\n");
  870. out->writeText(" <contour>\n");
  871. out->writeText(" <pt x=\"");
  872. out->writeDecAsText(ibounds.fRight);
  873. out->writeText("\" y=\"");
  874. out->writeDecAsText(-ibounds.fTop);
  875. out->writeText("\" on=\"1\"/>\n");
  876. out->writeText(" </contour>\n");
  877. out->writeText(" <instructions/>\n");
  878. out->writeText(" </TTGlyph>\n");
  879. }
  880. out->writeText(" </glyf>\n");
  881. // The loca table will be re-calculated, but if we don't write one we don't get one.
  882. out->writeText(" <loca/>\n");
  883. out->writeText(" <sbix>\n");
  884. out->writeText(" <version value=\"1\"/>\n");
  885. out->writeText(" <flags value=\"00000000 00000001\"/>\n");
  886. for (size_t strikeIndex = 0; strikeIndex < strikeSizes.size(); ++strikeIndex) {
  887. font.setSize(strikeSizes[strikeIndex]);
  888. out->writeText(" <strike>\n");
  889. out->writeText(" <ppem value=\"");
  890. out->writeDecAsText(strikeSizes[strikeIndex]);
  891. out->writeText("\"/>\n");
  892. out->writeText(" <resolution value=\"72\"/>\n");
  893. for (int i = 0; i < fGlyphCount; ++i) {
  894. SkGlyphID gid = i;
  895. SkScalar advance;
  896. SkRect bounds;
  897. font.getWidthsBounds(&gid, 1, &advance, &bounds, nullptr);
  898. SkIRect ibounds = bounds.roundOut();
  899. if (ibounds.isEmpty()) {
  900. continue;
  901. }
  902. SkImageInfo image_info = SkImageInfo::MakeN32Premul(ibounds.width(), ibounds.height());
  903. sk_sp<SkSurface> surface(SkSurface::MakeRaster(image_info));
  904. SkASSERT(surface);
  905. SkCanvas* canvas = surface->getCanvas();
  906. canvas->clear(0);
  907. SkPixmap pix;
  908. surface->peekPixels(&pix);
  909. canvas->drawSimpleText(&gid,
  910. sizeof(gid),
  911. SkTextEncoding::kGlyphID,
  912. -bounds.fLeft,
  913. -bounds.fTop,
  914. font,
  915. paint);
  916. surface->flush();
  917. sk_sp<SkImage> image = surface->makeImageSnapshot();
  918. sk_sp<SkData> data = image->encodeToData(SkEncodedImageFormat::kPNG, 100);
  919. // The originOffset values are difficult to use as DirectWrite and FreeType interpret
  920. // the origin to be the initial glyph position on the baseline, but CoreGraphics
  921. // interprets the origin to be the lower left of the cbox of the outline in the 'glyf'
  922. // table.
  923. //#define SK_SBIX_LIKE_FT
  924. //#define SK_SBIX_LIKE_DW
  925. out->writeText(" <glyph name=\"glyf");
  926. out->writeHexAsText(i, 4);
  927. out->writeText("\" graphicType=\"png \" originOffsetX=\"");
  928. #if defined(SK_SBIX_LIKE_FT) || defined(SK_SBIX_LIKE_DW)
  929. out->writeDecAsText(bounds.fLeft);
  930. #else
  931. out->writeDecAsText(0);
  932. #endif
  933. // DirectWrite and CoreGraphics use positive values of originOffsetY to push the
  934. // image visually up (but from different origins).
  935. // FreeType uses positive values to push the image down.
  936. out->writeText("\" originOffsetY=\"");
  937. #if defined(SK_SBIX_LIKE_FT)
  938. out->writeScalarAsText(bounds.fBottom);
  939. #elif defined(SK_SBIX_LIKE_DW)
  940. out->writeScalarAsText(-bounds.fBottom);
  941. #else
  942. out->writeDecAsText(0);
  943. #endif
  944. out->writeText("\">\n");
  945. out->writeText(" <hexdata>");
  946. uint8_t const* bytes = data->bytes();
  947. for (size_t i = 0; i < data->size(); ++i) {
  948. if ((i % 0x10) == 0x0) {
  949. out->writeText("\n ");
  950. } else if (((i - 1) % 0x4) == 0x3) {
  951. out->writeText(" ");
  952. }
  953. out->writeHexAsText(bytes[i], 2);
  954. }
  955. out->writeText("\n");
  956. out->writeText(" </hexdata>\n");
  957. out->writeText(" </glyph>\n");
  958. }
  959. out->writeText(" </strike>\n");
  960. }
  961. out->writeText(" </sbix>\n");
  962. out->writeText("</ttFont>\n");
  963. }
  964. namespace {
  965. void convert_noninflect_cubic_to_quads(const SkPoint p[4],
  966. SkScalar toleranceSqd,
  967. SkTArray<SkPoint, true>* quads,
  968. int sublevel = 0) {
  969. // Notation: Point a is always p[0]. Point b is p[1] unless p[1] == p[0], in which case it is
  970. // p[2]. Point d is always p[3]. Point c is p[2] unless p[2] == p[3], in which case it is p[1].
  971. SkVector ab = p[1] - p[0];
  972. SkVector dc = p[2] - p[3];
  973. if (SkPointPriv::LengthSqd(ab) < SK_ScalarNearlyZero) {
  974. if (SkPointPriv::LengthSqd(dc) < SK_ScalarNearlyZero) {
  975. SkPoint* degQuad = quads->push_back_n(3);
  976. degQuad[0] = p[0];
  977. degQuad[1] = p[0];
  978. degQuad[2] = p[3];
  979. return;
  980. }
  981. ab = p[2] - p[0];
  982. }
  983. if (SkPointPriv::LengthSqd(dc) < SK_ScalarNearlyZero) {
  984. dc = p[1] - p[3];
  985. }
  986. static const SkScalar kLengthScale = 3 * SK_Scalar1 / 2;
  987. static const int kMaxSubdivs = 10;
  988. ab.scale(kLengthScale);
  989. dc.scale(kLengthScale);
  990. // e0 and e1 are extrapolations along vectors ab and dc.
  991. SkVector c0 = p[0];
  992. c0 += ab;
  993. SkVector c1 = p[3];
  994. c1 += dc;
  995. SkScalar dSqd = sublevel > kMaxSubdivs ? 0 : SkPointPriv::DistanceToSqd(c0, c1);
  996. if (dSqd < toleranceSqd) {
  997. SkPoint cAvg = c0;
  998. cAvg += c1;
  999. cAvg.scale(SK_ScalarHalf);
  1000. SkPoint* pts = quads->push_back_n(3);
  1001. pts[0] = p[0];
  1002. pts[1] = cAvg;
  1003. pts[2] = p[3];
  1004. return;
  1005. }
  1006. SkPoint choppedPts[7];
  1007. SkChopCubicAtHalf(p, choppedPts);
  1008. convert_noninflect_cubic_to_quads(choppedPts + 0, toleranceSqd, quads, sublevel + 1);
  1009. convert_noninflect_cubic_to_quads(choppedPts + 3, toleranceSqd, quads, sublevel + 1);
  1010. }
  1011. void convertCubicToQuads(const SkPoint p[4], SkScalar tolScale, SkTArray<SkPoint, true>* quads) {
  1012. if (!p[0].isFinite() || !p[1].isFinite() || !p[2].isFinite() || !p[3].isFinite()) {
  1013. return;
  1014. }
  1015. SkPoint chopped[10];
  1016. int count = SkChopCubicAtInflections(p, chopped);
  1017. const SkScalar tolSqd = SkScalarSquare(tolScale);
  1018. for (int i = 0; i < count; ++i) {
  1019. SkPoint* cubic = chopped + 3 * i;
  1020. convert_noninflect_cubic_to_quads(cubic, tolSqd, quads);
  1021. }
  1022. }
  1023. void path_to_quads(const SkPath& path, SkPath* quadPath) {
  1024. quadPath->reset();
  1025. SkTArray<SkPoint, true> qPts;
  1026. SkAutoConicToQuads converter;
  1027. const SkPoint* quadPts;
  1028. SkPath::RawIter iter(path);
  1029. uint8_t verb;
  1030. SkPoint pts[4];
  1031. while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
  1032. switch (verb) {
  1033. case SkPath::kMove_Verb: quadPath->moveTo(pts[0].fX, pts[0].fY); break;
  1034. case SkPath::kLine_Verb: quadPath->lineTo(pts[1].fX, pts[1].fY); break;
  1035. case SkPath::kQuad_Verb:
  1036. quadPath->quadTo(pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY);
  1037. break;
  1038. case SkPath::kCubic_Verb:
  1039. qPts.reset();
  1040. convertCubicToQuads(pts, SK_Scalar1, &qPts);
  1041. for (int i = 0; i < qPts.count(); i += 3) {
  1042. quadPath->quadTo(
  1043. qPts[i + 1].fX, qPts[i + 1].fY, qPts[i + 2].fX, qPts[i + 2].fY);
  1044. }
  1045. break;
  1046. case SkPath::kConic_Verb:
  1047. quadPts = converter.computeQuads(pts, iter.conicWeight(), SK_Scalar1);
  1048. for (int i = 0; i < converter.countQuads(); ++i) {
  1049. quadPath->quadTo(quadPts[i * 2 + 1].fX,
  1050. quadPts[i * 2 + 1].fY,
  1051. quadPts[i * 2 + 2].fX,
  1052. quadPts[i * 2 + 2].fY);
  1053. }
  1054. break;
  1055. case SkPath::kClose_Verb: quadPath->close(); break;
  1056. default: SkDEBUGFAIL("bad verb"); return;
  1057. }
  1058. }
  1059. }
  1060. class SkCOLRCanvas : public SkNoDrawCanvas {
  1061. public:
  1062. SkCOLRCanvas(SkRect glyphBounds,
  1063. const TestSVGTypeface& typeface,
  1064. SkGlyphID glyphId,
  1065. TestSVGTypeface::GlyfInfo* glyf,
  1066. SkTHashMap<SkColor, int>* colors,
  1067. SkWStream* out)
  1068. : SkNoDrawCanvas(glyphBounds.roundOut().width(), glyphBounds.roundOut().height())
  1069. , fBaselineOffset(glyphBounds.top())
  1070. , fTypeface(typeface)
  1071. , fGlyphId(glyphId)
  1072. , fGlyf(glyf)
  1073. , fColors(colors)
  1074. , fOut(out)
  1075. , fLayerId(0) {}
  1076. void writePoint(SkScalar x, SkScalar y, bool on) {
  1077. fOut->writeText(" <pt x=\"");
  1078. fOut->writeDecAsText(SkScalarRoundToInt(x));
  1079. fOut->writeText("\" y=\"");
  1080. fOut->writeDecAsText(SkScalarRoundToInt(y));
  1081. fOut->writeText("\" on=\"");
  1082. fOut->write8(on ? '1' : '0');
  1083. fOut->writeText("\"/>\n");
  1084. }
  1085. SkIRect writePath(const SkPath& path, bool layer) {
  1086. // Convert to quads.
  1087. SkPath quads;
  1088. path_to_quads(path, &quads);
  1089. SkRect bounds = quads.computeTightBounds();
  1090. SkIRect ibounds = bounds.roundOut();
  1091. // The bounds will be re-calculated anyway.
  1092. fOut->writeText(" <TTGlyph name=\"glyf");
  1093. fOut->writeHexAsText(fGlyphId, 4);
  1094. if (layer) {
  1095. fOut->writeText("l");
  1096. fOut->writeHexAsText(fLayerId, 4);
  1097. }
  1098. fOut->writeText("\" xMin=\"");
  1099. fOut->writeDecAsText(ibounds.fLeft);
  1100. fOut->writeText("\" yMin=\"");
  1101. fOut->writeDecAsText(ibounds.fTop);
  1102. fOut->writeText("\" xMax=\"");
  1103. fOut->writeDecAsText(ibounds.fRight);
  1104. fOut->writeText("\" yMax=\"");
  1105. fOut->writeDecAsText(ibounds.fBottom);
  1106. fOut->writeText("\">\n");
  1107. SkPath::RawIter iter(quads);
  1108. uint8_t verb;
  1109. SkPoint pts[4];
  1110. bool contourOpen = false;
  1111. while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
  1112. switch (verb) {
  1113. case SkPath::kMove_Verb:
  1114. if (contourOpen) {
  1115. fOut->writeText(" </contour>\n");
  1116. contourOpen = false;
  1117. }
  1118. break;
  1119. case SkPath::kLine_Verb:
  1120. if (!contourOpen) {
  1121. fOut->writeText(" <contour>\n");
  1122. this->writePoint(pts[0].fX, pts[0].fY, true);
  1123. contourOpen = true;
  1124. }
  1125. this->writePoint(pts[1].fX, pts[1].fY, true);
  1126. break;
  1127. case SkPath::kQuad_Verb:
  1128. if (!contourOpen) {
  1129. fOut->writeText(" <contour>\n");
  1130. this->writePoint(pts[0].fX, pts[0].fY, true);
  1131. contourOpen = true;
  1132. }
  1133. this->writePoint(pts[1].fX, pts[1].fY, false);
  1134. this->writePoint(pts[2].fX, pts[2].fY, true);
  1135. break;
  1136. case SkPath::kClose_Verb:
  1137. if (contourOpen) {
  1138. fOut->writeText(" </contour>\n");
  1139. contourOpen = false;
  1140. }
  1141. break;
  1142. default: SkDEBUGFAIL("bad verb"); return ibounds;
  1143. }
  1144. }
  1145. if (contourOpen) {
  1146. fOut->writeText(" </contour>\n");
  1147. }
  1148. // Required to write out an instructions tag.
  1149. fOut->writeText(" <instructions/>\n");
  1150. fOut->writeText(" </TTGlyph>\n");
  1151. return ibounds;
  1152. }
  1153. void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
  1154. SkPath path;
  1155. path.addRect(rect);
  1156. this->drawPath(path, paint);
  1157. }
  1158. void onDrawOval(const SkRect& oval, const SkPaint& paint) override {
  1159. SkPath path;
  1160. path.addOval(oval);
  1161. this->drawPath(path, paint);
  1162. }
  1163. void onDrawArc(const SkRect& oval,
  1164. SkScalar startAngle,
  1165. SkScalar sweepAngle,
  1166. bool useCenter,
  1167. const SkPaint& paint) override {
  1168. SkPath path;
  1169. bool fillNoPathEffect = SkPaint::kFill_Style == paint.getStyle() && !paint.getPathEffect();
  1170. SkPathPriv::CreateDrawArcPath(
  1171. &path, oval, startAngle, sweepAngle, useCenter, fillNoPathEffect);
  1172. this->drawPath(path, paint);
  1173. }
  1174. void onDrawRRect(const SkRRect& rrect, const SkPaint& paint) override {
  1175. SkPath path;
  1176. path.addRRect(rrect);
  1177. this->drawPath(path, paint);
  1178. }
  1179. void onDrawPath(const SkPath& platonicPath, const SkPaint& originalPaint) override {
  1180. SkPaint paint = originalPaint;
  1181. SkPath path = platonicPath;
  1182. // Apply the path effect.
  1183. if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) {
  1184. bool fill = paint.getFillPath(path, &path);
  1185. paint.setPathEffect(nullptr);
  1186. if (fill) {
  1187. paint.setStyle(SkPaint::kFill_Style);
  1188. } else {
  1189. paint.setStyle(SkPaint::kStroke_Style);
  1190. paint.setStrokeWidth(0);
  1191. }
  1192. }
  1193. // Apply the matrix.
  1194. SkMatrix m = this->getTotalMatrix();
  1195. // If done to the canvas then everything would get clipped out.
  1196. m.postTranslate(0, fBaselineOffset); // put the baseline at 0
  1197. m.postScale(1, -1); // and flip it since OpenType is y-up.
  1198. path.transform(m);
  1199. // While creating the default glyf, union with dark colors and intersect with bright colors.
  1200. SkColor color = paint.getColor();
  1201. SkPathOp op;
  1202. if (fTypeface.getPathOp(color, &op)) {
  1203. fBasePath.add(path, op);
  1204. }
  1205. SkIRect bounds = this->writePath(path, true);
  1206. // The CPAL table has the concept of a 'current color' which is index 0xFFFF.
  1207. // Mark any layer drawn in 'currentColor' as having this special index.
  1208. // The value of 'currentColor' here should a color which causes this layer to union into the
  1209. // default glyf.
  1210. constexpr SkColor currentColor = 0xFF2B0000;
  1211. int colorIndex;
  1212. if (color == currentColor) {
  1213. colorIndex = 0xFFFF;
  1214. } else {
  1215. int* colorIndexPtr = fColors->find(color);
  1216. if (colorIndexPtr) {
  1217. colorIndex = *colorIndexPtr;
  1218. } else {
  1219. colorIndex = fColors->count();
  1220. fColors->set(color, colorIndex);
  1221. }
  1222. }
  1223. fGlyf->fLayers.emplace_back(colorIndex, bounds);
  1224. ++fLayerId;
  1225. }
  1226. void finishGlyph() {
  1227. SkPath baseGlyph;
  1228. fBasePath.resolve(&baseGlyph);
  1229. fGlyf->fBounds = this->writePath(baseGlyph, false);
  1230. }
  1231. private:
  1232. SkScalar fBaselineOffset;
  1233. const TestSVGTypeface& fTypeface;
  1234. SkGlyphID fGlyphId;
  1235. TestSVGTypeface::GlyfInfo* fGlyf;
  1236. SkTHashMap<SkColor, int>* fColors;
  1237. SkWStream* const fOut;
  1238. SkOpBuilder fBasePath;
  1239. int fLayerId;
  1240. };
  1241. } // namespace
  1242. void TestSVGTypeface::exportTtxColr(SkWStream* out) const {
  1243. out->writeText("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
  1244. out->writeText("<ttFont sfntVersion=\"\\x00\\x01\\x00\\x00\" ttLibVersion=\"3.19\">\n");
  1245. SkTHashMap<SkColor, int> colors;
  1246. SkTArray<GlyfInfo> glyfInfos(fGlyphCount);
  1247. // Need to know all the glyphs up front for the common tables.
  1248. SkDynamicMemoryWStream glyfOut;
  1249. glyfOut.writeText(" <glyf>\n");
  1250. for (int i = 0; i < fGlyphCount; ++i) {
  1251. const TestSVGTypeface::Glyph& glyphData = this->fGlyphs[i];
  1252. SkSize containerSize = glyphData.size();
  1253. SkRect bounds = SkRect::MakeXYWH(glyphData.fOrigin.fX,
  1254. -glyphData.fOrigin.fY,
  1255. containerSize.fWidth,
  1256. containerSize.fHeight);
  1257. SkCOLRCanvas canvas(bounds, *this, i, &glyfInfos.emplace_back(), &colors, &glyfOut);
  1258. glyphData.render(&canvas);
  1259. canvas.finishGlyph();
  1260. }
  1261. glyfOut.writeText(" </glyf>\n");
  1262. this->exportTtxCommon(out, "COLR", &glyfInfos);
  1263. // The loca table will be re-calculated, but if we don't write one we don't get one.
  1264. out->writeText(" <loca/>\n");
  1265. std::unique_ptr<SkStreamAsset> glyfStream = glyfOut.detachAsStream();
  1266. out->writeStream(glyfStream.get(), glyfStream->getLength());
  1267. out->writeText(" <COLR>\n");
  1268. out->writeText(" <version value=\"0\"/>\n");
  1269. for (int i = 0; i < fGlyphCount; ++i) {
  1270. if (glyfInfos[i].fLayers.empty()) {
  1271. continue;
  1272. }
  1273. if (glyfInfos[i].fBounds.isEmpty()) {
  1274. SkDebugf("Glyph %d is empty but has layers.\n", i);
  1275. }
  1276. out->writeText(" <ColorGlyph name=\"glyf");
  1277. out->writeHexAsText(i, 4);
  1278. out->writeText("\">\n");
  1279. for (int j = 0; j < glyfInfos[i].fLayers.count(); ++j) {
  1280. const int colorIndex = glyfInfos[i].fLayers[j].fLayerColorIndex;
  1281. out->writeText(" <layer colorID=\"");
  1282. out->writeDecAsText(colorIndex);
  1283. out->writeText("\" name=\"glyf");
  1284. out->writeHexAsText(i, 4);
  1285. out->writeText("l");
  1286. out->writeHexAsText(j, 4);
  1287. out->writeText("\"/>\n");
  1288. }
  1289. out->writeText(" </ColorGlyph>\n");
  1290. }
  1291. out->writeText(" </COLR>\n");
  1292. // The colors must be written in order, the 'index' is ignored by ttx.
  1293. SkAutoTMalloc<SkColor> colorsInOrder(colors.count());
  1294. colors.foreach ([&colorsInOrder](const SkColor& c, const int* i) { colorsInOrder[*i] = c; });
  1295. out->writeText(" <CPAL>\n");
  1296. out->writeText(" <version value=\"0\"/>\n");
  1297. out->writeText(" <numPaletteEntries value=\"");
  1298. out->writeDecAsText(colors.count());
  1299. out->writeText("\"/>\n");
  1300. out->writeText(" <palette index=\"0\">\n");
  1301. for (int i = 0; i < colors.count(); ++i) {
  1302. SkColor c = colorsInOrder[i];
  1303. out->writeText(" <color index=\"");
  1304. out->writeDecAsText(i);
  1305. out->writeText("\" value=\"#");
  1306. out->writeHexAsText(SkColorGetR(c), 2);
  1307. out->writeHexAsText(SkColorGetG(c), 2);
  1308. out->writeHexAsText(SkColorGetB(c), 2);
  1309. out->writeHexAsText(SkColorGetA(c), 2);
  1310. out->writeText("\"/>\n");
  1311. }
  1312. out->writeText(" </palette>\n");
  1313. out->writeText(" </CPAL>\n");
  1314. out->writeText("</ttFont>\n");
  1315. }
  1316. #endif // SK_XML