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