14f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger/* 24f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * Copyright 2011 Google Inc. 34f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * 44f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be 54f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * found in the LICENSE file. 64f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger */ 74f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 84f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#include "gm.h" 94f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#include "SkCanvas.h" 104f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#include "SkPath.h" 114f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#include "SkGradientShader.h" 124f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#include "SkTypeface.h" 134f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 144f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic SkShader* make_heatGradient(const SkPoint pts[2]) { 154f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger const SkColor colors[] = { 164f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SK_ColorBLACK, SK_ColorBLUE, SK_ColorCYAN, SK_ColorGREEN, 174f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SK_ColorYELLOW, SK_ColorRED, SK_ColorWHITE 184f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger }; 194f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger const SkColor bw[] = { SK_ColorBLACK, SK_ColorWHITE }; 204f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 214f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger return SkGradientShader::CreateLinear(pts, bw, NULL, 224f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SK_ARRAY_COUNT(bw), 234f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkShader::kClamp_TileMode); 244f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger} 254f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 264f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic bool setFont(SkPaint* paint, const char name[]) { 274f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkTypeface* tf = SkTypeface::CreateFromName(name, SkTypeface::kNormal); 284f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger if (tf) { 294f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger paint->setTypeface(tf)->unref(); 304f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger return true; 314f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } 324f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger return false; 334f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger} 344f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 354f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#ifdef SK_BUILD_FOR_MAC 364f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#import <ApplicationServices/ApplicationServices.h> 374f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#define BITMAP_INFO_RGB (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host) 384f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 394f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic CGContextRef makeCG(const SkBitmap& bm) { 404f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger if (SkBitmap::kARGB_8888_Config != bm.config() || 414f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger NULL == bm.getPixels()) { 424f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger return NULL; 434f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } 444f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB(); 454f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger CGContextRef cg = CGBitmapContextCreate(bm.getPixels(), bm.width(), bm.height(), 464f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 8, bm.rowBytes(), space, BITMAP_INFO_RGB); 474f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger CFRelease(space); 484f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 494f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger CGContextSetAllowsFontSubpixelQuantization(cg, false); 504f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger CGContextSetShouldSubpixelQuantizeFonts(cg, false); 514f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 524f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger return cg; 534f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger} 544f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 554f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerextern CTFontRef SkTypeface_GetCTFontRef(const SkTypeface* face); 564f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 574f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic CGFontRef typefaceToCGFont(const SkTypeface* face) { 584f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger if (NULL == face) { 594f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger return 0; 604f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } 614f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 624f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger CTFontRef ct = SkTypeface_GetCTFontRef(face); 634f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger return CTFontCopyGraphicsFont(ct, NULL); 644f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger} 654f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 664f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic void cgSetPaintForText(CGContextRef cg, const SkPaint& paint) { 674f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkColor c = paint.getColor(); 684f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger CGFloat rgba[] = { 694f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkColorGetB(c) / 255.0, 704f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkColorGetG(c) / 255.0, 714f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkColorGetR(c) / 255.0, 724f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkColorGetA(c) / 255.0, 734f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger }; 744f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger CGContextSetRGBFillColor(cg, rgba[0], rgba[1], rgba[2], rgba[3]); 754f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 764f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger CGContextSetTextDrawingMode(cg, kCGTextFill); 774f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger CGContextSetFont(cg, typefaceToCGFont(paint.getTypeface())); 784f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger CGContextSetFontSize(cg, SkScalarToFloat(paint.getTextSize())); 794f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 804f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger CGContextSetAllowsFontSubpixelPositioning(cg, paint.isSubpixelText()); 814f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger CGContextSetShouldSubpixelPositionFonts(cg, paint.isSubpixelText()); 824f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 834f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger CGContextSetShouldAntialias(cg, paint.isAntiAlias()); 844f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger CGContextSetShouldSmoothFonts(cg, paint.isLCDRenderText()); 854f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger} 864f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 874f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic void cgDrawText(CGContextRef cg, const void* text, size_t len, 884f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger float x, float y, const SkPaint& paint) { 894f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger if (cg) { 904f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger cgSetPaintForText(cg, paint); 914f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 924f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger uint16_t glyphs[200]; 934f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int count = paint.textToGlyphs(text, len, glyphs); 944f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 954f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger CGContextShowGlyphsAtPoint(cg, x, y, glyphs, count); 964f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } 974f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger} 984f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#endif 994f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 1004f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergernamespace skiagm { 1014f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 1024f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger/** 1034f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger Test a set of clipping problems discovered while writing blitAntiRect, 1044f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger and test all the code paths through the clipping blitters. 1054f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger Each region should show as a blue center surrounded by a 2px green 1064f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger border, with no red. 1074f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger*/ 1084f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 1094f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#define HEIGHT 480 1104f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 1114f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerclass GammaTextGM : public GM { 1124f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerpublic: 1134f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger GammaTextGM() { 1144f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 1154f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } 1164f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 1174f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerprotected: 1184f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger virtual SkString onShortName() { 1194f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger return SkString("gammatext"); 1204f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } 1214f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 1224f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger virtual SkISize onISize() { 1234f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger return make_isize(1024, HEIGHT); 1244f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } 1254f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 1264f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger static void drawGrad(SkCanvas* canvas) { 1274f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkPoint pts[] = { { 0, 0 }, { 0, HEIGHT } }; 1284f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#if 0 1294f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger const SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE }; 1304f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, 2, SkShader::kClamp_TileMode); 1314f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#else 1324f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkShader* s = make_heatGradient(pts); 1334f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#endif 1344f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 1354f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger canvas->clear(SK_ColorRED); 1364f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkPaint paint; 1374f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger paint.setShader(s)->unref(); 1384f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkRect r = { 0, 0, 1024, HEIGHT }; 1394f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger canvas->drawRect(r, paint); 1404f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } 1414f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 1424f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger virtual void onDraw(SkCanvas* canvas) { 1434f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#ifdef SK_BUILD_FOR_MAC 1444f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger CGContextRef cg = makeCG(canvas->getDevice()->accessBitmap(false)); 1454f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#endif 1464f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 1474f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger drawGrad(canvas); 1484f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 1494f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger const SkColor fg[] = { 1504f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 0xFFFFFFFF, 1514f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 0xFFFFFF00, 0xFFFF00FF, 0xFF00FFFF, 1524f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 1534f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 0xFF000000, 1544f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger }; 1554f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 1564f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger const char* text = "Hamburgefons"; 1574f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger size_t len = strlen(text); 1584f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 1594f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkPaint paint; 1604f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger setFont(&paint, "Times"); 1614f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger paint.setTextSize(SkIntToScalar(16)); 1624f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger paint.setAntiAlias(true); 1634f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger paint.setLCDRenderText(true); 1644f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 1654f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkScalar x = 10; 1664f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger for (size_t i = 0; i < SK_ARRAY_COUNT(fg); ++i) { 1674f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger paint.setColor(fg[i]); 1684f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 1694f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkScalar y = 40; 1704f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkScalar stopy = HEIGHT; 1714f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger while (y < stopy) { 1724f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#if 1 1734f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger canvas->drawText(text, len, x, y, paint); 1744f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#else 1754f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger cgDrawText(cg, text, len, x, HEIGHT - y, paint); 1764f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#endif 1774f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger y += paint.getTextSize() * 2; 1784f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } 1794f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger x += SkIntToScalar(1024) / SK_ARRAY_COUNT(fg); 1804f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } 1814f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } 1824f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 1834f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerprivate: 1844f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger typedef GM INHERITED; 1854f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}; 1864f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 1874f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger////////////////////////////////////////////////////////////////////////////// 1884f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 1894f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic GM* MyFactory(void*) { return new GammaTextGM; } 1904f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic GMRegistry reg(MyFactory); 1914f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 1924f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger} 193