SampleAAGeometry.cpp 62 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847
  1. /*
  2. * Copyright 2015 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 "include/core/SkBitmap.h"
  8. #include "include/core/SkCanvas.h"
  9. #include "include/core/SkString.h"
  10. #include "include/private/SkMacros.h"
  11. #include "include/utils/SkTextUtils.h"
  12. #include "samplecode/Sample.h"
  13. #include "src/core/SkGeometry.h"
  14. #include "src/core/SkPointPriv.h"
  15. #include "src/pathops/SkIntersections.h"
  16. #include "src/pathops/SkOpEdgeBuilder.h"
  17. #if 0
  18. void SkStrokeSegment::dump() const {
  19. SkDebugf("{{{%1.9g,%1.9g}, {%1.9g,%1.9g}", fPts[0].fX, fPts[0].fY, fPts[1].fX, fPts[1].fY);
  20. if (SkPath::kQuad_Verb == fVerb) {
  21. SkDebugf(", {%1.9g,%1.9g}", fPts[2].fX, fPts[2].fY);
  22. }
  23. SkDebugf("}}");
  24. #ifdef SK_DEBUG
  25. SkDebugf(" id=%d", fDebugID);
  26. #endif
  27. SkDebugf("\n");
  28. }
  29. void SkStrokeSegment::dumpAll() const {
  30. const SkStrokeSegment* segment = this;
  31. while (segment) {
  32. segment->dump();
  33. segment = segment->fNext;
  34. }
  35. }
  36. void SkStrokeTriple::dump() const {
  37. SkDebugf("{{{%1.9g,%1.9g}, {%1.9g,%1.9g}", fPts[0].fX, fPts[0].fY, fPts[1].fX, fPts[1].fY);
  38. if (SkPath::kQuad_Verb <= fVerb) {
  39. SkDebugf(", {%1.9g,%1.9g}", fPts[2].fX, fPts[2].fY);
  40. }
  41. if (SkPath::kCubic_Verb == fVerb) {
  42. SkDebugf(", {%1.9g,%1.9g}", fPts[3].fX, fPts[3].fY);
  43. } else if (SkPath::kConic_Verb == fVerb) {
  44. SkDebugf(", %1.9g", weight());
  45. }
  46. SkDebugf("}}");
  47. #ifdef SK_DEBUG
  48. SkDebugf(" triple id=%d", fDebugID);
  49. #endif
  50. SkDebugf("\ninner:\n");
  51. fInner->dumpAll();
  52. SkDebugf("outer:\n");
  53. fOuter->dumpAll();
  54. SkDebugf("join:\n");
  55. fJoin->dumpAll();
  56. }
  57. void SkStrokeTriple::dumpAll() const {
  58. const SkStrokeTriple* triple = this;
  59. while (triple) {
  60. triple->dump();
  61. triple = triple->fNext;
  62. }
  63. }
  64. void SkStrokeContour::dump() const {
  65. #ifdef SK_DEBUG
  66. SkDebugf("id=%d ", fDebugID);
  67. #endif
  68. SkDebugf("head:\n");
  69. fHead->dumpAll();
  70. SkDebugf("head cap:\n");
  71. fHeadCap->dumpAll();
  72. SkDebugf("tail cap:\n");
  73. fTailCap->dumpAll();
  74. }
  75. void SkStrokeContour::dumpAll() const {
  76. const SkStrokeContour* contour = this;
  77. while (contour) {
  78. contour->dump();
  79. contour = contour->fNext;
  80. }
  81. }
  82. #endif
  83. SkScalar gCurveDistance = 10;
  84. #if 0 // unused
  85. static SkPath::Verb get_path_verb(int index, const SkPath& path) {
  86. if (index < 0) {
  87. return SkPath::kMove_Verb;
  88. }
  89. SkPoint pts[4];
  90. SkPath::Verb verb;
  91. SkPath::Iter iter(path, true);
  92. int counter = -1;
  93. while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
  94. if (++counter < index) {
  95. continue;
  96. }
  97. return verb;
  98. }
  99. SkASSERT(0);
  100. return SkPath::kMove_Verb;
  101. }
  102. #endif
  103. static SkScalar get_path_weight(int index, const SkPath& path) {
  104. SkPoint pts[4];
  105. SkPath::Verb verb;
  106. SkPath::Iter iter(path, true);
  107. int counter = -1;
  108. while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
  109. if (++counter < index) {
  110. continue;
  111. }
  112. return verb == SkPath::kConic_Verb ? iter.conicWeight() : 1;
  113. }
  114. SkASSERT(0);
  115. return 0;
  116. }
  117. static void set_path_pt(int index, const SkPoint& pt, SkPath* path) {
  118. SkPath result;
  119. SkPoint pts[4];
  120. SkPath::Verb verb;
  121. SkPath::RawIter iter(*path);
  122. int startIndex = 0;
  123. int endIndex = 0;
  124. while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
  125. switch (verb) {
  126. case SkPath::kMove_Verb:
  127. endIndex += 1;
  128. break;
  129. case SkPath::kLine_Verb:
  130. endIndex += 1;
  131. break;
  132. case SkPath::kQuad_Verb:
  133. case SkPath::kConic_Verb:
  134. endIndex += 2;
  135. break;
  136. case SkPath::kCubic_Verb:
  137. endIndex += 3;
  138. break;
  139. case SkPath::kClose_Verb:
  140. break;
  141. case SkPath::kDone_Verb:
  142. break;
  143. default:
  144. SkASSERT(0);
  145. }
  146. if (startIndex <= index && index < endIndex) {
  147. pts[index - startIndex] = pt;
  148. index = -1;
  149. }
  150. switch (verb) {
  151. case SkPath::kMove_Verb:
  152. result.moveTo(pts[0]);
  153. break;
  154. case SkPath::kLine_Verb:
  155. result.lineTo(pts[1]);
  156. startIndex += 1;
  157. break;
  158. case SkPath::kQuad_Verb:
  159. result.quadTo(pts[1], pts[2]);
  160. startIndex += 2;
  161. break;
  162. case SkPath::kConic_Verb:
  163. result.conicTo(pts[1], pts[2], iter.conicWeight());
  164. startIndex += 2;
  165. break;
  166. case SkPath::kCubic_Verb:
  167. result.cubicTo(pts[1], pts[2], pts[3]);
  168. startIndex += 3;
  169. break;
  170. case SkPath::kClose_Verb:
  171. result.close();
  172. startIndex += 1;
  173. break;
  174. case SkPath::kDone_Verb:
  175. break;
  176. default:
  177. SkASSERT(0);
  178. }
  179. }
  180. #if 0
  181. SkDebugf("\n\noriginal\n");
  182. path->dump();
  183. SkDebugf("\nedited\n");
  184. result.dump();
  185. #endif
  186. *path = result;
  187. }
  188. static void add_path_segment(int index, SkPath* path) {
  189. SkPath result;
  190. SkPoint pts[4];
  191. SkPoint firstPt = { 0, 0 }; // init to avoid warning
  192. SkPoint lastPt = { 0, 0 }; // init to avoid warning
  193. SkPath::Verb verb;
  194. SkPath::RawIter iter(*path);
  195. int counter = -1;
  196. while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
  197. SkScalar weight SK_INIT_TO_AVOID_WARNING;
  198. if (++counter == index) {
  199. switch (verb) {
  200. case SkPath::kLine_Verb:
  201. result.lineTo((pts[0].fX + pts[1].fX) / 2, (pts[0].fY + pts[1].fY) / 2);
  202. break;
  203. case SkPath::kQuad_Verb: {
  204. SkPoint chop[5];
  205. SkChopQuadAtHalf(pts, chop);
  206. result.quadTo(chop[1], chop[2]);
  207. pts[1] = chop[3];
  208. } break;
  209. case SkPath::kConic_Verb: {
  210. SkConic chop[2];
  211. SkConic conic;
  212. conic.set(pts, iter.conicWeight());
  213. if (!conic.chopAt(0.5f, chop)) {
  214. return;
  215. }
  216. result.conicTo(chop[0].fPts[1], chop[0].fPts[2], chop[0].fW);
  217. pts[1] = chop[1].fPts[1];
  218. weight = chop[1].fW;
  219. } break;
  220. case SkPath::kCubic_Verb: {
  221. SkPoint chop[7];
  222. SkChopCubicAtHalf(pts, chop);
  223. result.cubicTo(chop[1], chop[2], chop[3]);
  224. pts[1] = chop[4];
  225. pts[2] = chop[5];
  226. } break;
  227. case SkPath::kClose_Verb: {
  228. result.lineTo((lastPt.fX + firstPt.fX) / 2, (lastPt.fY + firstPt.fY) / 2);
  229. } break;
  230. default:
  231. SkASSERT(0);
  232. }
  233. } else if (verb == SkPath::kConic_Verb) {
  234. weight = iter.conicWeight();
  235. }
  236. switch (verb) {
  237. case SkPath::kMove_Verb:
  238. result.moveTo(firstPt = pts[0]);
  239. break;
  240. case SkPath::kLine_Verb:
  241. result.lineTo(lastPt = pts[1]);
  242. break;
  243. case SkPath::kQuad_Verb:
  244. result.quadTo(pts[1], lastPt = pts[2]);
  245. break;
  246. case SkPath::kConic_Verb:
  247. result.conicTo(pts[1], lastPt = pts[2], weight);
  248. break;
  249. case SkPath::kCubic_Verb:
  250. result.cubicTo(pts[1], pts[2], lastPt = pts[3]);
  251. break;
  252. case SkPath::kClose_Verb:
  253. result.close();
  254. break;
  255. case SkPath::kDone_Verb:
  256. break;
  257. default:
  258. SkASSERT(0);
  259. }
  260. }
  261. *path = result;
  262. }
  263. static void delete_path_segment(int index, SkPath* path) {
  264. SkPath result;
  265. SkPoint pts[4];
  266. SkPath::Verb verb;
  267. SkPath::RawIter iter(*path);
  268. int counter = -1;
  269. while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
  270. if (++counter == index) {
  271. continue;
  272. }
  273. switch (verb) {
  274. case SkPath::kMove_Verb:
  275. result.moveTo(pts[0]);
  276. break;
  277. case SkPath::kLine_Verb:
  278. result.lineTo(pts[1]);
  279. break;
  280. case SkPath::kQuad_Verb:
  281. result.quadTo(pts[1], pts[2]);
  282. break;
  283. case SkPath::kConic_Verb:
  284. result.conicTo(pts[1], pts[2], iter.conicWeight());
  285. break;
  286. case SkPath::kCubic_Verb:
  287. result.cubicTo(pts[1], pts[2], pts[3]);
  288. break;
  289. case SkPath::kClose_Verb:
  290. result.close();
  291. break;
  292. case SkPath::kDone_Verb:
  293. break;
  294. default:
  295. SkASSERT(0);
  296. }
  297. }
  298. *path = result;
  299. }
  300. static void set_path_weight(int index, SkScalar w, SkPath* path) {
  301. SkPath result;
  302. SkPoint pts[4];
  303. SkPath::Verb verb;
  304. SkPath::Iter iter(*path, true);
  305. int counter = -1;
  306. while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
  307. ++counter;
  308. switch (verb) {
  309. case SkPath::kMove_Verb:
  310. result.moveTo(pts[0]);
  311. break;
  312. case SkPath::kLine_Verb:
  313. result.lineTo(pts[1]);
  314. break;
  315. case SkPath::kQuad_Verb:
  316. result.quadTo(pts[1], pts[2]);
  317. break;
  318. case SkPath::kConic_Verb:
  319. result.conicTo(pts[1], pts[2], counter == index ? w : iter.conicWeight());
  320. break;
  321. case SkPath::kCubic_Verb:
  322. result.cubicTo(pts[1], pts[2], pts[3]);
  323. break;
  324. case SkPath::kClose_Verb:
  325. result.close();
  326. break;
  327. case SkPath::kDone_Verb:
  328. break;
  329. default:
  330. SkASSERT(0);
  331. }
  332. }
  333. *path = result;
  334. }
  335. static void set_path_verb(int index, SkPath::Verb v, SkPath* path, SkScalar w) {
  336. SkASSERT(SkPath::kLine_Verb <= v && v <= SkPath::kCubic_Verb);
  337. SkPath result;
  338. SkPoint pts[4];
  339. SkPath::Verb verb;
  340. SkPath::Iter iter(*path, true);
  341. int counter = -1;
  342. while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
  343. SkScalar weight = verb == SkPath::kConic_Verb ? iter.conicWeight() : 1;
  344. if (++counter == index && v != verb) {
  345. SkASSERT(SkPath::kLine_Verb <= verb && verb <= SkPath::kCubic_Verb);
  346. switch (verb) {
  347. case SkPath::kLine_Verb:
  348. switch (v) {
  349. case SkPath::kConic_Verb:
  350. weight = w;
  351. case SkPath::kQuad_Verb:
  352. pts[2] = pts[1];
  353. pts[1].fX = (pts[0].fX + pts[2].fX) / 2;
  354. pts[1].fY = (pts[0].fY + pts[2].fY) / 2;
  355. break;
  356. case SkPath::kCubic_Verb:
  357. pts[3] = pts[1];
  358. pts[1].fX = (pts[0].fX * 2 + pts[3].fX) / 3;
  359. pts[1].fY = (pts[0].fY * 2 + pts[3].fY) / 3;
  360. pts[2].fX = (pts[0].fX + pts[3].fX * 2) / 3;
  361. pts[2].fY = (pts[0].fY + pts[3].fY * 2) / 3;
  362. break;
  363. default:
  364. SkASSERT(0);
  365. break;
  366. }
  367. break;
  368. case SkPath::kQuad_Verb:
  369. case SkPath::kConic_Verb:
  370. switch (v) {
  371. case SkPath::kLine_Verb:
  372. pts[1] = pts[2];
  373. break;
  374. case SkPath::kConic_Verb:
  375. weight = w;
  376. case SkPath::kQuad_Verb:
  377. break;
  378. case SkPath::kCubic_Verb: {
  379. SkDQuad dQuad;
  380. dQuad.set(pts);
  381. SkDCubic dCubic = dQuad.debugToCubic();
  382. pts[3] = pts[2];
  383. pts[1] = dCubic[1].asSkPoint();
  384. pts[2] = dCubic[2].asSkPoint();
  385. } break;
  386. default:
  387. SkASSERT(0);
  388. break;
  389. }
  390. break;
  391. case SkPath::kCubic_Verb:
  392. switch (v) {
  393. case SkPath::kLine_Verb:
  394. pts[1] = pts[3];
  395. break;
  396. case SkPath::kConic_Verb:
  397. weight = w;
  398. case SkPath::kQuad_Verb: {
  399. SkDCubic dCubic;
  400. dCubic.set(pts);
  401. SkDQuad dQuad = dCubic.toQuad();
  402. pts[1] = dQuad[1].asSkPoint();
  403. pts[2] = pts[3];
  404. } break;
  405. default:
  406. SkASSERT(0);
  407. break;
  408. }
  409. break;
  410. default:
  411. SkASSERT(0);
  412. break;
  413. }
  414. verb = v;
  415. }
  416. switch (verb) {
  417. case SkPath::kMove_Verb:
  418. result.moveTo(pts[0]);
  419. break;
  420. case SkPath::kLine_Verb:
  421. result.lineTo(pts[1]);
  422. break;
  423. case SkPath::kQuad_Verb:
  424. result.quadTo(pts[1], pts[2]);
  425. break;
  426. case SkPath::kConic_Verb:
  427. result.conicTo(pts[1], pts[2], weight);
  428. break;
  429. case SkPath::kCubic_Verb:
  430. result.cubicTo(pts[1], pts[2], pts[3]);
  431. break;
  432. case SkPath::kClose_Verb:
  433. result.close();
  434. break;
  435. default:
  436. SkASSERT(0);
  437. break;
  438. }
  439. }
  440. *path = result;
  441. }
  442. static void add_to_map(SkScalar coverage, int x, int y, uint8_t* distanceMap, int w, int h) {
  443. int byteCoverage = (int) (coverage * 256);
  444. if (byteCoverage < 0) {
  445. byteCoverage = 0;
  446. } else if (byteCoverage > 255) {
  447. byteCoverage = 255;
  448. }
  449. SkASSERT(x < w);
  450. SkASSERT(y < h);
  451. distanceMap[y * w + x] = SkTMax(distanceMap[y * w + x], (uint8_t) byteCoverage);
  452. }
  453. static void filter_coverage(const uint8_t* map, int len, uint8_t min, uint8_t max,
  454. uint8_t* filter) {
  455. for (int index = 0; index < len; ++index) {
  456. uint8_t in = map[index];
  457. filter[index] = in < min ? 0 : max < in ? 0 : in;
  458. }
  459. }
  460. static void construct_path(SkPath& path) {
  461. path.reset();
  462. path.moveTo(442, 101.5f);
  463. path.quadTo(413.5f, 691, 772, 514);
  464. path.lineTo(346, 721.5f);
  465. path.lineTo(154, 209);
  466. path.lineTo(442, 101.5f);
  467. path.close();
  468. }
  469. struct ButtonPaints {
  470. static const int kMaxStateCount = 3;
  471. SkPaint fDisabled;
  472. SkPaint fStates[kMaxStateCount];
  473. SkFont fLabelFont;
  474. ButtonPaints() {
  475. fStates[0].setAntiAlias(true);
  476. fStates[0].setStyle(SkPaint::kStroke_Style);
  477. fStates[0].setColor(0xFF3F0000);
  478. fStates[1] = fStates[0];
  479. fStates[1].setStrokeWidth(3);
  480. fStates[2] = fStates[1];
  481. fStates[2].setColor(0xFFcf0000);
  482. fLabelFont.setSize(25.0f);
  483. }
  484. };
  485. struct Button {
  486. SkRect fBounds;
  487. int fStateCount;
  488. int fState;
  489. char fLabel;
  490. bool fVisible;
  491. Button(char label) {
  492. fStateCount = 2;
  493. fState = 0;
  494. fLabel = label;
  495. fVisible = false;
  496. }
  497. Button(char label, int stateCount) {
  498. SkASSERT(stateCount <= ButtonPaints::kMaxStateCount);
  499. fStateCount = stateCount;
  500. fState = 0;
  501. fLabel = label;
  502. fVisible = false;
  503. }
  504. bool contains(const SkRect& rect) {
  505. return fVisible && fBounds.contains(rect);
  506. }
  507. bool enabled() {
  508. return SkToBool(fState);
  509. }
  510. void draw(SkCanvas* canvas, const ButtonPaints& paints) {
  511. if (!fVisible) {
  512. return;
  513. }
  514. canvas->drawRect(fBounds, paints.fStates[fState]);
  515. SkTextUtils::Draw(canvas, &fLabel, 1, SkTextEncoding::kUTF8, fBounds.centerX(), fBounds.fBottom - 5,
  516. paints.fLabelFont, SkPaint(), SkTextUtils::kCenter_Align);
  517. }
  518. void toggle() {
  519. if (++fState == fStateCount) {
  520. fState = 0;
  521. }
  522. }
  523. void setEnabled(bool enabled) {
  524. fState = (int) enabled;
  525. }
  526. };
  527. struct ControlPaints {
  528. SkPaint fOutline;
  529. SkPaint fIndicator;
  530. SkPaint fFill;
  531. SkPaint fLabel;
  532. SkPaint fValue;
  533. SkFont fLabelFont;
  534. SkFont fValueFont;
  535. ControlPaints() {
  536. fOutline.setAntiAlias(true);
  537. fOutline.setStyle(SkPaint::kStroke_Style);
  538. fIndicator = fOutline;
  539. fIndicator.setColor(SK_ColorRED);
  540. fFill.setAntiAlias(true);
  541. fFill.setColor(0x7fff0000);
  542. fLabel.setAntiAlias(true);
  543. fLabelFont.setSize(13.0f);
  544. fValue.setAntiAlias(true);
  545. fValueFont.setSize(11.0f);
  546. }
  547. };
  548. struct UniControl {
  549. SkString fName;
  550. SkRect fBounds;
  551. SkScalar fMin;
  552. SkScalar fMax;
  553. SkScalar fValLo;
  554. SkScalar fYLo;
  555. bool fVisible;
  556. UniControl(const char* name, SkScalar min, SkScalar max) {
  557. fName = name;
  558. fValLo = fMin = min;
  559. fMax = max;
  560. fVisible = false;
  561. }
  562. virtual ~UniControl() {}
  563. bool contains(const SkRect& rect) {
  564. return fVisible && fBounds.contains(rect);
  565. }
  566. virtual void draw(SkCanvas* canvas, const ControlPaints& paints) {
  567. if (!fVisible) {
  568. return;
  569. }
  570. canvas->drawRect(fBounds, paints.fOutline);
  571. fYLo = fBounds.fTop + (fValLo - fMin) * fBounds.height() / (fMax - fMin);
  572. canvas->drawLine(fBounds.fLeft - 5, fYLo, fBounds.fRight + 5, fYLo, paints.fIndicator);
  573. SkString label;
  574. label.printf("%0.3g", fValLo);
  575. canvas->drawString(label, fBounds.fLeft + 5, fYLo - 5, paints.fValueFont, paints.fValue);
  576. canvas->drawString(fName, fBounds.fLeft, fBounds.bottom() + 11, paints.fLabelFont,
  577. paints.fLabel);
  578. }
  579. };
  580. struct BiControl : public UniControl {
  581. SkScalar fValHi;
  582. BiControl(const char* name, SkScalar min, SkScalar max)
  583. : UniControl(name, min, max)
  584. , fValHi(fMax) {
  585. }
  586. virtual ~BiControl() {}
  587. virtual void draw(SkCanvas* canvas, const ControlPaints& paints) {
  588. UniControl::draw(canvas, paints);
  589. if (!fVisible || fValHi == fValLo) {
  590. return;
  591. }
  592. SkScalar yPos = fBounds.fTop + (fValHi - fMin) * fBounds.height() / (fMax - fMin);
  593. canvas->drawLine(fBounds.fLeft - 5, yPos, fBounds.fRight + 5, yPos, paints.fIndicator);
  594. SkString label;
  595. label.printf("%0.3g", fValHi);
  596. if (yPos < fYLo + 10) {
  597. yPos = fYLo + 10;
  598. }
  599. canvas->drawString(label, fBounds.fLeft + 5, yPos - 5, paints.fValueFont, paints.fValue);
  600. SkRect fill = { fBounds.fLeft, fYLo, fBounds.fRight, yPos };
  601. canvas->drawRect(fill, paints.fFill);
  602. }
  603. };
  604. class MyClick : public Sample::Click {
  605. public:
  606. enum ClickType {
  607. kInvalidType = -1,
  608. kPtType,
  609. kVerbType,
  610. kControlType,
  611. kPathType,
  612. } fType;
  613. enum ControlType {
  614. kInvalidControl = -1,
  615. kFirstControl,
  616. kFilterControl = kFirstControl,
  617. kResControl,
  618. kWeightControl,
  619. kWidthControl,
  620. kLastControl = kWidthControl,
  621. kFirstButton,
  622. kCubicButton = kFirstButton,
  623. kConicButton,
  624. kQuadButton,
  625. kLineButton,
  626. kLastVerbButton = kLineButton,
  627. kAddButton,
  628. kDeleteButton,
  629. kInOutButton,
  630. kFillButton,
  631. kSkeletonButton,
  632. kFilterButton,
  633. kBisectButton,
  634. kJoinButton,
  635. kLastButton = kJoinButton,
  636. kPathMove,
  637. } fControl;
  638. SkPath::Verb fVerb;
  639. SkScalar fWeight;
  640. MyClick(ClickType type, ControlType control)
  641. : fType(type)
  642. , fControl(control)
  643. , fVerb((SkPath::Verb) -1)
  644. , fWeight(1) {
  645. }
  646. MyClick(ClickType type, int index)
  647. : fType(type)
  648. , fControl((ControlType) index)
  649. , fVerb((SkPath::Verb) -1)
  650. , fWeight(1) {
  651. }
  652. MyClick(ClickType type, int index, SkPath::Verb verb, SkScalar weight)
  653. : fType(type)
  654. , fControl((ControlType) index)
  655. , fVerb(verb)
  656. , fWeight(weight) {
  657. }
  658. bool isButton() {
  659. return kFirstButton <= fControl && fControl <= kLastButton;
  660. }
  661. int ptHit() const {
  662. SkASSERT(fType == kPtType);
  663. return (int) fControl;
  664. }
  665. int verbHit() const {
  666. SkASSERT(fType == kVerbType);
  667. return (int) fControl;
  668. }
  669. };
  670. enum {
  671. kControlCount = MyClick::kLastControl - MyClick::kFirstControl + 1,
  672. };
  673. static struct ControlPair {
  674. UniControl* fControl;
  675. MyClick::ControlType fControlType;
  676. } kControlList[kControlCount];
  677. enum {
  678. kButtonCount = MyClick::kLastButton - MyClick::kFirstButton + 1,
  679. kVerbCount = MyClick::kLastVerbButton - MyClick::kFirstButton + 1,
  680. };
  681. static struct ButtonPair {
  682. Button* fButton;
  683. MyClick::ControlType fButtonType;
  684. } kButtonList[kButtonCount];
  685. static void enable_verb_button(MyClick::ControlType type) {
  686. for (int index = 0; index < kButtonCount; ++index) {
  687. MyClick::ControlType testType = kButtonList[index].fButtonType;
  688. if (MyClick::kFirstButton <= testType && testType <= MyClick::kLastVerbButton) {
  689. Button* button = kButtonList[index].fButton;
  690. button->setEnabled(testType == type);
  691. }
  692. }
  693. }
  694. struct Stroke;
  695. struct Active {
  696. Active* fNext;
  697. Stroke* fParent;
  698. SkScalar fStart;
  699. SkScalar fEnd;
  700. void reset() {
  701. fNext = nullptr;
  702. fStart = 0;
  703. fEnd = 1;
  704. }
  705. };
  706. struct Stroke {
  707. SkPath fPath;
  708. Active fActive;
  709. bool fInner;
  710. void reset() {
  711. fPath.reset();
  712. fActive.reset();
  713. }
  714. };
  715. struct PathUndo {
  716. SkPath fPath;
  717. std::unique_ptr<PathUndo> fNext;
  718. };
  719. class AAGeometryView : public Sample {
  720. SkPaint fActivePaint;
  721. SkPaint fComplexPaint;
  722. SkPaint fCoveragePaint;
  723. SkFont fLegendLeftFont;
  724. SkFont fLegendRightFont;
  725. SkPaint fPointPaint;
  726. SkPaint fSkeletonPaint;
  727. SkPaint fLightSkeletonPaint;
  728. SkPath fPath;
  729. ControlPaints fControlPaints;
  730. UniControl fResControl;
  731. UniControl fWeightControl;
  732. UniControl fWidthControl;
  733. BiControl fFilterControl;
  734. ButtonPaints fButtonPaints;
  735. Button fCubicButton;
  736. Button fConicButton;
  737. Button fQuadButton;
  738. Button fLineButton;
  739. Button fAddButton;
  740. Button fDeleteButton;
  741. Button fFillButton;
  742. Button fSkeletonButton;
  743. Button fFilterButton;
  744. Button fBisectButton;
  745. Button fJoinButton;
  746. Button fInOutButton;
  747. SkTArray<Stroke> fStrokes;
  748. std::unique_ptr<PathUndo> fUndo;
  749. int fActivePt;
  750. int fActiveVerb;
  751. bool fHandlePathMove;
  752. bool fShowLegend;
  753. bool fHideAll;
  754. const int kHitToleranace = 25;
  755. public:
  756. AAGeometryView()
  757. : fResControl("error", 0, 10)
  758. , fWeightControl("weight", 0, 5)
  759. , fWidthControl("width", FLT_EPSILON, 100)
  760. , fFilterControl("filter", 0, 255)
  761. , fCubicButton('C')
  762. , fConicButton('K')
  763. , fQuadButton('Q')
  764. , fLineButton('L')
  765. , fAddButton('+')
  766. , fDeleteButton('x')
  767. , fFillButton('p')
  768. , fSkeletonButton('s')
  769. , fFilterButton('f', 3)
  770. , fBisectButton('b')
  771. , fJoinButton('j')
  772. , fInOutButton('|')
  773. , fActivePt(-1)
  774. , fActiveVerb(-1)
  775. , fHandlePathMove(true)
  776. , fShowLegend(false)
  777. , fHideAll(false)
  778. {
  779. fCoveragePaint.setAntiAlias(true);
  780. fCoveragePaint.setColor(SK_ColorBLUE);
  781. SkPaint strokePaint;
  782. strokePaint.setAntiAlias(true);
  783. strokePaint.setStyle(SkPaint::kStroke_Style);
  784. fPointPaint = strokePaint;
  785. fPointPaint.setColor(0x99ee3300);
  786. fSkeletonPaint = strokePaint;
  787. fSkeletonPaint.setColor(SK_ColorRED);
  788. fLightSkeletonPaint = fSkeletonPaint;
  789. fLightSkeletonPaint.setColor(0xFFFF7f7f);
  790. fActivePaint = strokePaint;
  791. fActivePaint.setColor(0x99ee3300);
  792. fActivePaint.setStrokeWidth(5);
  793. fComplexPaint = fActivePaint;
  794. fComplexPaint.setColor(SK_ColorBLUE);
  795. fLegendLeftFont.setSize(13);
  796. fLegendRightFont = fLegendLeftFont;
  797. construct_path(fPath);
  798. fFillButton.fVisible = fSkeletonButton.fVisible = fFilterButton.fVisible
  799. = fBisectButton.fVisible = fJoinButton.fVisible = fInOutButton.fVisible = true;
  800. fSkeletonButton.setEnabled(true);
  801. fInOutButton.setEnabled(true);
  802. fJoinButton.setEnabled(true);
  803. fFilterControl.fValLo = 120;
  804. fFilterControl.fValHi = 141;
  805. fFilterControl.fVisible = fFilterButton.fState == 2;
  806. fResControl.fValLo = 5;
  807. fResControl.fVisible = true;
  808. fWidthControl.fValLo = 50;
  809. fWidthControl.fVisible = true;
  810. init_controlList();
  811. init_buttonList();
  812. }
  813. ~AAGeometryView() override {
  814. // Free linked list without deep recursion.
  815. std::unique_ptr<PathUndo> undo = std::move(fUndo);
  816. while (undo) {
  817. undo = std::move(undo->fNext);
  818. }
  819. }
  820. bool constructPath() {
  821. construct_path(fPath);
  822. return true;
  823. }
  824. void savePath(InputState state) {
  825. if (state != InputState::kDown) {
  826. return;
  827. }
  828. if (fUndo && fUndo->fPath == fPath) {
  829. return;
  830. }
  831. std::unique_ptr<PathUndo> undo(new PathUndo);
  832. undo->fPath = fPath;
  833. undo->fNext = std::move(fUndo);
  834. fUndo = std::move(undo);
  835. }
  836. bool undo() {
  837. if (!fUndo) {
  838. return false;
  839. }
  840. fPath = std::move(fUndo->fPath);
  841. fUndo = std::move(fUndo->fNext);
  842. validatePath();
  843. return true;
  844. }
  845. void validatePath() {}
  846. void set_controlList(int index, UniControl* control, MyClick::ControlType type) {
  847. kControlList[index].fControl = control;
  848. kControlList[index].fControlType = type;
  849. }
  850. #define SET_CONTROL(Name) set_controlList(index++, &f##Name##Control, \
  851. MyClick::k##Name##Control)
  852. bool hideAll() {
  853. fHideAll ^= true;
  854. return true;
  855. }
  856. void init_controlList() {
  857. int index = 0;
  858. SET_CONTROL(Width);
  859. SET_CONTROL(Res);
  860. SET_CONTROL(Filter);
  861. SET_CONTROL(Weight);
  862. }
  863. #undef SET_CONTROL
  864. void set_buttonList(int index, Button* button, MyClick::ControlType type) {
  865. kButtonList[index].fButton = button;
  866. kButtonList[index].fButtonType = type;
  867. }
  868. #define SET_BUTTON(Name) set_buttonList(index++, &f##Name##Button, \
  869. MyClick::k##Name##Button)
  870. void init_buttonList() {
  871. int index = 0;
  872. SET_BUTTON(Fill);
  873. SET_BUTTON(Skeleton);
  874. SET_BUTTON(Filter);
  875. SET_BUTTON(Bisect);
  876. SET_BUTTON(Join);
  877. SET_BUTTON(InOut);
  878. SET_BUTTON(Cubic);
  879. SET_BUTTON(Conic);
  880. SET_BUTTON(Quad);
  881. SET_BUTTON(Line);
  882. SET_BUTTON(Add);
  883. SET_BUTTON(Delete);
  884. }
  885. #undef SET_BUTTON
  886. SkString name() override { return SkString("AAGeometry"); }
  887. bool onChar(SkUnichar) override;
  888. void onSizeChange() override {
  889. setControlButtonsPos();
  890. this->INHERITED::onSizeChange();
  891. }
  892. bool pathDump() {
  893. fPath.dump();
  894. return true;
  895. }
  896. bool scaleDown() {
  897. SkMatrix matrix;
  898. SkRect bounds = fPath.getBounds();
  899. matrix.setScale(1.f / 1.5f, 1.f / 1.5f, bounds.centerX(), bounds.centerY());
  900. fPath.transform(matrix);
  901. validatePath();
  902. return true;
  903. }
  904. bool scaleToFit() {
  905. SkMatrix matrix;
  906. SkRect bounds = fPath.getBounds();
  907. SkScalar scale = SkTMin(this->width() / bounds.width(), this->height() / bounds.height())
  908. * 0.8f;
  909. matrix.setScale(scale, scale, bounds.centerX(), bounds.centerY());
  910. fPath.transform(matrix);
  911. bounds = fPath.getBounds();
  912. SkScalar offsetX = (this->width() - bounds.width()) / 2 - bounds.fLeft;
  913. SkScalar offsetY = (this->height() - bounds.height()) / 2 - bounds.fTop;
  914. fPath.offset(offsetX, offsetY);
  915. validatePath();
  916. return true;
  917. }
  918. bool scaleUp() {
  919. SkMatrix matrix;
  920. SkRect bounds = fPath.getBounds();
  921. matrix.setScale(1.5f, 1.5f, bounds.centerX(), bounds.centerY());
  922. fPath.transform(matrix);
  923. validatePath();
  924. return true;
  925. }
  926. void setControlButtonsPos() {
  927. SkScalar widthOffset = this->width() - 100;
  928. for (int index = 0; index < kControlCount; ++index) {
  929. if (kControlList[index].fControl->fVisible) {
  930. kControlList[index].fControl->fBounds.setXYWH(widthOffset, 30, 30, 400);
  931. widthOffset -= 50;
  932. }
  933. }
  934. SkScalar buttonOffset = 0;
  935. for (int index = 0; index < kButtonCount; ++index) {
  936. kButtonList[index].fButton->fBounds.setXYWH(this->width() - 50,
  937. buttonOffset += 50, 30, 30);
  938. }
  939. }
  940. bool showLegend() {
  941. fShowLegend ^= true;
  942. return true;
  943. }
  944. void draw_bisect(SkCanvas* canvas, const SkVector& lastVector, const SkVector& vector,
  945. const SkPoint& pt) {
  946. SkVector lastV = lastVector;
  947. SkScalar lastLen = lastVector.length();
  948. SkVector nextV = vector;
  949. SkScalar nextLen = vector.length();
  950. if (lastLen < nextLen) {
  951. lastV.setLength(nextLen);
  952. } else {
  953. nextV.setLength(lastLen);
  954. }
  955. SkVector bisect = { (lastV.fX + nextV.fX) / 2, (lastV.fY + nextV.fY) / 2 };
  956. bisect.setLength(fWidthControl.fValLo * 2);
  957. if (fBisectButton.enabled()) {
  958. canvas->drawLine(pt, pt + bisect, fSkeletonPaint);
  959. }
  960. lastV.setLength(fWidthControl.fValLo);
  961. if (fBisectButton.enabled()) {
  962. canvas->drawLine(pt, {pt.fX - lastV.fY, pt.fY + lastV.fX}, fSkeletonPaint);
  963. }
  964. nextV.setLength(fWidthControl.fValLo);
  965. if (fBisectButton.enabled()) {
  966. canvas->drawLine(pt, {pt.fX + nextV.fY, pt.fY - nextV.fX}, fSkeletonPaint);
  967. }
  968. if (fJoinButton.enabled()) {
  969. SkScalar r = fWidthControl.fValLo;
  970. SkRect oval = { pt.fX - r, pt.fY - r, pt.fX + r, pt.fY + r};
  971. SkScalar startAngle = SkScalarATan2(lastV.fX, -lastV.fY) * 180.f / SK_ScalarPI;
  972. SkScalar endAngle = SkScalarATan2(-nextV.fX, nextV.fY) * 180.f / SK_ScalarPI;
  973. if (endAngle > startAngle) {
  974. canvas->drawArc(oval, startAngle, endAngle - startAngle, false, fSkeletonPaint);
  975. } else {
  976. canvas->drawArc(oval, startAngle, 360 - (startAngle - endAngle), false,
  977. fSkeletonPaint);
  978. }
  979. }
  980. }
  981. void draw_bisects(SkCanvas* canvas, bool activeOnly) {
  982. SkVector firstVector, lastVector, nextLast, vector;
  983. SkPoint pts[4];
  984. SkPoint firstPt = { 0, 0 }; // init to avoid warning;
  985. SkPath::Verb verb;
  986. SkPath::Iter iter(fPath, true);
  987. bool foundFirst = false;
  988. int counter = -1;
  989. while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
  990. ++counter;
  991. if (activeOnly && counter != fActiveVerb && counter - 1 != fActiveVerb
  992. && counter + 1 != fActiveVerb
  993. && (fActiveVerb != 1 || counter != fPath.countVerbs())) {
  994. continue;
  995. }
  996. switch (verb) {
  997. case SkPath::kLine_Verb:
  998. nextLast = pts[0] - pts[1];
  999. vector = pts[1] - pts[0];
  1000. break;
  1001. case SkPath::kQuad_Verb: {
  1002. nextLast = pts[1] - pts[2];
  1003. if (SkScalarNearlyZero(nextLast.length())) {
  1004. nextLast = pts[0] - pts[2];
  1005. }
  1006. vector = pts[1] - pts[0];
  1007. if (SkScalarNearlyZero(vector.length())) {
  1008. vector = pts[2] - pts[0];
  1009. }
  1010. if (!fBisectButton.enabled()) {
  1011. break;
  1012. }
  1013. SkScalar t = SkFindQuadMaxCurvature(pts);
  1014. if (0 < t && t < 1) {
  1015. SkPoint maxPt = SkEvalQuadAt(pts, t);
  1016. SkVector tangent = SkEvalQuadTangentAt(pts, t);
  1017. tangent.setLength(fWidthControl.fValLo * 2);
  1018. canvas->drawLine(maxPt, {maxPt.fX + tangent.fY, maxPt.fY - tangent.fX},
  1019. fSkeletonPaint);
  1020. }
  1021. } break;
  1022. case SkPath::kConic_Verb:
  1023. nextLast = pts[1] - pts[2];
  1024. if (SkScalarNearlyZero(nextLast.length())) {
  1025. nextLast = pts[0] - pts[2];
  1026. }
  1027. vector = pts[1] - pts[0];
  1028. if (SkScalarNearlyZero(vector.length())) {
  1029. vector = pts[2] - pts[0];
  1030. }
  1031. if (!fBisectButton.enabled()) {
  1032. break;
  1033. }
  1034. // FIXME : need max curvature or equivalent here
  1035. break;
  1036. case SkPath::kCubic_Verb: {
  1037. nextLast = pts[2] - pts[3];
  1038. if (SkScalarNearlyZero(nextLast.length())) {
  1039. nextLast = pts[1] - pts[3];
  1040. if (SkScalarNearlyZero(nextLast.length())) {
  1041. nextLast = pts[0] - pts[3];
  1042. }
  1043. }
  1044. vector = pts[0] - pts[1];
  1045. if (SkScalarNearlyZero(vector.length())) {
  1046. vector = pts[0] - pts[2];
  1047. if (SkScalarNearlyZero(vector.length())) {
  1048. vector = pts[0] - pts[3];
  1049. }
  1050. }
  1051. if (!fBisectButton.enabled()) {
  1052. break;
  1053. }
  1054. SkScalar tMax[2];
  1055. int tMaxCount = SkFindCubicMaxCurvature(pts, tMax);
  1056. for (int tIndex = 0; tIndex < tMaxCount; ++tIndex) {
  1057. if (0 >= tMax[tIndex] || tMax[tIndex] >= 1) {
  1058. continue;
  1059. }
  1060. SkPoint maxPt;
  1061. SkVector tangent;
  1062. SkEvalCubicAt(pts, tMax[tIndex], &maxPt, &tangent, nullptr);
  1063. tangent.setLength(fWidthControl.fValLo * 2);
  1064. canvas->drawLine(maxPt, {maxPt.fX + tangent.fY, maxPt.fY - tangent.fX},
  1065. fSkeletonPaint);
  1066. }
  1067. } break;
  1068. case SkPath::kClose_Verb:
  1069. if (foundFirst) {
  1070. draw_bisect(canvas, lastVector, firstVector, firstPt);
  1071. foundFirst = false;
  1072. }
  1073. break;
  1074. default:
  1075. break;
  1076. }
  1077. if (SkPath::kLine_Verb <= verb && verb <= SkPath::kCubic_Verb) {
  1078. if (!foundFirst) {
  1079. firstPt = pts[0];
  1080. firstVector = vector;
  1081. foundFirst = true;
  1082. } else {
  1083. draw_bisect(canvas, lastVector, vector, pts[0]);
  1084. }
  1085. lastVector = nextLast;
  1086. }
  1087. }
  1088. }
  1089. void draw_legend(SkCanvas* canvas);
  1090. void draw_segment(SkCanvas* canvas) {
  1091. SkPoint pts[4];
  1092. SkPath::Verb verb;
  1093. SkPath::Iter iter(fPath, true);
  1094. int counter = -1;
  1095. while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
  1096. if (++counter < fActiveVerb) {
  1097. continue;
  1098. }
  1099. switch (verb) {
  1100. case SkPath::kLine_Verb:
  1101. canvas->drawPoints(SkCanvas::kLines_PointMode, 2, pts, fActivePaint);
  1102. draw_points(canvas, pts, 2);
  1103. break;
  1104. case SkPath::kQuad_Verb: {
  1105. SkPath qPath;
  1106. qPath.moveTo(pts[0]);
  1107. qPath.quadTo(pts[1], pts[2]);
  1108. canvas->drawPath(qPath, fActivePaint);
  1109. draw_points(canvas, pts, 3);
  1110. } break;
  1111. case SkPath::kConic_Verb: {
  1112. SkPath conicPath;
  1113. conicPath.moveTo(pts[0]);
  1114. conicPath.conicTo(pts[1], pts[2], iter.conicWeight());
  1115. canvas->drawPath(conicPath, fActivePaint);
  1116. draw_points(canvas, pts, 3);
  1117. } break;
  1118. case SkPath::kCubic_Verb: {
  1119. SkScalar loopT[3];
  1120. int complex = SkDCubic::ComplexBreak(pts, loopT);
  1121. SkPath cPath;
  1122. cPath.moveTo(pts[0]);
  1123. cPath.cubicTo(pts[1], pts[2], pts[3]);
  1124. canvas->drawPath(cPath, complex ? fComplexPaint : fActivePaint);
  1125. draw_points(canvas, pts, 4);
  1126. } break;
  1127. default:
  1128. break;
  1129. }
  1130. return;
  1131. }
  1132. }
  1133. void draw_points(SkCanvas* canvas, SkPoint* points, int count) {
  1134. for (int index = 0; index < count; ++index) {
  1135. canvas->drawCircle(points[index].fX, points[index].fY, 10, fPointPaint);
  1136. }
  1137. }
  1138. int hittest_verb(SkPoint pt, SkPath::Verb* verbPtr, SkScalar* weight) {
  1139. SkIntersections i;
  1140. SkDLine hHit = {{{pt.fX - kHitToleranace, pt.fY }, {pt.fX + kHitToleranace, pt.fY}}};
  1141. SkDLine vHit = {{{pt.fX, pt.fY - kHitToleranace }, {pt.fX, pt.fY + kHitToleranace}}};
  1142. SkPoint pts[4];
  1143. SkPath::Verb verb;
  1144. SkPath::Iter iter(fPath, true);
  1145. int counter = -1;
  1146. while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
  1147. ++counter;
  1148. switch (verb) {
  1149. case SkPath::kLine_Verb: {
  1150. SkDLine line;
  1151. line.set(pts);
  1152. if (i.intersect(line, hHit) || i.intersect(line, vHit)) {
  1153. *verbPtr = verb;
  1154. *weight = 1;
  1155. return counter;
  1156. }
  1157. } break;
  1158. case SkPath::kQuad_Verb: {
  1159. SkDQuad quad;
  1160. quad.set(pts);
  1161. if (i.intersect(quad, hHit) || i.intersect(quad, vHit)) {
  1162. *verbPtr = verb;
  1163. *weight = 1;
  1164. return counter;
  1165. }
  1166. } break;
  1167. case SkPath::kConic_Verb: {
  1168. SkDConic conic;
  1169. SkScalar w = iter.conicWeight();
  1170. conic.set(pts, w);
  1171. if (i.intersect(conic, hHit) || i.intersect(conic, vHit)) {
  1172. *verbPtr = verb;
  1173. *weight = w;
  1174. return counter;
  1175. }
  1176. } break;
  1177. case SkPath::kCubic_Verb: {
  1178. SkDCubic cubic;
  1179. cubic.set(pts);
  1180. if (i.intersect(cubic, hHit) || i.intersect(cubic, vHit)) {
  1181. *verbPtr = verb;
  1182. *weight = 1;
  1183. return counter;
  1184. }
  1185. } break;
  1186. default:
  1187. break;
  1188. }
  1189. }
  1190. return -1;
  1191. }
  1192. SkScalar pt_to_line(SkPoint s, SkPoint e, int x, int y) {
  1193. SkScalar radius = fWidthControl.fValLo;
  1194. SkVector adjOpp = e - s;
  1195. SkScalar lenSq = SkPointPriv::LengthSqd(adjOpp);
  1196. SkPoint rotated = {
  1197. (y - s.fY) * adjOpp.fY + (x - s.fX) * adjOpp.fX,
  1198. (y - s.fY) * adjOpp.fX - (x - s.fX) * adjOpp.fY,
  1199. };
  1200. if (rotated.fX < 0 || rotated.fX > lenSq) {
  1201. return -radius;
  1202. }
  1203. rotated.fY /= SkScalarSqrt(lenSq);
  1204. return SkTMax(-radius, SkTMin(radius, rotated.fY));
  1205. }
  1206. // given a line, compute the interior and exterior gradient coverage
  1207. bool coverage(SkPoint s, SkPoint e, uint8_t* distanceMap, int w, int h) {
  1208. SkScalar radius = fWidthControl.fValLo;
  1209. int minX = SkTMax(0, (int) (SkTMin(s.fX, e.fX) - radius));
  1210. int minY = SkTMax(0, (int) (SkTMin(s.fY, e.fY) - radius));
  1211. int maxX = SkTMin(w, (int) (SkTMax(s.fX, e.fX) + radius) + 1);
  1212. int maxY = SkTMin(h, (int) (SkTMax(s.fY, e.fY) + radius) + 1);
  1213. for (int y = minY; y < maxY; ++y) {
  1214. for (int x = minX; x < maxX; ++x) {
  1215. SkScalar ptToLineDist = pt_to_line(s, e, x, y);
  1216. if (ptToLineDist > -radius && ptToLineDist < radius) {
  1217. SkScalar coverage = ptToLineDist / radius;
  1218. add_to_map(1 - SkScalarAbs(coverage), x, y, distanceMap, w, h);
  1219. }
  1220. SkVector ptToS = { x - s.fX, y - s.fY };
  1221. SkScalar dist = ptToS.length();
  1222. if (dist < radius) {
  1223. SkScalar coverage = dist / radius;
  1224. add_to_map(1 - SkScalarAbs(coverage), x, y, distanceMap, w, h);
  1225. }
  1226. SkVector ptToE = { x - e.fX, y - e.fY };
  1227. dist = ptToE.length();
  1228. if (dist < radius) {
  1229. SkScalar coverage = dist / radius;
  1230. add_to_map(1 - SkScalarAbs(coverage), x, y, distanceMap, w, h);
  1231. }
  1232. }
  1233. }
  1234. return true;
  1235. }
  1236. void quad_coverage(SkPoint pts[3], uint8_t* distanceMap, int w, int h) {
  1237. SkScalar dist = pts[0].Distance(pts[0], pts[2]);
  1238. if (dist < gCurveDistance) {
  1239. (void) coverage(pts[0], pts[2], distanceMap, w, h);
  1240. return;
  1241. }
  1242. SkPoint split[5];
  1243. SkChopQuadAt(pts, split, 0.5f);
  1244. quad_coverage(&split[0], distanceMap, w, h);
  1245. quad_coverage(&split[2], distanceMap, w, h);
  1246. }
  1247. void conic_coverage(SkPoint pts[3], SkScalar weight, uint8_t* distanceMap, int w, int h) {
  1248. SkScalar dist = pts[0].Distance(pts[0], pts[2]);
  1249. if (dist < gCurveDistance) {
  1250. (void) coverage(pts[0], pts[2], distanceMap, w, h);
  1251. return;
  1252. }
  1253. SkConic split[2];
  1254. SkConic conic;
  1255. conic.set(pts, weight);
  1256. if (conic.chopAt(0.5f, split)) {
  1257. conic_coverage(split[0].fPts, split[0].fW, distanceMap, w, h);
  1258. conic_coverage(split[1].fPts, split[1].fW, distanceMap, w, h);
  1259. }
  1260. }
  1261. void cubic_coverage(SkPoint pts[4], uint8_t* distanceMap, int w, int h) {
  1262. SkScalar dist = pts[0].Distance(pts[0], pts[3]);
  1263. if (dist < gCurveDistance) {
  1264. (void) coverage(pts[0], pts[3], distanceMap, w, h);
  1265. return;
  1266. }
  1267. SkPoint split[7];
  1268. SkChopCubicAt(pts, split, 0.5f);
  1269. cubic_coverage(&split[0], distanceMap, w, h);
  1270. cubic_coverage(&split[3], distanceMap, w, h);
  1271. }
  1272. void path_coverage(const SkPath& path, uint8_t* distanceMap, int w, int h) {
  1273. memset(distanceMap, 0, sizeof(distanceMap[0]) * w * h);
  1274. SkPoint pts[4];
  1275. SkPath::Verb verb;
  1276. SkPath::Iter iter(path, true);
  1277. while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
  1278. switch (verb) {
  1279. case SkPath::kLine_Verb:
  1280. (void) coverage(pts[0], pts[1], distanceMap, w, h);
  1281. break;
  1282. case SkPath::kQuad_Verb:
  1283. quad_coverage(pts, distanceMap, w, h);
  1284. break;
  1285. case SkPath::kConic_Verb:
  1286. conic_coverage(pts, iter.conicWeight(), distanceMap, w, h);
  1287. break;
  1288. case SkPath::kCubic_Verb:
  1289. cubic_coverage(pts, distanceMap, w, h);
  1290. break;
  1291. default:
  1292. break;
  1293. }
  1294. }
  1295. }
  1296. static uint8_t* set_up_dist_map(const SkImageInfo& imageInfo, SkBitmap* distMap) {
  1297. distMap->setInfo(imageInfo);
  1298. distMap->setIsVolatile(true);
  1299. SkAssertResult(distMap->tryAllocPixels());
  1300. SkASSERT((int) distMap->rowBytes() == imageInfo.width());
  1301. return distMap->getAddr8(0, 0);
  1302. }
  1303. void path_stroke(int index, SkPath* inner, SkPath* outer) {
  1304. #if 0
  1305. SkPathStroker stroker(fPath, fWidthControl.fValLo, 0,
  1306. SkPaint::kRound_Cap, SkPaint::kRound_Join, fResControl.fValLo);
  1307. SkPoint pts[4], firstPt, lastPt;
  1308. SkPath::Verb verb;
  1309. SkPath::Iter iter(fPath, true);
  1310. int counter = -1;
  1311. while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
  1312. ++counter;
  1313. switch (verb) {
  1314. case SkPath::kMove_Verb:
  1315. firstPt = pts[0];
  1316. break;
  1317. case SkPath::kLine_Verb:
  1318. if (counter == index) {
  1319. stroker.moveTo(pts[0]);
  1320. stroker.lineTo(pts[1]);
  1321. goto done;
  1322. }
  1323. lastPt = pts[1];
  1324. break;
  1325. case SkPath::kQuad_Verb:
  1326. if (counter == index) {
  1327. stroker.moveTo(pts[0]);
  1328. stroker.quadTo(pts[1], pts[2]);
  1329. goto done;
  1330. }
  1331. lastPt = pts[2];
  1332. break;
  1333. case SkPath::kConic_Verb:
  1334. if (counter == index) {
  1335. stroker.moveTo(pts[0]);
  1336. stroker.conicTo(pts[1], pts[2], iter.conicWeight());
  1337. goto done;
  1338. }
  1339. lastPt = pts[2];
  1340. break;
  1341. case SkPath::kCubic_Verb:
  1342. if (counter == index) {
  1343. stroker.moveTo(pts[0]);
  1344. stroker.cubicTo(pts[1], pts[2], pts[3]);
  1345. goto done;
  1346. }
  1347. lastPt = pts[3];
  1348. break;
  1349. case SkPath::kClose_Verb:
  1350. if (counter == index) {
  1351. stroker.moveTo(lastPt);
  1352. stroker.lineTo(firstPt);
  1353. goto done;
  1354. }
  1355. break;
  1356. case SkPath::kDone_Verb:
  1357. break;
  1358. default:
  1359. SkASSERT(0);
  1360. }
  1361. }
  1362. done:
  1363. *inner = stroker.fInner;
  1364. *outer = stroker.fOuter;
  1365. #endif
  1366. }
  1367. void draw_stroke(SkCanvas* canvas, int active) {
  1368. SkPath inner, outer;
  1369. path_stroke(active, &inner, &outer);
  1370. canvas->drawPath(inner, fSkeletonPaint);
  1371. canvas->drawPath(outer, fSkeletonPaint);
  1372. }
  1373. void gather_strokes() {
  1374. fStrokes.reset();
  1375. for (int index = 0; index < fPath.countVerbs(); ++index) {
  1376. Stroke& inner = fStrokes.push_back();
  1377. inner.reset();
  1378. inner.fInner = true;
  1379. Stroke& outer = fStrokes.push_back();
  1380. outer.reset();
  1381. outer.fInner = false;
  1382. path_stroke(index, &inner.fPath, &outer.fPath);
  1383. }
  1384. }
  1385. void trim_strokes() {
  1386. // eliminate self-itersecting loops
  1387. // trim outside edges
  1388. gather_strokes();
  1389. for (int index = 0; index < fStrokes.count(); ++index) {
  1390. SkPath& outPath = fStrokes[index].fPath;
  1391. for (int inner = 0; inner < fStrokes.count(); ++inner) {
  1392. if (index == inner) {
  1393. continue;
  1394. }
  1395. SkPath& inPath = fStrokes[inner].fPath;
  1396. if (!outPath.getBounds().intersects(inPath.getBounds())) {
  1397. continue;
  1398. }
  1399. }
  1400. }
  1401. }
  1402. void onDrawContent(SkCanvas* canvas) override {
  1403. #if 0
  1404. SkDEBUGCODE(SkDebugStrokeGlobals debugGlobals);
  1405. SkOpAA aaResult(fPath, fWidthControl.fValLo, fResControl.fValLo
  1406. SkDEBUGPARAMS(&debugGlobals));
  1407. #endif
  1408. SkPath strokePath;
  1409. // aaResult.simplify(&strokePath);
  1410. canvas->drawPath(strokePath, fSkeletonPaint);
  1411. SkRect bounds = fPath.getBounds();
  1412. SkScalar radius = fWidthControl.fValLo;
  1413. int w = (int) (bounds.fRight + radius + 1);
  1414. int h = (int) (bounds.fBottom + radius + 1);
  1415. SkImageInfo imageInfo = SkImageInfo::MakeA8(w, h);
  1416. SkBitmap distMap;
  1417. uint8_t* distanceMap = set_up_dist_map(imageInfo, &distMap);
  1418. path_coverage(fPath, distanceMap, w, h);
  1419. if (fFillButton.enabled()) {
  1420. canvas->drawPath(fPath, fCoveragePaint);
  1421. }
  1422. if (fFilterButton.fState == 2
  1423. && (0 < fFilterControl.fValLo || fFilterControl.fValHi < 255)) {
  1424. SkBitmap filteredMap;
  1425. uint8_t* filtered = set_up_dist_map(imageInfo, &filteredMap);
  1426. filter_coverage(distanceMap, sizeof(uint8_t) * w * h, (uint8_t) fFilterControl.fValLo,
  1427. (uint8_t) fFilterControl.fValHi, filtered);
  1428. canvas->drawBitmap(filteredMap, 0, 0, &fCoveragePaint);
  1429. } else if (fFilterButton.enabled()) {
  1430. canvas->drawBitmap(distMap, 0, 0, &fCoveragePaint);
  1431. }
  1432. if (fSkeletonButton.enabled()) {
  1433. canvas->drawPath(fPath, fActiveVerb >= 0 ? fLightSkeletonPaint : fSkeletonPaint);
  1434. }
  1435. if (fActiveVerb >= 0) {
  1436. draw_segment(canvas);
  1437. }
  1438. if (fBisectButton.enabled() || fJoinButton.enabled()) {
  1439. draw_bisects(canvas, fActiveVerb >= 0);
  1440. }
  1441. if (fInOutButton.enabled()) {
  1442. if (fActiveVerb >= 0) {
  1443. draw_stroke(canvas, fActiveVerb);
  1444. } else {
  1445. for (int index = 0; index < fPath.countVerbs(); ++index) {
  1446. draw_stroke(canvas, index);
  1447. }
  1448. }
  1449. }
  1450. if (fHideAll) {
  1451. return;
  1452. }
  1453. for (int index = 0; index < kControlCount; ++index) {
  1454. kControlList[index].fControl->draw(canvas, fControlPaints);
  1455. }
  1456. for (int index = 0; index < kButtonCount; ++index) {
  1457. kButtonList[index].fButton->draw(canvas, fButtonPaints);
  1458. }
  1459. if (fShowLegend) {
  1460. draw_legend(canvas);
  1461. }
  1462. #if 0
  1463. SkPaint paint;
  1464. paint.setARGB(255, 34, 31, 31);
  1465. paint.setAntiAlias(true);
  1466. SkPath path;
  1467. path.moveTo(18,439);
  1468. path.lineTo(414,439);
  1469. path.lineTo(414,702);
  1470. path.lineTo(18,702);
  1471. path.lineTo(18,439);
  1472. path.moveTo(19,701);
  1473. path.lineTo(413,701);
  1474. path.lineTo(413,440);
  1475. path.lineTo(19,440);
  1476. path.lineTo(19,701);
  1477. path.close();
  1478. canvas->drawPath(path, paint);
  1479. canvas->scale(1.0f, -1.0f);
  1480. canvas->translate(0.0f, -800.0f);
  1481. canvas->drawPath(path, paint);
  1482. #endif
  1483. }
  1484. int hittest_pt(SkPoint pt) {
  1485. for (int index = 0; index < fPath.countPoints(); ++index) {
  1486. if (SkPoint::Distance(fPath.getPoint(index), pt) <= kHitToleranace * 2) {
  1487. return index;
  1488. }
  1489. }
  1490. return -1;
  1491. }
  1492. virtual Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey modi) override {
  1493. SkPoint pt = {x, y};
  1494. int ptHit = hittest_pt(pt);
  1495. if (ptHit >= 0) {
  1496. return new MyClick(MyClick::kPtType, ptHit);
  1497. }
  1498. SkPath::Verb verb;
  1499. SkScalar weight;
  1500. int verbHit = hittest_verb(pt, &verb, &weight);
  1501. if (verbHit >= 0) {
  1502. return new MyClick(MyClick::kVerbType, verbHit, verb, weight);
  1503. }
  1504. if (!fHideAll) {
  1505. const SkRect& rectPt = SkRect::MakeXYWH(x, y, 1, 1);
  1506. for (int index = 0; index < kControlCount; ++index) {
  1507. if (kControlList[index].fControl->contains(rectPt)) {
  1508. return new MyClick(MyClick::kControlType,
  1509. kControlList[index].fControlType);
  1510. }
  1511. }
  1512. for (int index = 0; index < kButtonCount; ++index) {
  1513. if (kButtonList[index].fButton->contains(rectPt)) {
  1514. return new MyClick(MyClick::kControlType, kButtonList[index].fButtonType);
  1515. }
  1516. }
  1517. }
  1518. fLineButton.fVisible = fQuadButton.fVisible = fConicButton.fVisible
  1519. = fCubicButton.fVisible = fWeightControl.fVisible = fAddButton.fVisible
  1520. = fDeleteButton.fVisible = false;
  1521. fActiveVerb = -1;
  1522. fActivePt = -1;
  1523. if (fHandlePathMove) {
  1524. return new MyClick(MyClick::kPathType, MyClick::kPathMove);
  1525. }
  1526. return nullptr;
  1527. }
  1528. static SkScalar MapScreenYtoValue(int y, const UniControl& control) {
  1529. return SkTMin(1.f, SkTMax(0.f,
  1530. SkIntToScalar(y) - control.fBounds.fTop) / control.fBounds.height())
  1531. * (control.fMax - control.fMin) + control.fMin;
  1532. }
  1533. bool onClick(Click* click) override {
  1534. MyClick* myClick = (MyClick*) click;
  1535. switch (myClick->fType) {
  1536. case MyClick::kPtType: {
  1537. savePath(click->fState);
  1538. fActivePt = myClick->ptHit();
  1539. SkPoint pt = fPath.getPoint((int) myClick->fControl);
  1540. pt.offset(SkIntToScalar(click->fCurr.fX - click->fPrev.fX),
  1541. SkIntToScalar(click->fCurr.fY - click->fPrev.fY));
  1542. set_path_pt(fActivePt, pt, &fPath);
  1543. validatePath();
  1544. return true;
  1545. }
  1546. case MyClick::kPathType:
  1547. savePath(click->fState);
  1548. fPath.offset(SkIntToScalar(click->fCurr.fX - click->fPrev.fX),
  1549. SkIntToScalar(click->fCurr.fY - click->fPrev.fY));
  1550. validatePath();
  1551. return true;
  1552. case MyClick::kVerbType: {
  1553. fActiveVerb = myClick->verbHit();
  1554. fLineButton.fVisible = fQuadButton.fVisible = fConicButton.fVisible
  1555. = fCubicButton.fVisible = fAddButton.fVisible = fDeleteButton.fVisible
  1556. = true;
  1557. fLineButton.setEnabled(myClick->fVerb == SkPath::kLine_Verb);
  1558. fQuadButton.setEnabled(myClick->fVerb == SkPath::kQuad_Verb);
  1559. fConicButton.setEnabled(myClick->fVerb == SkPath::kConic_Verb);
  1560. fCubicButton.setEnabled(myClick->fVerb == SkPath::kCubic_Verb);
  1561. fWeightControl.fValLo = myClick->fWeight;
  1562. fWeightControl.fVisible = myClick->fVerb == SkPath::kConic_Verb;
  1563. } break;
  1564. case MyClick::kControlType: {
  1565. if (click->fState != InputState::kDown && myClick->isButton()) {
  1566. return true;
  1567. }
  1568. switch (myClick->fControl) {
  1569. case MyClick::kFilterControl: {
  1570. SkScalar val = MapScreenYtoValue(click->fCurr.fY, fFilterControl);
  1571. if (val - fFilterControl.fValLo < fFilterControl.fValHi - val) {
  1572. fFilterControl.fValLo = SkTMax(0.f, val);
  1573. } else {
  1574. fFilterControl.fValHi = SkTMin(255.f, val);
  1575. }
  1576. } break;
  1577. case MyClick::kResControl:
  1578. fResControl.fValLo = MapScreenYtoValue(click->fCurr.fY, fResControl);
  1579. break;
  1580. case MyClick::kWeightControl: {
  1581. savePath(click->fState);
  1582. SkScalar w = MapScreenYtoValue(click->fCurr.fY, fWeightControl);
  1583. set_path_weight(fActiveVerb, w, &fPath);
  1584. validatePath();
  1585. fWeightControl.fValLo = w;
  1586. } break;
  1587. case MyClick::kWidthControl:
  1588. fWidthControl.fValLo = MapScreenYtoValue(click->fCurr.fY, fWidthControl);
  1589. break;
  1590. case MyClick::kLineButton:
  1591. savePath(click->fState);
  1592. enable_verb_button(myClick->fControl);
  1593. fWeightControl.fVisible = false;
  1594. set_path_verb(fActiveVerb, SkPath::kLine_Verb, &fPath, 1);
  1595. validatePath();
  1596. break;
  1597. case MyClick::kQuadButton:
  1598. savePath(click->fState);
  1599. enable_verb_button(myClick->fControl);
  1600. fWeightControl.fVisible = false;
  1601. set_path_verb(fActiveVerb, SkPath::kQuad_Verb, &fPath, 1);
  1602. validatePath();
  1603. break;
  1604. case MyClick::kConicButton: {
  1605. savePath(click->fState);
  1606. enable_verb_button(myClick->fControl);
  1607. fWeightControl.fVisible = true;
  1608. const SkScalar defaultConicWeight = 1.f / SkScalarSqrt(2);
  1609. set_path_verb(fActiveVerb, SkPath::kConic_Verb, &fPath, defaultConicWeight);
  1610. validatePath();
  1611. fWeightControl.fValLo = get_path_weight(fActiveVerb, fPath);
  1612. } break;
  1613. case MyClick::kCubicButton:
  1614. savePath(click->fState);
  1615. enable_verb_button(myClick->fControl);
  1616. fWeightControl.fVisible = false;
  1617. set_path_verb(fActiveVerb, SkPath::kCubic_Verb, &fPath, 1);
  1618. validatePath();
  1619. break;
  1620. case MyClick::kAddButton:
  1621. savePath(click->fState);
  1622. add_path_segment(fActiveVerb, &fPath);
  1623. validatePath();
  1624. if (fWeightControl.fVisible) {
  1625. fWeightControl.fValLo = get_path_weight(fActiveVerb, fPath);
  1626. }
  1627. break;
  1628. case MyClick::kDeleteButton:
  1629. savePath(click->fState);
  1630. delete_path_segment(fActiveVerb, &fPath);
  1631. validatePath();
  1632. break;
  1633. case MyClick::kFillButton:
  1634. fFillButton.toggle();
  1635. break;
  1636. case MyClick::kSkeletonButton:
  1637. fSkeletonButton.toggle();
  1638. break;
  1639. case MyClick::kFilterButton:
  1640. fFilterButton.toggle();
  1641. fFilterControl.fVisible = fFilterButton.fState == 2;
  1642. break;
  1643. case MyClick::kBisectButton:
  1644. fBisectButton.toggle();
  1645. break;
  1646. case MyClick::kJoinButton:
  1647. fJoinButton.toggle();
  1648. break;
  1649. case MyClick::kInOutButton:
  1650. fInOutButton.toggle();
  1651. break;
  1652. default:
  1653. SkASSERT(0);
  1654. break;
  1655. }
  1656. } break;
  1657. default:
  1658. SkASSERT(0);
  1659. break;
  1660. }
  1661. setControlButtonsPos();
  1662. return true;
  1663. }
  1664. private:
  1665. typedef Sample INHERITED;
  1666. };
  1667. static struct KeyCommand {
  1668. char fKey;
  1669. char fAlternate;
  1670. const char* fDescriptionL;
  1671. const char* fDescriptionR;
  1672. bool (AAGeometryView::*fFunction)();
  1673. } kKeyCommandList[] = {
  1674. { ' ', 0, "space", "center path", &AAGeometryView::scaleToFit },
  1675. { '-', 0, "-", "zoom out", &AAGeometryView::scaleDown },
  1676. { '+', '=', "+/=", "zoom in", &AAGeometryView::scaleUp },
  1677. { 'D', 0, "D", "dump to console", &AAGeometryView::pathDump },
  1678. { 'H', 0, "H", "hide controls", &AAGeometryView::hideAll },
  1679. { 'R', 0, "R", "reset path", &AAGeometryView::constructPath },
  1680. { 'Z', 0, "Z", "undo", &AAGeometryView::undo },
  1681. { '?', 0, "?", "show legend", &AAGeometryView::showLegend },
  1682. };
  1683. const int kKeyCommandCount = (int) SK_ARRAY_COUNT(kKeyCommandList);
  1684. void AAGeometryView::draw_legend(SkCanvas* canvas) {
  1685. SkScalar bottomOffset = this->height() - 10;
  1686. for (int index = kKeyCommandCount - 1; index >= 0; --index) {
  1687. bottomOffset -= 15;
  1688. SkTextUtils::DrawString(canvas, kKeyCommandList[index].fDescriptionL, this->width() - 160, bottomOffset,
  1689. fLegendLeftFont, SkPaint());
  1690. SkTextUtils::DrawString(canvas, kKeyCommandList[index].fDescriptionR,
  1691. this->width() - 20, bottomOffset,
  1692. fLegendRightFont, SkPaint(), SkTextUtils::kRight_Align);
  1693. }
  1694. }
  1695. bool AAGeometryView::onChar(SkUnichar uni) {
  1696. for (int index = 0; index < kButtonCount; ++index) {
  1697. Button* button = kButtonList[index].fButton;
  1698. if (button->fVisible && uni == button->fLabel) {
  1699. MyClick click(MyClick::kControlType, kButtonList[index].fButtonType);
  1700. click.fState = InputState::kDown;
  1701. (void) this->onClick(&click);
  1702. return true;
  1703. }
  1704. }
  1705. for (int index = 0; index < kKeyCommandCount; ++index) {
  1706. KeyCommand& keyCommand = kKeyCommandList[index];
  1707. if (uni == keyCommand.fKey || uni == keyCommand.fAlternate) {
  1708. return (this->*keyCommand.fFunction)();
  1709. }
  1710. }
  1711. if (('A' <= uni && uni <= 'Z') || ('a' <= uni && uni <= 'z')) {
  1712. for (int index = 0; index < kButtonCount; ++index) {
  1713. Button* button = kButtonList[index].fButton;
  1714. if (button->fVisible && (uni & ~0x20) == (button->fLabel & ~0x20)) {
  1715. MyClick click(MyClick::kControlType, kButtonList[index].fButtonType);
  1716. click.fState = InputState::kDown;
  1717. (void) this->onClick(&click);
  1718. return true;
  1719. }
  1720. }
  1721. }
  1722. return false;
  1723. }
  1724. DEF_SAMPLE( return new AAGeometryView; )