SampleRegion.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. /*
  2. * Copyright 2011 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/SkFont.h"
  10. #include "include/core/SkFontMetrics.h"
  11. #include "include/core/SkPath.h"
  12. #include "include/core/SkRegion.h"
  13. #include "include/core/SkShader.h"
  14. #include "include/effects/SkGradientShader.h"
  15. #include "samplecode/Sample.h"
  16. #include "src/utils/SkUTF.h"
  17. #include <math.h>
  18. static void test_strokerect(SkCanvas* canvas) {
  19. int width = 100;
  20. int height = 100;
  21. SkBitmap bitmap;
  22. bitmap.allocPixels(SkImageInfo::MakeA8(width*2, height*2));
  23. bitmap.eraseColor(SK_ColorTRANSPARENT);
  24. SkScalar dx = 20;
  25. SkScalar dy = 20;
  26. SkPath path;
  27. path.addRect(0.0f, 0.0f,
  28. SkIntToScalar(width), SkIntToScalar(height),
  29. SkPath::kCW_Direction);
  30. SkRect r = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
  31. SkCanvas c(bitmap);
  32. c.translate(dx, dy);
  33. SkPaint paint;
  34. paint.setStyle(SkPaint::kStroke_Style);
  35. paint.setStrokeWidth(1);
  36. // use the rect
  37. c.clear(SK_ColorTRANSPARENT);
  38. c.drawRect(r, paint);
  39. canvas->drawBitmap(bitmap, 0, 0, nullptr);
  40. // use the path
  41. c.clear(SK_ColorTRANSPARENT);
  42. c.drawPath(path, paint);
  43. canvas->drawBitmap(bitmap, SkIntToScalar(2*width), 0, nullptr);
  44. }
  45. static void drawFadingText(SkCanvas* canvas,
  46. const char* text, size_t len, SkScalar x, SkScalar y,
  47. const SkFont& font, const SkPaint& paint) {
  48. // Need a bounds for the text
  49. SkRect bounds;
  50. SkFontMetrics fm;
  51. font.getMetrics(&fm);
  52. bounds.set(x, y + fm.fTop, x + font.measureText(text, len, SkTextEncoding::kUTF8), y + fm.fBottom);
  53. // may need to outset bounds a little, to account for hinting and/or
  54. // antialiasing
  55. bounds.inset(-SkIntToScalar(2), -SkIntToScalar(2));
  56. canvas->saveLayer(&bounds, nullptr);
  57. canvas->drawSimpleText(text, len, SkTextEncoding::kUTF8, x, y, font, paint);
  58. const SkPoint pts[] = {
  59. { bounds.fLeft, y },
  60. { bounds.fRight, y }
  61. };
  62. const SkColor colors[] = { SK_ColorBLACK, SK_ColorBLACK, 0 };
  63. // pos[1] value is where we start to fade, relative to the width
  64. // of our pts[] array.
  65. const SkScalar pos[] = { 0, 0.9f, SK_Scalar1 };
  66. SkPaint p;
  67. p.setShader(SkGradientShader::MakeLinear(pts, colors, pos, 3, SkTileMode::kClamp));
  68. p.setBlendMode(SkBlendMode::kDstIn);
  69. canvas->drawRect(bounds, p);
  70. canvas->restore();
  71. }
  72. static void test_text(SkCanvas* canvas) {
  73. SkPaint paint;
  74. paint.setAntiAlias(true);
  75. SkFont font;
  76. font.setSize(20);
  77. const char* str = "Hamburgefons";
  78. size_t len = strlen(str);
  79. SkScalar x = 20;
  80. SkScalar y = 20;
  81. canvas->drawSimpleText(str, len, SkTextEncoding::kUTF8, x, y, font, paint);
  82. y += 20;
  83. const SkPoint pts[] = { { x , y },
  84. { x + font.measureText(str, len, SkTextEncoding::kUTF8), y } };
  85. const SkColor colors[] = { SK_ColorBLACK, SK_ColorBLACK, 0 };
  86. const SkScalar pos[] = { 0, 0.9f, 1 };
  87. paint.setShader(SkGradientShader::MakeLinear(pts, colors, pos,
  88. SK_ARRAY_COUNT(colors),
  89. SkTileMode::kClamp));
  90. canvas->drawSimpleText(str, len, SkTextEncoding::kUTF8, x, y, font, paint);
  91. y += 20;
  92. paint.setShader(nullptr);
  93. drawFadingText(canvas, str, len, x, y, font, paint);
  94. }
  95. static void scale_rect(SkIRect* dst, const SkIRect& src, float scale) {
  96. dst->fLeft = (int)::roundf(src.fLeft * scale);
  97. dst->fTop = (int)::roundf(src.fTop * scale);
  98. dst->fRight = (int)::roundf(src.fRight * scale);
  99. dst->fBottom = (int)::roundf(src.fBottom * scale);
  100. }
  101. static void scale_rgn(SkRegion* dst, const SkRegion& src, float scale) {
  102. SkRegion tmp;
  103. SkRegion::Iterator iter(src);
  104. for (; !iter.done(); iter.next()) {
  105. SkIRect r;
  106. scale_rect(&r, iter.rect(), scale);
  107. tmp.op(r, SkRegion::kUnion_Op);
  108. }
  109. dst->swap(tmp);
  110. }
  111. static void paint_rgn(SkCanvas* canvas, const SkRegion& rgn,
  112. const SkPaint& paint) {
  113. SkRegion scaled;
  114. scale_rgn(&scaled, rgn, 0.5f);
  115. SkRegion::Iterator iter(rgn);
  116. for (; !iter.done(); iter.next())
  117. {
  118. SkRect r;
  119. r.set(iter.rect());
  120. canvas->drawRect(r, paint);
  121. }
  122. }
  123. class RegionView : public Sample {
  124. public:
  125. RegionView() {
  126. fBase.set(100, 100, 150, 150);
  127. fRect = fBase;
  128. fRect.inset(5, 5);
  129. fRect.offset(25, 25);
  130. this->setBGColor(0xFFDDDDDD);
  131. }
  132. void build_base_rgn(SkRegion* rgn) {
  133. rgn->setRect(fBase);
  134. SkIRect r = fBase;
  135. r.offset(75, 20);
  136. rgn->op(r, SkRegion::kUnion_Op);
  137. }
  138. void build_rgn(SkRegion* rgn, SkRegion::Op op) {
  139. build_base_rgn(rgn);
  140. rgn->op(fRect, op);
  141. }
  142. protected:
  143. SkString name() override { return SkString("Regions"); }
  144. static void drawstr(SkCanvas* canvas, const char text[], const SkPoint& loc,
  145. bool hilite) {
  146. SkPaint paint;
  147. paint.setColor(hilite ? SK_ColorRED : 0x40FF0000);
  148. SkFont font;
  149. font.setSize(SkIntToScalar(20));
  150. canvas->drawSimpleText(text, strlen(text), SkTextEncoding::kUTF8, loc.fX, loc.fY, font, paint);
  151. }
  152. void drawPredicates(SkCanvas* canvas, const SkPoint pts[]) {
  153. SkRegion rgn;
  154. build_base_rgn(&rgn);
  155. drawstr(canvas, "Intersects", pts[0], rgn.intersects(fRect));
  156. drawstr(canvas, "Contains", pts[1], rgn.contains(fRect));
  157. }
  158. void drawOrig(SkCanvas* canvas, bool bg) {
  159. SkRect r;
  160. SkPaint paint;
  161. paint.setStyle(SkPaint::kStroke_Style);
  162. if (bg)
  163. paint.setColor(0xFFBBBBBB);
  164. SkRegion rgn;
  165. build_base_rgn(&rgn);
  166. paint_rgn(canvas, rgn, paint);
  167. r.set(fRect);
  168. canvas->drawRect(r, paint);
  169. }
  170. void drawRgnOped(SkCanvas* canvas, SkRegion::Op op, SkColor color) {
  171. SkRegion rgn;
  172. this->build_rgn(&rgn, op);
  173. {
  174. SkRegion tmp, tmp2(rgn);
  175. tmp = tmp2;
  176. tmp.translate(5, -3);
  177. {
  178. char buffer[1000];
  179. SkDEBUGCODE(size_t size = ) tmp.writeToMemory(nullptr);
  180. SkASSERT(size <= sizeof(buffer));
  181. SkDEBUGCODE(size_t size2 = ) tmp.writeToMemory(buffer);
  182. SkASSERT(size == size2);
  183. SkRegion tmp3;
  184. SkDEBUGCODE(size2 = ) tmp3.readFromMemory(buffer, 1000);
  185. SkASSERT(size == size2);
  186. SkASSERT(tmp3 == tmp);
  187. }
  188. rgn.translate(20, 30, &tmp);
  189. SkASSERT(rgn.isEmpty() || tmp != rgn);
  190. tmp.translate(-20, -30);
  191. SkASSERT(tmp == rgn);
  192. }
  193. this->drawOrig(canvas, true);
  194. SkPaint paint;
  195. paint.setColor((color & ~(0xFF << 24)) | (0x44 << 24));
  196. paint_rgn(canvas, rgn, paint);
  197. paint.setStyle(SkPaint::kStroke_Style);
  198. paint.setColor(color);
  199. paint_rgn(canvas, rgn, paint);
  200. }
  201. void drawPathOped(SkCanvas* canvas, SkRegion::Op op, SkColor color) {
  202. SkRegion rgn;
  203. SkPath path;
  204. this->build_rgn(&rgn, op);
  205. rgn.getBoundaryPath(&path);
  206. this->drawOrig(canvas, true);
  207. SkPaint paint;
  208. paint.setStyle(SkPaint::kFill_Style);
  209. paint.setColor((color & ~(0xFF << 24)) | (0x44 << 24));
  210. canvas->drawPath(path, paint);
  211. paint.setColor(color);
  212. paint.setStyle(SkPaint::kStroke_Style);
  213. canvas->drawPath(path, paint);
  214. }
  215. void onDrawContent(SkCanvas* canvas) override {
  216. if (false) { // avoid bit rot, suppress warning
  217. test_strokerect(canvas);
  218. return;
  219. }
  220. if (false) { // avoid bit rot, suppress warning
  221. test_text(canvas);
  222. return;
  223. }
  224. const SkPoint origins[] = {
  225. { 30*SK_Scalar1, 50*SK_Scalar1 },
  226. { 150*SK_Scalar1, 50*SK_Scalar1 },
  227. };
  228. this->drawPredicates(canvas, origins);
  229. static const struct {
  230. SkColor fColor;
  231. const char* fName;
  232. SkRegion::Op fOp;
  233. } gOps[] = {
  234. { SK_ColorBLACK, "Difference", SkRegion::kDifference_Op },
  235. { SK_ColorRED, "Intersect", SkRegion::kIntersect_Op },
  236. { 0xFF008800, "Union", SkRegion::kUnion_Op },
  237. { SK_ColorBLUE, "XOR", SkRegion::kXOR_Op }
  238. };
  239. SkFont font;
  240. font.setSize(SK_Scalar1*24);
  241. this->drawOrig(canvas, false);
  242. canvas->save();
  243. canvas->translate(SkIntToScalar(200), 0);
  244. this->drawRgnOped(canvas, SkRegion::kUnion_Op, SK_ColorBLACK);
  245. canvas->restore();
  246. canvas->translate(0, SkIntToScalar(200));
  247. for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); op++) {
  248. canvas->drawSimpleText(gOps[op].fName, strlen(gOps[op].fName), SkTextEncoding::kUTF8,
  249. SkIntToScalar(75), SkIntToScalar(50), font, SkPaint());
  250. this->drawRgnOped(canvas, gOps[op].fOp, gOps[op].fColor);
  251. canvas->save();
  252. canvas->translate(0, SkIntToScalar(200));
  253. this->drawPathOped(canvas, gOps[op].fOp, gOps[op].fColor);
  254. canvas->restore();
  255. canvas->translate(SkIntToScalar(200), 0);
  256. }
  257. }
  258. virtual Sample::Click* onFindClickHandler(SkScalar x, SkScalar y,
  259. ModifierKey modi) override {
  260. return fRect.contains(SkScalarRoundToInt(x),
  261. SkScalarRoundToInt(y)) ? new Click() : nullptr;
  262. }
  263. bool onClick(Click* click) override {
  264. fRect.offset(click->fCurr.fX - click->fPrev.fX,
  265. click->fCurr.fY - click->fPrev.fY);
  266. return true;
  267. }
  268. private:
  269. SkIRect fBase, fRect;
  270. typedef Sample INHERITED;
  271. };
  272. //////////////////////////////////////////////////////////////////////////////
  273. DEF_SAMPLE( return new RegionView(); )