1e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein/* 2e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein * Copyright 2015 Google Inc. 3e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein * 4e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein * Use of this source code is governed by a BSD-style license that can be 5e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein * found in the LICENSE file. 6e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein */ 7e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein 8e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein#include "../include/core/SkCanvas.h" 9e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein#include "../include/core/SkData.h" 10e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein#include "../include/core/SkSurface.h" 11e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein#include "../include/effects/SkGradientShader.h" 12e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein#include "../include/gpu/GrContext.h" 13e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein 14e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein// These headers are just handy for writing this example file. Nothing Skia specific. 15e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein#include <cstdlib> 16e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein#include <ctime> 17e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein#include <fstream> 18e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein#include <iostream> 19e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein#include <memory> 20e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein 212409abb812aa1c26f89604382f0653f948aebfa8mtklein// These setup_gl_context() are not meant to represent good form. 222409abb812aa1c26f89604382f0653f948aebfa8mtklein// They are just quick hacks to get us going. 23e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein#if defined(__APPLE__) 24e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein #include <OpenGL/OpenGL.h> 252409abb812aa1c26f89604382f0653f948aebfa8mtklein static bool setup_gl_context() { 26e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein CGLPixelFormatAttribute attributes[] = { (CGLPixelFormatAttribute)0 }; 27e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein CGLPixelFormatObj format; 28e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein GLint npix; 29e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein CGLChoosePixelFormat(attributes, &format, &npix); 30e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein CGLContextObj context; 31e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein CGLCreateContext(format, nullptr, &context); 32e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein CGLSetCurrentContext(context); 33e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein CGLReleasePixelFormat(format); 342409abb812aa1c26f89604382f0653f948aebfa8mtklein return true; 352409abb812aa1c26f89604382f0653f948aebfa8mtklein } 362409abb812aa1c26f89604382f0653f948aebfa8mtklein#else 372409abb812aa1c26f89604382f0653f948aebfa8mtklein static bool setup_gl_context() { 382409abb812aa1c26f89604382f0653f948aebfa8mtklein return false; 39e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein } 40e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein#endif 41e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein 42e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein// Most pointers returned by Skia are derived from SkRefCnt, 43e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein// meaning we need to call ->unref() on them when done rather than delete them. 44e0f06a47522b81d9d81485bfd5c8e3333211db5amtkleintemplate <typename T> std::shared_ptr<T> adopt(T* ptr) { 45e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein return std::shared_ptr<T>(ptr, [](T* p) { p->unref(); }); 46e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein} 47e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein 48e0f06a47522b81d9d81485bfd5c8e3333211db5amtkleinstatic std::shared_ptr<SkSurface> create_raster_surface(int w, int h) { 49e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein std::cout << "Using raster surface" << std::endl; 50e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein return adopt(SkSurface::NewRasterN32Premul(w, h)); 51e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein} 52e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein 53e0f06a47522b81d9d81485bfd5c8e3333211db5amtkleinstatic std::shared_ptr<SkSurface> create_opengl_surface(int w, int h) { 54e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein std::cout << "Using opengl surface" << std::endl; 55e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein std::shared_ptr<GrContext> grContext = adopt(GrContext::Create(kOpenGL_GrBackend, 0)); 56e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein return adopt(SkSurface::NewRenderTarget(grContext.get(), 575ec26ae9bfca635ccc98283aad5deda11519d826bsalomon SkBudgeted::kNo, 58e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein SkImageInfo::MakeN32Premul(w,h))); 59e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein} 60e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein 61e0f06a47522b81d9d81485bfd5c8e3333211db5amtkleinint main(int, char**) { 622409abb812aa1c26f89604382f0653f948aebfa8mtklein bool gl_ok = setup_gl_context(); 63e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein srand(time(nullptr)); 642409abb812aa1c26f89604382f0653f948aebfa8mtklein std::shared_ptr<SkSurface> surface = (gl_ok && rand() % 2) ? create_opengl_surface(320, 240) 652409abb812aa1c26f89604382f0653f948aebfa8mtklein : create_raster_surface(320, 240); 66e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein 67e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein // Create a left-to-right green-to-purple gradient shader. 68e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein SkPoint pts[] = { {0,0}, {320,240} }; 69e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein SkColor colors[] = { 0xFF00FF00, 0xFFFF00FF }; 70e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein std::shared_ptr<SkShader> shader = adopt( 71e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein SkGradientShader::CreateLinear(pts, colors, nullptr, 2, SkShader::kRepeat_TileMode)); 72e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein 73e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein // Our text will draw with this paint: size 24, antialiased, with the shader. 74e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein SkPaint paint; 75e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein paint.setTextSize(24); 76e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein paint.setAntiAlias(true); 77e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein paint.setShader(shader.get()); 78e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein 79e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein // Draw to the surface via its SkCanvas. 80e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein SkCanvas* canvas = surface->getCanvas(); // We don't manage this pointer's lifetime. 81e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein static const char* msg = "Hello world!"; 82e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein canvas->clear(SK_ColorWHITE); 83e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein canvas->drawText(msg, strlen(msg), 90,120, paint); 84e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein 85e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein // Grab a snapshot of the surface as an immutable SkImage. 86e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein std::shared_ptr<SkImage> image = adopt(surface->newImageSnapshot()); 87e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein // Encode that image as a .png into a blob in memory. 88e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein std::shared_ptr<SkData> png = adopt(image->encode(SkImageEncoder::kPNG_Type, 100)); 89e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein 90e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein // This code is no longer Skia-specific. We just dump the .png to disk. Any way works. 91e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein static const char* path = "example.png"; 92e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein std::ofstream(path, std::ios::out | std::ios::binary) 93e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein .write((const char*)png->data(), png->size()); 94e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein std::cout << "Wrote " << path << std::endl; 95e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein 96e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein return 0; 97e0f06a47522b81d9d81485bfd5c8e3333211db5amtklein} 98