arithmode.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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 "gm/gm.h"
  8. #include "include/core/SkCanvas.h"
  9. #include "include/core/SkColor.h"
  10. #include "include/core/SkFont.h"
  11. #include "include/core/SkFontTypes.h"
  12. #include "include/core/SkImage.h"
  13. #include "include/core/SkImageFilter.h"
  14. #include "include/core/SkPaint.h"
  15. #include "include/core/SkPoint.h"
  16. #include "include/core/SkRect.h"
  17. #include "include/core/SkRefCnt.h"
  18. #include "include/core/SkScalar.h"
  19. #include "include/core/SkShader.h"
  20. #include "include/core/SkSize.h"
  21. #include "include/core/SkString.h"
  22. #include "include/core/SkSurface.h"
  23. #include "include/core/SkTileMode.h"
  24. #include "include/core/SkTypeface.h"
  25. #include "include/core/SkTypes.h"
  26. #include "include/effects/SkArithmeticImageFilter.h"
  27. #include "include/effects/SkGradientShader.h"
  28. #include "include/effects/SkImageSource.h"
  29. #include "tools/ToolUtils.h"
  30. #include <utility>
  31. #define WW 100
  32. #define HH 32
  33. static sk_sp<SkImage> make_src() {
  34. sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(WW, HH));
  35. SkCanvas* canvas = surface->getCanvas();
  36. SkPaint paint;
  37. SkPoint pts[] = { {0, 0}, {SkIntToScalar(WW), SkIntToScalar(HH)} };
  38. SkColor colors[] = {
  39. SK_ColorTRANSPARENT, SK_ColorGREEN, SK_ColorCYAN,
  40. SK_ColorRED, SK_ColorMAGENTA, SK_ColorWHITE,
  41. };
  42. paint.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, SK_ARRAY_COUNT(colors),
  43. SkTileMode::kClamp));
  44. canvas->drawPaint(paint);
  45. return surface->makeImageSnapshot();
  46. }
  47. static sk_sp<SkImage> make_dst() {
  48. sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(WW, HH));
  49. SkCanvas* canvas = surface->getCanvas();
  50. SkPaint paint;
  51. SkPoint pts[] = { {0, SkIntToScalar(HH)}, {SkIntToScalar(WW), 0} };
  52. SkColor colors[] = {
  53. SK_ColorBLUE, SK_ColorYELLOW, SK_ColorBLACK, SK_ColorGREEN,
  54. SK_ColorGRAY,
  55. };
  56. paint.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, SK_ARRAY_COUNT(colors),
  57. SkTileMode::kClamp));
  58. canvas->drawPaint(paint);
  59. return surface->makeImageSnapshot();
  60. }
  61. static void show_k_text(SkCanvas* canvas, SkScalar x, SkScalar y, const SkScalar k[]) {
  62. SkFont font(ToolUtils::create_portable_typeface(), 24);
  63. font.setEdging(SkFont::Edging::kAntiAlias);
  64. SkPaint paint;
  65. paint.setAntiAlias(true);
  66. for (int i = 0; i < 4; ++i) {
  67. SkString str;
  68. str.appendScalar(k[i]);
  69. SkScalar width = font.measureText(str.c_str(), str.size(), SkTextEncoding::kUTF8);
  70. canvas->drawString(str, x, y + font.getSize(), font, paint);
  71. x += width + SkIntToScalar(10);
  72. }
  73. }
  74. class ArithmodeGM : public skiagm::GM {
  75. SkString onShortName() override { return SkString("arithmode"); }
  76. SkISize onISize() override { return {640, 572}; }
  77. void onDraw(SkCanvas* canvas) override {
  78. sk_sp<SkImage> src = make_src();
  79. sk_sp<SkImage> dst = make_dst();
  80. sk_sp<SkImageFilter> srcFilter = SkImageSource::Make(src);
  81. sk_sp<SkImageFilter> dstFilter = SkImageSource::Make(dst);
  82. constexpr SkScalar one = SK_Scalar1;
  83. constexpr SkScalar K[] = {
  84. 0, 0, 0, 0,
  85. 0, 0, 0, one,
  86. 0, one, 0, 0,
  87. 0, 0, one, 0,
  88. 0, one, one, 0,
  89. 0, one, -one, 0,
  90. 0, one/2, one/2, 0,
  91. 0, one/2, one/2, one/4,
  92. 0, one/2, one/2, -one/4,
  93. one/4, one/2, one/2, 0,
  94. -one/4, one/2, one/2, 0,
  95. };
  96. const SkScalar* k = K;
  97. const SkScalar* stop = k + SK_ARRAY_COUNT(K);
  98. const SkRect rect = SkRect::MakeWH(WW, HH);
  99. SkScalar gap = SkIntToScalar(WW + 20);
  100. while (k < stop) {
  101. {
  102. SkAutoCanvasRestore acr(canvas, true);
  103. canvas->drawImage(src, 0, 0);
  104. canvas->translate(gap, 0);
  105. canvas->drawImage(dst, 0, 0);
  106. canvas->translate(gap, 0);
  107. SkPaint paint;
  108. paint.setImageFilter(SkArithmeticImageFilter::Make(k[0], k[1], k[2], k[3], true,
  109. dstFilter, srcFilter, nullptr));
  110. canvas->saveLayer(&rect, &paint);
  111. canvas->restore();
  112. canvas->translate(gap, 0);
  113. show_k_text(canvas, 0, 0, k);
  114. }
  115. k += 4;
  116. canvas->translate(0, HH + 12);
  117. }
  118. // Draw two special cases to test enforcePMColor. In these cases, we
  119. // draw the dst bitmap twice, the first time it is halved and inverted,
  120. // leading to invalid premultiplied colors. If we enforcePMColor, these
  121. // invalid values should be clamped, and will not contribute to the
  122. // second draw.
  123. for (int i = 0; i < 2; i++) {
  124. const bool enforcePMColor = (i == 0);
  125. {
  126. SkAutoCanvasRestore acr(canvas, true);
  127. canvas->translate(gap, 0);
  128. canvas->drawImage(dst, 0, 0);
  129. canvas->translate(gap, 0);
  130. sk_sp<SkImageFilter> bg =
  131. SkArithmeticImageFilter::Make(0, 0, -one / 2, 1, enforcePMColor, dstFilter,
  132. nullptr, nullptr);
  133. SkPaint p;
  134. p.setImageFilter(SkArithmeticImageFilter::Make(0, one / 2, -one, 1, true,
  135. std::move(bg), dstFilter, nullptr));
  136. canvas->saveLayer(&rect, &p);
  137. canvas->restore();
  138. canvas->translate(gap, 0);
  139. // Label
  140. SkFont font(ToolUtils::create_portable_typeface(), 24);
  141. SkString str(enforcePMColor ? "enforcePM" : "no enforcePM");
  142. canvas->drawString(str, 0, font.getSize(), font, SkPaint());
  143. }
  144. canvas->translate(0, HH + 12);
  145. }
  146. }
  147. private:
  148. typedef GM INHERITED;
  149. };
  150. ///////////////////////////////////////////////////////////////////////////////
  151. DEF_GM( return new ArithmodeGM; )