1 #include "SampleCode.h" 2 #include "SkView.h" 3 #include "SkCanvas.h" 4 #include "Sk64.h" 5 #include "SkGradientShader.h" 6 #include "SkGraphics.h" 7 #include "SkImageDecoder.h" 8 #include "SkKernel33MaskFilter.h" 9 #include "SkPath.h" 10 #include "SkRandom.h" 11 #include "SkRegion.h" 12 #include "SkShader.h" 13 #include "SkUtils.h" 14 #include "SkColorPriv.h" 15 #include "SkColorFilter.h" 16 #include "SkTime.h" 17 #include "SkTypeface.h" 18 #include "SkXfermode.h" 19 20 #include "SkStream.h" 21 #include "SkXMLParser.h" 22 23 static const int gKernel[3][3] = { 24 // { -1, -2, -1 }, { -2, 12, -2 }, { -1, -2, -1 } 25 { 1, 2, 1 }, { 2, 64-12, 2 }, { 1, 2, 1 } 26 }; 27 static const int gShift = 6; 28 29 class ReduceNoise : public SkKernel33ProcMaskFilter { 30 public: 31 ReduceNoise(int percent256) : SkKernel33ProcMaskFilter(percent256) {} 32 virtual uint8_t computeValue(uint8_t* const* srcRows) 33 { 34 int c = srcRows[1][1]; 35 int min = 255, max = 0; 36 for (int i = 0; i < 3; i++) 37 for (int j = 0; j < 3; j++) 38 if (i != 1 || j != 1) 39 { 40 int v = srcRows[i][j]; 41 if (max < v) 42 max = v; 43 if (min > v) 44 min = v; 45 } 46 if (c > max) c = max; 47 // if (c < min) c = min; 48 return c; 49 } 50 virtual Factory getFactory() { return Create; } 51 private: 52 ReduceNoise(SkFlattenableReadBuffer& rb) : SkKernel33ProcMaskFilter(rb) {} 53 static SkFlattenable* Create(SkFlattenableReadBuffer& rb) { 54 return new ReduceNoise(rb); 55 } 56 }; 57 58 class Darken : public SkKernel33ProcMaskFilter { 59 public: 60 Darken(int percent256) : SkKernel33ProcMaskFilter(percent256) {} 61 virtual uint8_t computeValue(uint8_t* const* srcRows) 62 { 63 int c = srcRows[1][1]; 64 float f = c / 255.f; 65 66 if (c >= 0) { 67 f = sqrtf(f); 68 } else { 69 f *= f; 70 } 71 SkASSERT(f >= 0 && f <= 1); 72 return (int)(f * 255); 73 } 74 virtual Factory getFactory() { return Create; } 75 private: 76 Darken(SkFlattenableReadBuffer& rb) : SkKernel33ProcMaskFilter(rb) {} 77 static SkFlattenable* Create(SkFlattenableReadBuffer& rb) { 78 return new Darken(rb); 79 } 80 }; 81 82 static SkMaskFilter* makemf() { return new Darken(0x30); } 83 84 static void test_breakText() { 85 SkPaint paint; 86 const char* text = "sdfkljAKLDFJKEWkldfjlk#$%&sdfs.dsj"; 87 size_t length = strlen(text); 88 SkScalar width = paint.measureText(text, length); 89 90 SkScalar mm = 0; 91 SkScalar nn = 0; 92 for (SkScalar w = 0; w <= width; w += SK_Scalar1) { 93 SkScalar m; 94 size_t n = paint.breakText(text, length, w, &m, 95 SkPaint::kBackward_TextBufferDirection); 96 97 SkASSERT(n <= length); 98 SkASSERT(m <= width); 99 100 if (n == 0) { 101 SkASSERT(m == 0); 102 } else { 103 // now assert that we're monotonic 104 if (n == nn) { 105 SkASSERT(m == mm); 106 } else { 107 SkASSERT(n > nn); 108 SkASSERT(m > mm); 109 } 110 } 111 nn = SkIntToScalar(n); 112 mm = m; 113 } 114 115 SkDEBUGCODE(size_t length2 =) paint.breakText(text, length, width, &mm); 116 SkASSERT(length2 == length); 117 SkASSERT(mm == width); 118 } 119 120 static SkRandom gRand; 121 122 class SkPowerMode : public SkXfermode { 123 public: 124 SkPowerMode(SkScalar exponent) { this->init(exponent); } 125 126 virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count, 127 const SkAlpha aa[]); 128 129 typedef SkFlattenable* (*Factory)(SkFlattenableReadBuffer&); 130 131 // overrides for SkFlattenable 132 virtual Factory getFactory() { return Create; } 133 virtual void flatten(SkFlattenableWriteBuffer& b) { 134 // this->INHERITED::flatten(b); How can we know if this is legal???? 135 b.write32(SkScalarToFixed(fExp)); 136 } 137 138 private: 139 SkScalar fExp; // user's value 140 uint8_t fTable[256]; // cache 141 142 void init(SkScalar exponent); 143 SkPowerMode(SkFlattenableReadBuffer& b) : SkXfermode(b) { 144 // read the exponent 145 this->init(SkFixedToScalar(b.readS32())); 146 } 147 static SkFlattenable* Create(SkFlattenableReadBuffer& b) { 148 return SkNEW_ARGS(SkPowerMode, (b)); 149 } 150 151 typedef SkXfermode INHERITED; 152 }; 153 154 void SkPowerMode::init(SkScalar e) { 155 fExp = e; 156 float ee = SkScalarToFloat(e); 157 158 printf("------ %g\n", ee); 159 for (int i = 0; i < 256; i++) { 160 float x = i / 255.f; 161 // printf(" %d %g", i, x); 162 x = powf(x, ee); 163 // printf(" %g", x); 164 int xx = SkScalarRound(SkFloatToScalar(x * 255)); 165 // printf(" %d\n", xx); 166 fTable[i] = SkToU8(xx); 167 } 168 } 169 170 void SkPowerMode::xfer16(uint16_t dst[], const SkPMColor src[], int count, 171 const SkAlpha aa[]) { 172 for (int i = 0; i < count; i++) { 173 SkPMColor c = src[i]; 174 int r = SkGetPackedR32(c); 175 int g = SkGetPackedG32(c); 176 int b = SkGetPackedB32(c); 177 r = fTable[r]; 178 g = fTable[g]; 179 b = fTable[b]; 180 dst[i] = SkPack888ToRGB16(r, g, b); 181 } 182 } 183 184 static const struct { 185 const char* fName; 186 uint32_t fFlags; 187 bool fFlushCache; 188 } gHints[] = { 189 { "Linear", SkPaint::kLinearText_Flag, false }, 190 { "Normal", 0, true }, 191 { "Subpixel", SkPaint::kSubpixelText_Flag, true } 192 }; 193 194 static int count_char_points(const SkPaint& paint, char c) { 195 SkPath path; 196 197 paint.getTextPath(&c, 1, 0, 0, &path); 198 return path.getPoints(NULL, 0); 199 } 200 201 static int gOld, gNew, gCount; 202 203 static void dump(int c, int oldc, int newc) { 204 if (oldc != newc) { 205 gOld += oldc; 206 gNew += newc; 207 gCount += 1; 208 printf("char %c: old = %3d, new = %3d, reduction %g%%\n", c, oldc, newc, 100. * (oldc - newc) / oldc); 209 } 210 } 211 212 static void tab(int n) { 213 // printf("[%d] ", n); return; 214 SkASSERT(n >= 0); 215 for (int i = 0; i < n; i++) 216 printf(" "); 217 } 218 219 static void draw_rgn(const SkRegion& rgn, SkCanvas* canvas, const SkPaint& paint) { 220 SkRect r; 221 SkRegion::Iterator iter(rgn); 222 223 for (; !iter.done(); iter.next()) { 224 r.set(iter.rect()); 225 canvas->drawRect(r, paint); 226 } 227 } 228 229 static void test_break(SkCanvas* canvas, const char text[], size_t length, 230 SkScalar x, SkScalar y, const SkPaint& paint, 231 SkScalar clickX) { 232 SkPaint linePaint; 233 234 linePaint.setAntiAlias(true); 235 236 SkScalar measured; 237 238 if (paint.breakText(text, length, clickX - x, &measured, 239 SkPaint::kForward_TextBufferDirection)) { 240 linePaint.setColor(SK_ColorRED); 241 canvas->drawLine(x, y, x + measured, y, linePaint); 242 } 243 244 x += paint.measureText(text, length); 245 if (paint.breakText(text, length, x - clickX, &measured, 246 SkPaint::kBackward_TextBufferDirection)) { 247 linePaint.setColor(SK_ColorBLUE); 248 canvas->drawLine(x - measured, y, x, y, linePaint); 249 } 250 } 251 252 static void DrawTheText(SkCanvas* canvas, const char text[], size_t length, 253 SkScalar x, SkScalar y, const SkPaint& paint, 254 SkScalar clickX, SkMaskFilter* mf) { 255 SkPaint p(paint); 256 257 #if 0 258 canvas->drawText(text, length, x, y, paint); 259 #else 260 { 261 SkPoint pts[1000]; 262 SkScalar xpos = x; 263 SkASSERT(length <= SK_ARRAY_COUNT(pts)); 264 for (size_t i = 0; i < length; i++) { 265 pts[i].set(xpos, y), xpos += paint.getTextSize(); 266 } 267 canvas->drawPosText(text, length, pts, paint); 268 } 269 #endif 270 271 p.setSubpixelText(true); 272 x += SkIntToScalar(180); 273 canvas->drawText(text, length, x, y, p); 274 275 #ifdef SK_DEBUG 276 if (true) { 277 // p.setMaskFilter(mf); 278 p.setSubpixelText(false); 279 p.setLinearText(true); 280 x += SkIntToScalar(180); 281 canvas->drawText(text, length, x, y, p); 282 } 283 #endif 284 } 285 286 class TextSpeedView : public SampleView { 287 public: 288 TextSpeedView() { 289 fMF = makemf(); 290 291 fHints = 0; 292 fClickX = 0; 293 294 test_breakText(); 295 } 296 297 virtual ~TextSpeedView() { 298 SkSafeUnref(fMF); 299 } 300 301 protected: 302 // overrides from SkEventSink 303 virtual bool onQuery(SkEvent* evt) { 304 if (SampleCode::TitleQ(*evt)) { 305 SampleCode::TitleR(evt, "Text"); 306 return true; 307 } 308 return this->INHERITED::onQuery(evt); 309 } 310 311 static void make_textstrip(SkBitmap* bm) { 312 bm->setConfig(SkBitmap::kRGB_565_Config, 200, 18); 313 bm->allocPixels(); 314 bm->eraseColor(SK_ColorWHITE); 315 316 SkCanvas canvas(*bm); 317 SkPaint paint; 318 const char* s = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit"; 319 320 paint.setFlags(paint.getFlags() | SkPaint::kAntiAlias_Flag 321 | SkPaint::kDevKernText_Flag); 322 paint.setTextSize(SkIntToScalar(14)); 323 canvas.drawText(s, strlen(s), SkIntToScalar(8), SkIntToScalar(14), paint); 324 } 325 326 static void fill_pts(SkPoint pts[], size_t n, SkRandom* rand) { 327 for (size_t i = 0; i < n; i++) 328 pts[i].set(rand->nextUScalar1() * 640, rand->nextUScalar1() * 480); 329 } 330 331 virtual void onDrawContent(SkCanvas* canvas) { 332 SkAutoCanvasRestore restore(canvas, false); 333 { 334 SkRect r; 335 r.set(0, 0, SkIntToScalar(1000), SkIntToScalar(20)); 336 // canvas->saveLayer(&r, NULL, SkCanvas::kHasAlphaLayer_SaveFlag); 337 } 338 339 SkPaint paint; 340 // const uint16_t glyphs[] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19 }; 341 int index = fHints % SK_ARRAY_COUNT(gHints); 342 index = 1; 343 // const char* style = gHints[index].fName; 344 345 // canvas->translate(0, SkIntToScalar(50)); 346 347 // canvas->drawText(style, strlen(style), SkIntToScalar(20), SkIntToScalar(20), paint); 348 349 SkSafeUnref(paint.setTypeface(SkTypeface::CreateFromFile("/skimages/samplefont.ttf"))); 350 paint.setAntiAlias(true); 351 paint.setFlags(paint.getFlags() | gHints[index].fFlags); 352 353 SkRect clip; 354 clip.set(SkIntToScalar(25), SkIntToScalar(34), SkIntToScalar(88), SkIntToScalar(155)); 355 356 const char* text = "Hamburgefons"; 357 size_t length = strlen(text); 358 359 SkScalar y = SkIntToScalar(0); 360 for (int i = 9; i <= 24; i++) { 361 paint.setTextSize(SkIntToScalar(i) /*+ (gRand.nextU() & 0xFFFF)*/); 362 for (SkScalar dx = 0; dx <= SkIntToScalar(3)/4; 363 dx += SkIntToScalar(1) /* /4 */) { 364 y += paint.getFontSpacing(); 365 DrawTheText(canvas, text, length, SkIntToScalar(20) + dx, y, 366 paint, fClickX, fMF); 367 } 368 } 369 if (gHints[index].fFlushCache) { 370 // SkGraphics::SetFontCacheUsed(0); 371 } 372 } 373 374 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) { 375 fClickX = x; 376 this->inval(NULL); 377 return this->INHERITED::onFindClickHandler(x, y); 378 } 379 380 virtual bool onClick(Click* click) { 381 return this->INHERITED::onClick(click); 382 } 383 384 private: 385 int fHints; 386 SkScalar fClickX; 387 SkMaskFilter* fMF; 388 389 typedef SampleView INHERITED; 390 }; 391 392 ////////////////////////////////////////////////////////////////////////////// 393 394 static SkView* MyFactory() { return new TextSpeedView; } 395 static SkViewRegister reg(MyFactory); 396 397