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