PaintTest.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  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/SkFont.h"
  8. #include "include/core/SkMaskFilter.h"
  9. #include "include/core/SkPath.h"
  10. #include "include/core/SkTypeface.h"
  11. #include "include/effects/SkLayerDrawLooper.h"
  12. #include "include/private/SkTo.h"
  13. #include "include/utils/SkRandom.h"
  14. #include "src/core/SkAutoMalloc.h"
  15. #include "src/core/SkBlurMask.h"
  16. #include "src/core/SkPaintPriv.h"
  17. #include "src/core/SkReadBuffer.h"
  18. #include "src/core/SkWriteBuffer.h"
  19. #include "src/utils/SkUTF.h"
  20. #include "tests/Test.h"
  21. #undef ASSERT
  22. // temparary api for bicubic, just be sure we can set/clear it
  23. DEF_TEST(Paint_filterQuality, reporter) {
  24. SkPaint p0, p1;
  25. REPORTER_ASSERT(reporter, kNone_SkFilterQuality == p0.getFilterQuality());
  26. static const SkFilterQuality gQualitys[] = {
  27. kNone_SkFilterQuality,
  28. kLow_SkFilterQuality,
  29. kMedium_SkFilterQuality,
  30. kHigh_SkFilterQuality
  31. };
  32. for (size_t i = 0; i < SK_ARRAY_COUNT(gQualitys); ++i) {
  33. p0.setFilterQuality(gQualitys[i]);
  34. REPORTER_ASSERT(reporter, gQualitys[i] == p0.getFilterQuality());
  35. p1 = p0;
  36. REPORTER_ASSERT(reporter, gQualitys[i] == p1.getFilterQuality());
  37. p0.reset();
  38. REPORTER_ASSERT(reporter, kNone_SkFilterQuality == p0.getFilterQuality());
  39. }
  40. }
  41. DEF_TEST(Paint_copy, reporter) {
  42. SkPaint paint;
  43. // set a few member variables
  44. paint.setStyle(SkPaint::kStrokeAndFill_Style);
  45. paint.setStrokeWidth(SkIntToScalar(2));
  46. // set a few pointers
  47. #ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
  48. SkLayerDrawLooper::Builder looperBuilder;
  49. paint.setLooper(looperBuilder.detach());
  50. #endif
  51. paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle,
  52. SkBlurMask::ConvertRadiusToSigma(1)));
  53. // copy the paint using the copy constructor and check they are the same
  54. SkPaint copiedPaint = paint;
  55. REPORTER_ASSERT(reporter, paint.getHash() == copiedPaint.getHash());
  56. REPORTER_ASSERT(reporter, paint == copiedPaint);
  57. // copy the paint using the equal operator and check they are the same
  58. copiedPaint = paint;
  59. REPORTER_ASSERT(reporter, paint == copiedPaint);
  60. // clean the paint and check they are back to their initial states
  61. SkPaint cleanPaint;
  62. paint.reset();
  63. copiedPaint.reset();
  64. REPORTER_ASSERT(reporter, cleanPaint == paint);
  65. REPORTER_ASSERT(reporter, cleanPaint == copiedPaint);
  66. }
  67. // found and fixed for webkit: mishandling when we hit recursion limit on
  68. // mostly degenerate cubic flatness test
  69. DEF_TEST(Paint_regression_cubic, reporter) {
  70. SkPath path, stroke;
  71. SkPaint paint;
  72. path.moveTo(460.2881309415525f,
  73. 303.250847066498f);
  74. path.cubicTo(463.36378422175284f,
  75. 302.1169735073363f,
  76. 456.32239330810046f,
  77. 304.720354932878f,
  78. 453.15255460013304f,
  79. 305.788586869862f);
  80. SkRect fillR, strokeR;
  81. fillR = path.getBounds();
  82. paint.setStyle(SkPaint::kStroke_Style);
  83. paint.setStrokeWidth(SkIntToScalar(2));
  84. paint.getFillPath(path, &stroke);
  85. strokeR = stroke.getBounds();
  86. SkRect maxR = fillR;
  87. SkScalar miter = SkMaxScalar(SK_Scalar1, paint.getStrokeMiter());
  88. SkScalar inset = paint.getStrokeJoin() == SkPaint::kMiter_Join ?
  89. paint.getStrokeWidth() * miter :
  90. paint.getStrokeWidth();
  91. maxR.inset(-inset, -inset);
  92. // test that our stroke didn't explode
  93. REPORTER_ASSERT(reporter, maxR.contains(strokeR));
  94. }
  95. DEF_TEST(Paint_flattening, reporter) {
  96. const SkFilterQuality levels[] = {
  97. kNone_SkFilterQuality,
  98. kLow_SkFilterQuality,
  99. kMedium_SkFilterQuality,
  100. kHigh_SkFilterQuality,
  101. };
  102. const SkPaint::Cap caps[] = {
  103. SkPaint::kButt_Cap,
  104. SkPaint::kRound_Cap,
  105. SkPaint::kSquare_Cap,
  106. };
  107. const SkPaint::Join joins[] = {
  108. SkPaint::kMiter_Join,
  109. SkPaint::kRound_Join,
  110. SkPaint::kBevel_Join,
  111. };
  112. const SkPaint::Style styles[] = {
  113. SkPaint::kFill_Style,
  114. SkPaint::kStroke_Style,
  115. SkPaint::kStrokeAndFill_Style,
  116. };
  117. #define FOR_SETUP(index, array, setter) \
  118. for (size_t index = 0; index < SK_ARRAY_COUNT(array); ++index) { \
  119. paint.setter(array[index]);
  120. SkPaint paint;
  121. paint.setAntiAlias(true);
  122. // we don't serialize hinting or encoding -- soon to be removed from paint
  123. FOR_SETUP(i, levels, setFilterQuality)
  124. FOR_SETUP(l, caps, setStrokeCap)
  125. FOR_SETUP(m, joins, setStrokeJoin)
  126. FOR_SETUP(p, styles, setStyle)
  127. SkBinaryWriteBuffer writer;
  128. SkPaintPriv::Flatten(paint, writer);
  129. SkAutoMalloc buf(writer.bytesWritten());
  130. writer.writeToMemory(buf.get());
  131. SkReadBuffer reader(buf.get(), writer.bytesWritten());
  132. SkPaint paint2;
  133. SkPaintPriv::Unflatten(&paint2, reader, nullptr);
  134. REPORTER_ASSERT(reporter, paint2 == paint);
  135. }}}}
  136. #undef FOR_SETUP
  137. }
  138. // found and fixed for android: not initializing rect for string's of length 0
  139. DEF_TEST(Paint_regression_measureText, reporter) {
  140. SkFont font;
  141. font.setSize(12.0f);
  142. SkRect r;
  143. r.setLTRB(SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN);
  144. // test that the rect was reset
  145. font.measureText("", 0, SkTextEncoding::kUTF8, &r);
  146. REPORTER_ASSERT(reporter, r.isEmpty());
  147. }
  148. #define ASSERT(expr) REPORTER_ASSERT(r, expr)
  149. DEF_TEST(Paint_MoreFlattening, r) {
  150. SkPaint paint;
  151. paint.setColor(0x00AABBCC);
  152. paint.setBlendMode(SkBlendMode::kModulate);
  153. #ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
  154. paint.setLooper(nullptr); // Default value, ignored.
  155. #endif
  156. SkBinaryWriteBuffer writer;
  157. SkPaintPriv::Flatten(paint, writer);
  158. SkAutoMalloc buf(writer.bytesWritten());
  159. writer.writeToMemory(buf.get());
  160. SkReadBuffer reader(buf.get(), writer.bytesWritten());
  161. SkPaint other;
  162. SkPaintPriv::Unflatten(&other, reader, nullptr);
  163. ASSERT(reader.offset() == writer.bytesWritten());
  164. // No matter the encoding, these must always hold.
  165. ASSERT(other.getColor() == paint.getColor());
  166. #ifdef SK_SUPPORT_LEGACY_DRAWLOOPER
  167. ASSERT(other.getLooper() == paint.getLooper());
  168. #endif
  169. ASSERT(other.getBlendMode() == paint.getBlendMode());
  170. }
  171. DEF_TEST(Paint_getHash, r) {
  172. // Try not to inspect the actual hash values in here.
  173. // We might want to change the hash function.
  174. SkPaint paint;
  175. const uint32_t defaultHash = paint.getHash();
  176. // Check that some arbitrary field affects the hash.
  177. paint.setColor(0xFF00FF00);
  178. REPORTER_ASSERT(r, paint.getHash() != defaultHash);
  179. paint.setColor(SK_ColorBLACK); // Reset to default value.
  180. REPORTER_ASSERT(r, paint.getHash() == defaultHash);
  181. // This is part of fBitfields, the last field we hash.
  182. paint.setBlendMode(SkBlendMode::kSrc);
  183. REPORTER_ASSERT(r, paint.getHash() != defaultHash);
  184. paint.setBlendMode(SkBlendMode::kSrcOver);
  185. REPORTER_ASSERT(r, paint.getHash() == defaultHash);
  186. }
  187. #include "include/effects/SkColorMatrixFilter.h"
  188. DEF_TEST(Paint_nothingToDraw, r) {
  189. SkPaint paint;
  190. REPORTER_ASSERT(r, !paint.nothingToDraw());
  191. paint.setAlpha(0);
  192. REPORTER_ASSERT(r, paint.nothingToDraw());
  193. paint.setAlpha(0xFF);
  194. paint.setBlendMode(SkBlendMode::kDst);
  195. REPORTER_ASSERT(r, paint.nothingToDraw());
  196. paint.setAlpha(0);
  197. paint.setBlendMode(SkBlendMode::kSrcOver);
  198. SkColorMatrix cm;
  199. cm.setIdentity(); // does not change alpha
  200. paint.setColorFilter(SkColorFilters::Matrix(cm));
  201. REPORTER_ASSERT(r, paint.nothingToDraw());
  202. cm.postTranslate(0, 0, 0, 1.0f/255); // wacks alpha
  203. paint.setColorFilter(SkColorFilters::Matrix(cm));
  204. REPORTER_ASSERT(r, !paint.nothingToDraw());
  205. }
  206. DEF_TEST(Font_getpos, r) {
  207. SkFont font;
  208. const char text[] = "Hamburgefons!@#!#23425,./;'[]";
  209. int count = font.countText(text, strlen(text), SkTextEncoding::kUTF8);
  210. SkAutoTArray<uint16_t> glyphStorage(count);
  211. uint16_t* glyphs = glyphStorage.get();
  212. (void)font.textToGlyphs(text, strlen(text), SkTextEncoding::kUTF8, glyphs, count);
  213. SkAutoTArray<SkScalar> widthStorage(count);
  214. SkAutoTArray<SkScalar> xposStorage(count);
  215. SkAutoTArray<SkPoint> posStorage(count);
  216. SkScalar* widths = widthStorage.get();
  217. SkScalar* xpos = xposStorage.get();
  218. SkPoint* pos = posStorage.get();
  219. for (bool subpix : { false, true }) {
  220. font.setSubpixel(subpix);
  221. for (auto hint : { SkFontHinting::kNone, SkFontHinting::kSlight, SkFontHinting::kNormal, SkFontHinting::kFull}) {
  222. font.setHinting(hint);
  223. for (auto size : { 1.0f, 12.0f, 100.0f }) {
  224. font.setSize(size);
  225. font.getWidths(glyphs, count, widths);
  226. font.getXPos(glyphs, count, xpos, 10);
  227. font.getPos(glyphs, count, pos, {10, 20});
  228. auto nearly_eq = [](SkScalar a, SkScalar b) {
  229. return SkScalarAbs(a - b) < 0.000001f;
  230. };
  231. SkScalar x = 10;
  232. for (int i = 0; i < count; ++i) {
  233. REPORTER_ASSERT(r, nearly_eq(x, xpos[i]));
  234. REPORTER_ASSERT(r, nearly_eq(x, pos[i].fX));
  235. REPORTER_ASSERT(r, nearly_eq(20, pos[i].fY));
  236. x += widths[i];
  237. }
  238. }
  239. }
  240. }
  241. }