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