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