| reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 1 | #include "SampleCode.h" | 
 | 2 | #include "SkView.h" | 
 | 3 | #include "SkCanvas.h" | 
 | 4 | #include "SkGradientShader.h" | 
 | 5 | #include "SkGraphics.h" | 
 | 6 | #include "SkImageDecoder.h" | 
 | 7 | #include "SkPackBits.h" | 
 | 8 | #include "SkPath.h" | 
 | 9 | #include "SkPathMeasure.h" | 
 | 10 | #include "SkRandom.h" | 
 | 11 | #include "SkRegion.h" | 
 | 12 | #include "SkShader.h" | 
 | 13 | #include "SkUtils.h" | 
| reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 14 | #include "SkColorPriv.h" | 
 | 15 | #include "SkColorFilter.h" | 
 | 16 | #include "SkTypeface.h" | 
 | 17 | #include "SkAvoidXfermode.h" | 
 | 18 |  | 
| reed@android.com | f2b98d6 | 2010-12-20 18:26:13 +0000 | [diff] [blame] | 19 | #define REPEAT_COUNT    0 | 
| reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 20 |  | 
 | 21 | static const char gText[] = "Hamburgefons"; | 
 | 22 |  | 
 | 23 | static bool gDevKern; | 
 | 24 |  | 
 | 25 | static void rand_text(char text[], SkRandom& rand, size_t count) { | 
 | 26 |     for (size_t i = 0; i < count; i++) { | 
 | 27 |         text[i] = rand.nextU() & 0x7F; | 
 | 28 |     } | 
 | 29 | } | 
 | 30 |  | 
 | 31 | static SkScalar sum_widths(const SkScalar widths[], int count) { | 
 | 32 |     SkScalar w = 0; | 
 | 33 |     for (int i = 0; i < count; i++) { | 
 | 34 |         w += widths[i]; | 
 | 35 |     } | 
 | 36 |     return w; | 
 | 37 | } | 
 | 38 |  | 
 | 39 | static void test_measure(const SkPaint& paint) { | 
 | 40 |     char        text[256]; | 
 | 41 |     SkScalar    widths[256]; | 
 | 42 |     SkRect      rects[256]; | 
 | 43 |     SkRect      bounds; | 
 | 44 |     int         count = 256; | 
 | 45 |      | 
 | 46 |     SkRandom rand; | 
 | 47 |      | 
 | 48 |     for (int i = 0; i < 100; i++) { | 
 | 49 |         rand_text(text, rand, 256); | 
 | 50 |         paint.getTextWidths(text, count, widths, NULL); | 
| reed@android.com | f2b98d6 | 2010-12-20 18:26:13 +0000 | [diff] [blame] | 51 |         SkDEBUGCODE(SkScalar tw0 = sum_widths(widths, count);) | 
| reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 52 |         paint.getTextWidths(text, count, widths, rects); | 
| reed@android.com | f2b98d6 | 2010-12-20 18:26:13 +0000 | [diff] [blame] | 53 |         SkDEBUGCODE(SkScalar tw1 = sum_widths(widths, count);) | 
| reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 54 |         SkASSERT(tw0 == tw1); | 
 | 55 |  | 
| reed@android.com | f2b98d6 | 2010-12-20 18:26:13 +0000 | [diff] [blame] | 56 |         SkDEBUGCODE(SkScalar w0 = paint.measureText(text, count, NULL);) | 
 | 57 |         SkDEBUGCODE(SkScalar w1 = paint.measureText(text, count, &bounds);) | 
| reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 58 |         SkASSERT(w0 == w1); | 
 | 59 |         SkASSERT(w0 == tw0); | 
 | 60 |          | 
 | 61 |         SkRect r = rects[0]; | 
 | 62 |         SkScalar x = 0; | 
 | 63 |         for (int j = 1; j < count; j++) { | 
 | 64 |             x += widths[j-1]; | 
 | 65 |             rects[j].offset(x, 0); | 
 | 66 |             r.join(rects[j]); | 
 | 67 |         } | 
 | 68 |         SkASSERT(r == bounds); | 
 | 69 |          | 
 | 70 |         if (r != bounds) { | 
 | 71 |             printf("flags=%x i=%d [%g %g %g %g] [%g %g %g %g]\n", | 
 | 72 |                    paint.getFlags(), i, | 
 | 73 |                    SkScalarToFloat(r.fLeft), | 
 | 74 |                    SkScalarToFloat(r.fTop), | 
 | 75 |                    SkScalarToFloat(r.fRight), | 
 | 76 |                    SkScalarToFloat(r.fBottom), | 
 | 77 |                    SkScalarToFloat(bounds.fLeft), | 
 | 78 |                    SkScalarToFloat(bounds.fTop), | 
 | 79 |                    SkScalarToFloat(bounds.fRight), | 
 | 80 |                    SkScalarToFloat(bounds.fBottom)); | 
 | 81 |         } | 
 | 82 |     } | 
 | 83 | } | 
 | 84 |  | 
 | 85 | static void test_measure() { | 
 | 86 |     SkPaint paint; | 
 | 87 |      | 
 | 88 |     for (int i = 0; i <= SkPaint::kAllFlags; i++) { | 
 | 89 |         paint.setFlags(i); | 
 | 90 |         test_measure(paint); | 
 | 91 |     } | 
 | 92 | } | 
 | 93 |  | 
 | 94 | ////////////////////////////////////////////////////////////////////////////// | 
 | 95 |  | 
 | 96 | static void test_textBounds(SkCanvas* canvas) { | 
 | 97 | //    canvas->scale(SK_Scalar1/2, SK_Scalar1/2); | 
 | 98 |      | 
 | 99 | //    canvas->rotate(SkIntToScalar(30)); | 
 | 100 |  | 
 | 101 |     gDevKern = !gDevKern; | 
 | 102 |  | 
 | 103 |     SkScalar x = SkIntToScalar(50); | 
 | 104 |     SkScalar y = SkIntToScalar(150); | 
 | 105 |     SkScalar w[100]; | 
 | 106 |     SkRect   r[100], bounds; | 
 | 107 |      | 
 | 108 |     SkPaint paint; | 
 | 109 |     paint.setTextSize(SkIntToScalar(64)); | 
 | 110 |     paint.setAntiAlias(true); | 
 | 111 |     paint.setDevKernText(gDevKern); | 
 | 112 |      | 
 | 113 |     (void)paint.measureText(gText, strlen(gText), &bounds, NULL); | 
 | 114 |     paint.setColor(SK_ColorGREEN); | 
 | 115 |     bounds.offset(x, y); | 
 | 116 |     canvas->drawRect(bounds, paint); | 
 | 117 |  | 
 | 118 |     int count = paint.getTextWidths(gText, strlen(gText), w, r); | 
 | 119 |  | 
 | 120 |     paint.setColor(SK_ColorRED); | 
 | 121 |     for (int i = 0; i < count; i++) { | 
 | 122 |         r[i].offset(x, y); | 
 | 123 |         canvas->drawRect(r[i], paint); | 
 | 124 |         x += w[i]; | 
 | 125 |     } | 
 | 126 |     x = SkIntToScalar(50); | 
 | 127 |     paint.setColor(gDevKern ? SK_ColorDKGRAY : SK_ColorBLACK); | 
 | 128 |     canvas->drawText(gText, strlen(gText), x, y, paint); | 
 | 129 | } | 
 | 130 |  | 
 | 131 | static void create_src(SkBitmap* bitmap, SkBitmap::Config config) { | 
 | 132 |     bitmap->setConfig(config, 100, 100); | 
 | 133 |     bitmap->allocPixels(); | 
 | 134 |     bitmap->eraseColor(0); | 
 | 135 |      | 
 | 136 |     SkCanvas    canvas(*bitmap); | 
 | 137 |     SkPaint     paint; | 
 | 138 |  | 
 | 139 |     paint.setAntiAlias(true); | 
 | 140 |     canvas.drawCircle(SkIntToScalar(50), SkIntToScalar(50), | 
 | 141 |                       SkIntToScalar(50), paint); | 
 | 142 | } | 
 | 143 |  | 
 | 144 | static void blur(SkBitmap* dst, const SkBitmap& src, SkScalar radius) { | 
 | 145 |     *dst = src; | 
 | 146 | } | 
 | 147 |  | 
 | 148 | static void test_bitmap_blur(SkCanvas* canvas) { | 
 | 149 |     SkBitmap    src, dst; | 
 | 150 |      | 
 | 151 |     create_src(&src, SkBitmap::kARGB_8888_Config); | 
 | 152 |     blur(&dst, src, SkIntToScalar(4)); | 
 | 153 |      | 
 | 154 |     SkPaint paint; | 
 | 155 |      | 
 | 156 |     paint.setColor(SK_ColorRED); | 
 | 157 |  | 
 | 158 |     canvas->drawBitmap(dst, SkIntToScalar(30), SkIntToScalar(60), &paint); | 
 | 159 | } | 
 | 160 |  | 
 | 161 | static SkScalar getpathlen(const SkPath& path) { | 
 | 162 |     SkPathMeasure   meas(path, false); | 
 | 163 |     return meas.getLength(); | 
 | 164 | } | 
 | 165 |  | 
 | 166 | static void test_textpathmatrix(SkCanvas* canvas) { | 
 | 167 |     SkPaint paint; | 
 | 168 |     SkPath  path; | 
 | 169 |     SkMatrix matrix; | 
 | 170 |      | 
 | 171 |     path.moveTo(SkIntToScalar(200), SkIntToScalar(300)); | 
 | 172 |     path.quadTo(SkIntToScalar(400), SkIntToScalar(100), | 
 | 173 |                 SkIntToScalar(600), SkIntToScalar(300)); | 
 | 174 |  | 
 | 175 |     paint.setAntiAlias(true); | 
 | 176 |      | 
 | 177 |     paint.setStyle(SkPaint::kStroke_Style); | 
| reed@android.com | f2b98d6 | 2010-12-20 18:26:13 +0000 | [diff] [blame] | 178 |  //   canvas->drawPath(path, paint); | 
| reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 179 |     paint.setStyle(SkPaint::kFill_Style); | 
 | 180 |     paint.setTextSize(SkIntToScalar(48)); | 
 | 181 |     paint.setTextAlign(SkPaint::kRight_Align); | 
 | 182 |      | 
| reed@android.com | f2b98d6 | 2010-12-20 18:26:13 +0000 | [diff] [blame] | 183 |     const char* text = "Reflection"; | 
| reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 184 |     size_t      len = strlen(text); | 
 | 185 |     SkScalar    pathLen = getpathlen(path); | 
 | 186 |  | 
 | 187 |     canvas->drawTextOnPath(text, len, path, NULL, paint); | 
 | 188 |      | 
 | 189 |     paint.setColor(SK_ColorRED); | 
 | 190 |     matrix.setScale(-SK_Scalar1, SK_Scalar1); | 
 | 191 |     matrix.postTranslate(pathLen, 0); | 
 | 192 |     canvas->drawTextOnPath(text, len, path, &matrix, paint); | 
 | 193 |      | 
 | 194 |     paint.setColor(SK_ColorBLUE); | 
 | 195 |     matrix.setScale(SK_Scalar1, -SK_Scalar1); | 
 | 196 |     canvas->drawTextOnPath(text, len, path, &matrix, paint); | 
 | 197 |      | 
 | 198 |     paint.setColor(SK_ColorGREEN); | 
 | 199 |     matrix.setScale(-SK_Scalar1, -SK_Scalar1); | 
 | 200 |     matrix.postTranslate(pathLen, 0); | 
 | 201 |     canvas->drawTextOnPath(text, len, path, &matrix, paint); | 
 | 202 | } | 
 | 203 |  | 
| reed@google.com | f218339 | 2011-04-22 14:10:48 +0000 | [diff] [blame] | 204 | class TextOnPathView : public SampleView { | 
| reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 205 | public: | 
 | 206 |     SkPath      fPath; | 
 | 207 |     SkScalar    fHOffset; | 
 | 208 |  | 
 | 209 | 	TextOnPathView() { | 
 | 210 |         SkRect r; | 
 | 211 |         r.set(SkIntToScalar(100), SkIntToScalar(100), | 
 | 212 |               SkIntToScalar(300), SkIntToScalar(300)); | 
 | 213 |         fPath.addOval(r); | 
| reed@android.com | f2b98d6 | 2010-12-20 18:26:13 +0000 | [diff] [blame] | 214 |         fPath.offset(SkIntToScalar(200), 0); | 
 | 215 |  | 
| reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 216 |         fHOffset = SkIntToScalar(50); | 
 | 217 |     } | 
 | 218 |  | 
 | 219 | protected: | 
 | 220 |     // overrides from SkEventSink | 
 | 221 |     virtual bool onQuery(SkEvent* evt) { | 
 | 222 |         if (SampleCode::TitleQ(*evt)) { | 
 | 223 |             SampleCode::TitleR(evt, "Text On Path"); | 
 | 224 |             return true; | 
 | 225 |         } | 
 | 226 |         return this->INHERITED::onQuery(evt); | 
 | 227 |     } | 
 | 228 |      | 
| reed@google.com | f218339 | 2011-04-22 14:10:48 +0000 | [diff] [blame] | 229 |     virtual void onDrawContent(SkCanvas* canvas) { | 
| reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 230 |         SkPaint paint; | 
 | 231 |          | 
 | 232 |         paint.setAntiAlias(true); | 
 | 233 |         paint.setTextSize(SkIntToScalar(50)); | 
 | 234 |  | 
 | 235 |         for (int j = 0; j < REPEAT_COUNT; j++) { | 
 | 236 |             SkScalar x = fHOffset; | 
 | 237 |  | 
 | 238 |             paint.setColor(SK_ColorBLACK); | 
 | 239 |             canvas->drawTextOnPathHV(gText, sizeof(gText)-1, fPath, | 
 | 240 |                                      x, paint.getTextSize()/2, paint); | 
 | 241 |  | 
 | 242 |             paint.setColor(SK_ColorRED); | 
 | 243 |             canvas->drawTextOnPathHV(gText, sizeof(gText)-1, fPath, | 
 | 244 |                                      x + SkIntToScalar(50), 0, paint); | 
 | 245 |  | 
 | 246 |             paint.setColor(SK_ColorBLUE); | 
 | 247 |             canvas->drawTextOnPathHV(gText, sizeof(gText)-1, fPath, | 
 | 248 |                          x + SkIntToScalar(100), -paint.getTextSize()/2, paint); | 
 | 249 |         } | 
 | 250 |          | 
 | 251 |         paint.setColor(SK_ColorGREEN); | 
 | 252 |         paint.setStyle(SkPaint::kStroke_Style); | 
| reed@android.com | f2b98d6 | 2010-12-20 18:26:13 +0000 | [diff] [blame] | 253 | //        canvas->drawPath(fPath, paint); | 
| reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 254 |          | 
| reed@android.com | f2b98d6 | 2010-12-20 18:26:13 +0000 | [diff] [blame] | 255 |         canvas->translate(0, SkIntToScalar(100)); | 
| reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 256 |         test_textpathmatrix(canvas); | 
| reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 257 |          | 
 | 258 |         if (REPEAT_COUNT > 1) | 
 | 259 |             this->inval(NULL); | 
 | 260 |     } | 
 | 261 |      | 
 | 262 |     virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) { | 
 | 263 |         fHints += 1; | 
 | 264 |         this->inval(NULL); | 
 | 265 |         return this->INHERITED::onFindClickHandler(x, y); | 
 | 266 |     } | 
 | 267 |      | 
 | 268 |     virtual bool onClick(Click* click) { | 
 | 269 |         return this->INHERITED::onClick(click); | 
 | 270 |     } | 
 | 271 |      | 
 | 272 | private: | 
 | 273 |     int fHints; | 
| reed@google.com | f218339 | 2011-04-22 14:10:48 +0000 | [diff] [blame] | 274 |     typedef SampleView INHERITED; | 
| reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 275 | }; | 
 | 276 |  | 
| reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 277 | ////////////////////////////////////////////////////////////////////////////// | 
 | 278 |  | 
 | 279 | static SkView* MyFactory() { | 
| reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 280 |     return new TextOnPathView; | 
 | 281 | } | 
 | 282 |  | 
 | 283 | static SkViewRegister reg(MyFactory); | 
 | 284 |  |